master/cdev.c
changeset 2031 7a025a9e192d
parent 2030 2bd8ad8bf41f
child 2034 ca03a6737cb7
equal deleted inserted replaced
2030:2bd8ad8bf41f 2031:7a025a9e192d
  1152         )
  1152         )
  1153 {
  1153 {
  1154     ec_ioctl_slave_reg_t data;
  1154     ec_ioctl_slave_reg_t data;
  1155     ec_slave_t *slave;
  1155     ec_slave_t *slave;
  1156     uint8_t *contents;
  1156     uint8_t *contents;
  1157     ec_reg_request_t request;
  1157     ec_reg_request_t* request;
       
  1158     int retval;
  1158 
  1159 
  1159     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
  1160     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
  1160         return -EFAULT;
  1161         return -EFAULT;
  1161     }
  1162     }
  1162 
  1163 
  1167         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
  1168         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
  1168                 " for register data.\n", data.length);
  1169                 " for register data.\n", data.length);
  1169         return -ENOMEM;
  1170         return -ENOMEM;
  1170     }
  1171     }
  1171 
  1172 
  1172     if (ec_mutex_lock_interruptible(&master->master_mutex))
  1173     request = kmalloc(sizeof(*request), GFP_KERNEL);
  1173         return -EINTR;
  1174     if (!request)
  1174 
  1175         return -ENOMEM;
       
  1176     kref_init(&request->refcount);
       
  1177 
       
  1178     // init register request
       
  1179     INIT_LIST_HEAD(&request->list);
       
  1180     request->dir = EC_DIR_INPUT;
       
  1181     request->data = contents;   // now "owned" by request, see ec_master_reg_request_release
       
  1182     request->offset = data.offset;
       
  1183     request->length = data.length;
       
  1184 
       
  1185     if (ec_mutex_lock_interruptible(&master->master_mutex)) {
       
  1186         kref_put(&request->refcount,ec_master_reg_request_release);
       
  1187         return -EINTR;
       
  1188     }
  1175     if (!(slave = ec_master_find_slave(
  1189     if (!(slave = ec_master_find_slave(
  1176                     master, 0, data.slave_position))) {
  1190                     master, 0, data.slave_position))) {
  1177         ec_mutex_unlock(&master->master_mutex);
  1191         ec_mutex_unlock(&master->master_mutex);
  1178         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
  1192         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
  1179                 data.slave_position);
  1193                 data.slave_position);
  1180         return -EINVAL;
  1194         kref_put(&request->refcount,ec_master_reg_request_release);
  1181     }
  1195         return -EINVAL;
  1182 
  1196     }
  1183     // init register request
  1197 
  1184     INIT_LIST_HEAD(&request.list);
  1198     request->slave = slave;
  1185     request.slave = slave;
  1199     request->state = EC_INT_REQUEST_QUEUED;
  1186     request.dir = EC_DIR_INPUT;
       
  1187     request.data = contents;
       
  1188     request.offset = data.offset;
       
  1189     request.length = data.length;
       
  1190     request.state = EC_INT_REQUEST_QUEUED;
       
  1191 
  1200 
  1192     // schedule request.
  1201     // schedule request.
  1193     list_add_tail(&request.list, &master->reg_requests);
  1202     list_add_tail(&request->list, &master->reg_requests);
       
  1203     kref_get(&request->refcount);
  1194 
  1204 
  1195     ec_mutex_unlock(&master->master_mutex);
  1205     ec_mutex_unlock(&master->master_mutex);
  1196 
  1206 
  1197     // wait for processing through FSM
  1207     // wait for processing through FSM
  1198     if (wait_event_interruptible(master->reg_queue,
  1208     if (wait_event_interruptible(master->reg_queue,
  1199                 request.state != EC_INT_REQUEST_QUEUED)) {
  1209           ((request->state == EC_INT_REQUEST_SUCCESS) || (request->state == EC_INT_REQUEST_FAILURE)))) {
  1200         // interrupted by signal
  1210            // interrupted by signal
  1201         ec_mutex_lock(&master->master_mutex);
  1211            kref_put(&request->refcount,ec_master_reg_request_release);
  1202         if (request.state == EC_INT_REQUEST_QUEUED) {
  1212            return -EINTR;
  1203             // abort request
  1213     }
  1204             list_del(&request.list);
  1214 
  1205             ec_mutex_unlock(&master->master_mutex);
  1215     if (request->state == EC_INT_REQUEST_SUCCESS) {
  1206             kfree(contents);
  1216         if (copy_to_user((void __user *) data.data, request->data, data.length)) {
  1207             return -EINTR;
  1217             kref_put(&request->refcount,ec_master_reg_request_release);
       
  1218             return -EFAULT;
  1208         }
  1219         }
  1209         ec_mutex_unlock(&master->master_mutex);
  1220     }
  1210     }
  1221     retval = request->state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
  1211 
  1222 
  1212     // wait until master FSM has finished processing
  1223     kref_put(&request->refcount,ec_master_reg_request_release);
  1213     wait_event(master->reg_queue, request.state != EC_INT_REQUEST_BUSY);
  1224     return retval;
  1214 
       
  1215     if (request.state == EC_INT_REQUEST_SUCCESS) {
       
  1216         if (copy_to_user((void __user *) data.data, contents, data.length))
       
  1217             return -EFAULT;
       
  1218     }
       
  1219     kfree(contents);
       
  1220 
       
  1221     return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  1222 }
  1225 }
  1223 
  1226 
  1224 /*****************************************************************************/
  1227 /*****************************************************************************/
  1225 
  1228 
  1226 /** Write a slave's registers.
  1229 /** Write a slave's registers.
  1231         )
  1234         )
  1232 {
  1235 {
  1233     ec_ioctl_slave_reg_t data;
  1236     ec_ioctl_slave_reg_t data;
  1234     ec_slave_t *slave;
  1237     ec_slave_t *slave;
  1235     uint8_t *contents;
  1238     uint8_t *contents;
  1236     ec_reg_request_t request;
  1239     ec_reg_request_t* request;
       
  1240     int retval;
  1237 
  1241 
  1238     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
  1242     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
  1239         return -EFAULT;
  1243         return -EFAULT;
  1240     }
  1244     }
  1241 
  1245 
  1251     if (copy_from_user(contents, (void __user *) data.data, data.length)) {
  1255     if (copy_from_user(contents, (void __user *) data.data, data.length)) {
  1252         kfree(contents);
  1256         kfree(contents);
  1253         return -EFAULT;
  1257         return -EFAULT;
  1254     }
  1258     }
  1255 
  1259 
  1256     if (ec_mutex_lock_interruptible(&master->master_mutex))
  1260     request = kmalloc(sizeof(*request), GFP_KERNEL);
  1257         return -EINTR;
  1261     if (!request)
       
  1262         return -ENOMEM;
       
  1263     kref_init(&request->refcount);
       
  1264     // init register request
       
  1265     INIT_LIST_HEAD(&request->list);
       
  1266     request->dir = EC_DIR_OUTPUT;
       
  1267     request->data = contents; // now "owned" by request, see ec_master_reg_request_release
       
  1268     request->offset = data.offset;
       
  1269     request->length = data.length;
       
  1270 
       
  1271     if (ec_mutex_lock_interruptible(&master->master_mutex)) {
       
  1272         kref_put(&request->refcount,ec_master_reg_request_release);
       
  1273         return -EINTR;
       
  1274     }
  1258 
  1275 
  1259     if (!(slave = ec_master_find_slave(
  1276     if (!(slave = ec_master_find_slave(
  1260                     master, 0, data.slave_position))) {
  1277                     master, 0, data.slave_position))) {
  1261         ec_mutex_unlock(&master->master_mutex);
  1278         ec_mutex_unlock(&master->master_mutex);
  1262         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
  1279         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
  1263                 data.slave_position);
  1280                 data.slave_position);
  1264         kfree(contents);
  1281         kref_put(&request->refcount,ec_master_reg_request_release);
  1265         return -EINVAL;
  1282         return -EINVAL;
  1266     }
  1283     }
  1267 
  1284 
  1268     // init register request
  1285     request->slave = slave;
  1269     INIT_LIST_HEAD(&request.list);
  1286     request->state = EC_INT_REQUEST_QUEUED;
  1270     request.slave = slave;
       
  1271     request.dir = EC_DIR_OUTPUT;
       
  1272     request.data = contents;
       
  1273     request.offset = data.offset;
       
  1274     request.length = data.length;
       
  1275     request.state = EC_INT_REQUEST_QUEUED;
       
  1276 
  1287 
  1277     // schedule request.
  1288     // schedule request.
  1278     list_add_tail(&request.list, &master->reg_requests);
  1289     list_add_tail(&request->list, &master->reg_requests);
       
  1290     kref_get(&request->refcount);
  1279 
  1291 
  1280     ec_mutex_unlock(&master->master_mutex);
  1292     ec_mutex_unlock(&master->master_mutex);
  1281 
  1293 
  1282     // wait for processing through FSM
  1294     // wait for processing through FSM
  1283     if (wait_event_interruptible(master->reg_queue,
  1295     if (wait_event_interruptible(master->reg_queue,
  1284                 request.state != EC_INT_REQUEST_QUEUED)) {
  1296           ((request->state == EC_INT_REQUEST_SUCCESS) || (request->state == EC_INT_REQUEST_FAILURE)))) {
  1285         // interrupted by signal
  1297            // interrupted by signal
  1286         ec_mutex_lock(&master->master_mutex);
  1298            kref_put(&request->refcount,ec_master_reg_request_release);
  1287         if (request.state == EC_INT_REQUEST_QUEUED) {
  1299            return -EINTR;
  1288             // abort request
  1300     }
  1289             list_del(&request.list);
  1301 
  1290             ec_mutex_unlock(&master->master_mutex);
  1302     retval = request->state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
  1291             kfree(contents);
  1303     kref_put(&request->refcount,ec_master_reg_request_release);
  1292             return -EINTR;
  1304     return retval;
  1293         }
  1305 
  1294         ec_mutex_unlock(&master->master_mutex);
       
  1295     }
       
  1296 
       
  1297     // wait until master FSM has finished processing
       
  1298     wait_event(master->reg_queue, request.state != EC_INT_REQUEST_BUSY);
       
  1299 
       
  1300     kfree(contents);
       
  1301 
       
  1302     return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  1303 }
  1306 }
  1304 
  1307 
  1305 /*****************************************************************************/
  1308 /*****************************************************************************/
  1306 
  1309 
  1307 /** Get slave configuration information.
  1310 /** Get slave configuration information.