master/cdev.c
changeset 2030 2bd8ad8bf41f
parent 2029 5ef6507fc77a
child 2031 7a025a9e192d
equal deleted inserted replaced
2029:5ef6507fc77a 2030:2bd8ad8bf41f
  1070 {
  1070 {
  1071     ec_ioctl_slave_sii_t data;
  1071     ec_ioctl_slave_sii_t data;
  1072     ec_slave_t *slave;
  1072     ec_slave_t *slave;
  1073     unsigned int byte_size;
  1073     unsigned int byte_size;
  1074     uint16_t *words;
  1074     uint16_t *words;
  1075     ec_sii_write_request_t request;
  1075     ec_sii_write_request_t* request;
       
  1076     int retval;
  1076 
  1077 
  1077     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
  1078     if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
  1078         return -EFAULT;
  1079         return -EFAULT;
  1079     }
  1080     }
  1080 
  1081 
  1086         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
  1087         EC_MASTER_ERR(master, "Failed to allocate %u bytes"
  1087                 " for SII contents.\n", byte_size);
  1088                 " for SII contents.\n", byte_size);
  1088         return -ENOMEM;
  1089         return -ENOMEM;
  1089     }
  1090     }
  1090 
  1091 
       
  1092     request = kmalloc(sizeof(*request), GFP_KERNEL);
       
  1093     if (!request)
       
  1094         return -ENOMEM;
       
  1095     kref_init(&request->refcount);
       
  1096     // init SII write request
       
  1097     INIT_LIST_HEAD(&request->list);
       
  1098     request->words = words; // now "owned" by request, see ec_master_sii_write_request_release
       
  1099     request->offset = data.offset;
       
  1100     request->nwords = data.nwords;
       
  1101 
  1091     if (copy_from_user(words,
  1102     if (copy_from_user(words,
  1092                 (void __user *) data.words, byte_size)) {
  1103                 (void __user *) data.words, byte_size)) {
  1093         kfree(words);
  1104         kref_put(&request->refcount,ec_master_sii_write_request_release);
  1094         return -EFAULT;
  1105         return -EFAULT;
  1095     }
  1106     }
  1096 
  1107 
  1097     if (ec_mutex_lock_interruptible(&master->master_mutex))
  1108     if (ec_mutex_lock_interruptible(&master->master_mutex)) {
  1098         return -EINTR;
  1109         kref_put(&request->refcount,ec_master_sii_write_request_release);
  1099 
  1110         return -EINTR;
       
  1111     }
  1100     if (!(slave = ec_master_find_slave(
  1112     if (!(slave = ec_master_find_slave(
  1101                     master, 0, data.slave_position))) {
  1113                     master, 0, data.slave_position))) {
  1102         ec_mutex_unlock(&master->master_mutex);
  1114         ec_mutex_unlock(&master->master_mutex);
  1103         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
  1115         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
  1104                 data.slave_position);
  1116                 data.slave_position);
  1105         kfree(words);
  1117         kref_put(&request->refcount,ec_master_sii_write_request_release);
  1106         return -EINVAL;
  1118         return -EINVAL;
  1107     }
  1119     }
  1108 
  1120 
  1109     // init SII write request
  1121     request->slave = slave;
  1110     INIT_LIST_HEAD(&request.list);
  1122     request->state = EC_INT_REQUEST_QUEUED;
  1111     request.slave = slave;
       
  1112     request.words = words;
       
  1113     request.offset = data.offset;
       
  1114     request.nwords = data.nwords;
       
  1115     request.state = EC_INT_REQUEST_QUEUED;
       
  1116 
  1123 
  1117     // schedule SII write request.
  1124     // schedule SII write request.
  1118     list_add_tail(&request.list, &master->sii_requests);
  1125     list_add_tail(&request->list, &master->sii_requests);
       
  1126     kref_get(&request->refcount);
  1119 
  1127 
  1120     ec_mutex_unlock(&master->master_mutex);
  1128     ec_mutex_unlock(&master->master_mutex);
  1121 
  1129 
  1122     // wait for processing through FSM
  1130     // wait for processing through FSM
  1123     if (wait_event_interruptible(master->sii_queue,
  1131     if (wait_event_interruptible(master->sii_queue,
  1124                 request.state != EC_INT_REQUEST_QUEUED)) {
  1132           ((request->state == EC_INT_REQUEST_SUCCESS) || (request->state == EC_INT_REQUEST_FAILURE)))) {
  1125         // interrupted by signal
  1133            // interrupted by signal
  1126         ec_mutex_lock(&master->master_mutex);
  1134            kref_put(&request->refcount,ec_master_sii_write_request_release);
  1127         if (request.state == EC_INT_REQUEST_QUEUED) {
  1135            return -EINTR;
  1128             // abort request
  1136     }
  1129             list_del(&request.list);
  1137 
  1130             ec_mutex_unlock(&master->master_mutex);
  1138 
  1131             kfree(words);
  1139     retval = request->state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
  1132             return -EINTR;
  1140     kref_put(&request->refcount,ec_master_sii_write_request_release);
  1133         }
  1141 
  1134         ec_mutex_unlock(&master->master_mutex);
  1142     return retval;
  1135     }
       
  1136 
       
  1137     // wait until master FSM has finished processing
       
  1138     wait_event(master->sii_queue, request.state != EC_INT_REQUEST_BUSY);
       
  1139 
       
  1140     kfree(words);
       
  1141 
       
  1142     return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
       
  1143 }
  1143 }
  1144 
  1144 
  1145 /*****************************************************************************/
  1145 /*****************************************************************************/
  1146 
  1146 
  1147 /** Read a slave's registers.
  1147 /** Read a slave's registers.