00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00035
00036
00037 #include <linux/slab.h>
00038
00039 #include "master.h"
00040 #include "datagram_pair.h"
00041
00042
00043
00048 int ec_datagram_pair_init(
00049 ec_datagram_pair_t *pair,
00050 ec_domain_t *domain,
00051 uint32_t logical_offset,
00052 uint8_t *data,
00053 size_t data_size,
00054 const unsigned int used[]
00055 )
00056 {
00057 ec_device_index_t dev_idx;
00058 int ret;
00059
00060 INIT_LIST_HEAD(&pair->list);
00061 pair->domain = domain;
00062
00063 for (dev_idx = EC_DEVICE_MAIN;
00064 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
00065 ec_datagram_init(&pair->datagrams[dev_idx]);
00066 snprintf(pair->datagrams[dev_idx].name,
00067 EC_DATAGRAM_NAME_SIZE, "domain%u-%u-%s", domain->index,
00068 logical_offset, ec_device_names[dev_idx != 0]);
00069 pair->datagrams[dev_idx].device_index = dev_idx;
00070 }
00071
00072 pair->expected_working_counter = 0U;
00073
00074 for (dev_idx = EC_DEVICE_BACKUP;
00075 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
00076
00077 ret = ec_datagram_prealloc(&pair->datagrams[dev_idx], data_size);
00078 if (ret) {
00079 goto out_datagrams;
00080 }
00081 }
00082
00083 #if EC_MAX_NUM_DEVICES > 1
00084 if (!(pair->send_buffer = kmalloc(data_size, GFP_KERNEL))) {
00085 EC_MASTER_ERR(domain->master,
00086 "Failed to allocate domain send buffer!\n");
00087 ret = -ENOMEM;
00088 goto out_datagrams;
00089 }
00090 #endif
00091
00092
00093
00094
00095 if (used[EC_DIR_OUTPUT] && used[EC_DIR_INPUT]) {
00096 ec_datagram_lrw_ext(&pair->datagrams[EC_DEVICE_MAIN],
00097 logical_offset, data_size, data);
00098
00099 for (dev_idx = EC_DEVICE_BACKUP;
00100 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
00101 ec_datagram_lrw(&pair->datagrams[dev_idx],
00102 logical_offset, data_size);
00103 }
00104
00105
00106
00107 pair->expected_working_counter =
00108 used[EC_DIR_OUTPUT] * 2 + used[EC_DIR_INPUT];
00109 } else if (used[EC_DIR_OUTPUT]) {
00110 ec_datagram_lwr_ext(&pair->datagrams[EC_DEVICE_MAIN],
00111 logical_offset, data_size, data);
00112 for (dev_idx = EC_DEVICE_BACKUP;
00113 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
00114 ec_datagram_lwr(&pair->datagrams[dev_idx],
00115 logical_offset, data_size);
00116 }
00117
00118 pair->expected_working_counter = used[EC_DIR_OUTPUT];
00119 } else {
00120 ec_datagram_lrd_ext(&pair->datagrams[EC_DEVICE_MAIN],
00121 logical_offset, data_size, data);
00122 for (dev_idx = EC_DEVICE_BACKUP;
00123 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
00124 ec_datagram_lrd(&pair->datagrams[dev_idx], logical_offset,
00125 data_size);
00126 }
00127
00128 pair->expected_working_counter = used[EC_DIR_INPUT];
00129 }
00130
00131 for (dev_idx = EC_DEVICE_MAIN;
00132 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
00133 ec_datagram_zero(&pair->datagrams[dev_idx]);
00134 }
00135
00136 return 0;
00137
00138 out_datagrams:
00139 for (dev_idx = EC_DEVICE_MAIN;
00140 dev_idx < ec_master_num_devices(domain->master); dev_idx++) {
00141 ec_datagram_clear(&pair->datagrams[dev_idx]);
00142 }
00143
00144 return ret;
00145 }
00146
00147
00148
00151 void ec_datagram_pair_clear(
00152 ec_datagram_pair_t *pair
00153 )
00154 {
00155 unsigned int dev_idx;
00156
00157 for (dev_idx = EC_DEVICE_MAIN;
00158 dev_idx < ec_master_num_devices(pair->domain->master);
00159 dev_idx++) {
00160 ec_datagram_clear(&pair->datagrams[dev_idx]);
00161 }
00162
00163 #if EC_MAX_NUM_DEVICES > 1
00164 if (pair->send_buffer) {
00165 kfree(pair->send_buffer);
00166 }
00167 #endif
00168 }
00169
00170
00171
00176 uint16_t ec_datagram_pair_process(
00177 ec_datagram_pair_t *pair,
00178 uint16_t wc_sum[]
00179 )
00180 {
00181 unsigned int dev_idx;
00182 uint16_t pair_wc = 0;
00183
00184 for (dev_idx = 0; dev_idx < ec_master_num_devices(pair->domain->master);
00185 dev_idx++) {
00186 ec_datagram_t *datagram = &pair->datagrams[dev_idx];
00187
00188 #ifdef EC_RT_SYSLOG
00189 ec_datagram_output_stats(datagram);
00190 #endif
00191
00192 if (datagram->state == EC_DATAGRAM_RECEIVED) {
00193 pair_wc += datagram->working_counter;
00194 wc_sum[dev_idx] += datagram->working_counter;
00195 }
00196 }
00197
00198 return pair_wc;
00199 }
00200
00201