diff -r 668bdb89879b -r 4c0c7347a956 master/cdev.c --- a/master/cdev.c Fri Dec 16 16:29:00 2011 +0100 +++ b/master/cdev.c Tue Dec 20 11:12:04 2011 +0100 @@ -49,6 +49,12 @@ */ #define DEBUG_IOCTL 0 +/** Set to 1 to enable ioctl() latency warnings. + * + * Requires CPU timestamp counter! + */ +#define DEBUG_LATENCY 0 + /*****************************************************************************/ static int eccdev_open(struct inode *, struct file *); @@ -1723,12 +1729,12 @@ if (down_interruptible(&master->master_sem)) return -EINTR; - ec_master_set_send_interval(master,send_interval); + + ec_master_set_send_interval(master, send_interval); + up(&master->master_sem); - - return 0; -} - + return 0; +} /*****************************************************************************/ @@ -2036,7 +2042,7 @@ return -ENOENT; } - up(&master->master_sem); // FIXME + up(&master->master_sem); /** \fixme sc could be invalidated */ return ecrt_slave_config_pdo_assign_add(sc, data.sync_index, data.index); } @@ -2068,7 +2074,7 @@ return -ENOENT; } - up(&master->master_sem); // FIXME + up(&master->master_sem); /** \fixme sc could be invalidated */ ecrt_slave_config_pdo_assign_clear(sc, data.sync_index); return 0; @@ -2101,7 +2107,7 @@ return -ENOENT; } - up(&master->master_sem); // FIXME + up(&master->master_sem); /** \fixme sc could be invalidated */ return ecrt_slave_config_pdo_mapping_add(sc, data.pdo_index, data.entry_index, data.entry_subindex, data.entry_bit_length); @@ -2134,7 +2140,7 @@ return -ENOENT; } - up(&master->master_sem); // FIXME + up(&master->master_sem); /** \fixme sc could be invalidated */ ecrt_slave_config_pdo_mapping_clear(sc, data.index); return 0; @@ -2174,7 +2180,7 @@ return -ENOENT; } - up(&master->master_sem); // FIXME + up(&master->master_sem); /** \fixme sc or domain could be invalidated */ ret = ecrt_slave_config_reg_pdo_entry(sc, data.entry_index, data.entry_subindex, domain, &data.bit_position); @@ -2267,7 +2273,7 @@ return -ENOENT; } - up(&master->master_sem); // FIXME + up(&master->master_sem); /** \fixme sc could be invalidated */ if (data.complete_access) { ret = ecrt_slave_config_complete_sdo(sc, @@ -2316,7 +2322,7 @@ data.request_index++; } - up(&master->master_sem); + up(&master->master_sem); /** \fixme sc could be invalidated */ req = ecrt_slave_config_create_sdo_request_err(sc, data.sdo_index, data.sdo_subindex, data.size); @@ -2365,7 +2371,7 @@ data.voe_index++; } - up(&master->master_sem); + up(&master->master_sem); /** \fixme sc could be invalidated */ voe = ecrt_slave_config_create_voe_handler_err(sc, data.size); if (IS_ERR(voe)) @@ -2398,18 +2404,15 @@ return -EFAULT; } - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because sc will not be deleted in the + * meantime. */ if (!(sc = ec_master_get_config_const(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } ecrt_slave_config_state(sc, &state); - up(&master->master_sem); - if (copy_to_user((void __user *) data.state, &state, sizeof(state))) return -EFAULT; @@ -2460,7 +2463,7 @@ return -ENOENT; } - up(&master->master_sem); // FIXME + up(&master->master_sem); /** \fixme sc could be invalidated */ ret = ecrt_slave_config_idn( sc, ioctl.drive_no, ioctl.idn, ioctl.al_state, data, ioctl.size); @@ -2515,16 +2518,14 @@ if (unlikely(!priv->requested)) return -EPERM; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because domain will not be deleted in + * the meantime. */ if (!(domain = ec_master_find_domain(master, arg))) { - up(&master->master_sem); return -ENOENT; } ecrt_domain_process(domain); - up(&master->master_sem); return 0; } @@ -2543,16 +2544,14 @@ if (unlikely(!priv->requested)) return -EPERM; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because domain will not be deleted in + * the meantime. */ if (!(domain = ec_master_find_domain(master, arg))) { - up(&master->master_sem); return -ENOENT; } ecrt_domain_queue(domain); - up(&master->master_sem); return 0; } @@ -2577,18 +2576,15 @@ return -EFAULT; } - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because domain will not be deleted in + * the meantime. */ if (!(domain = ec_master_find_domain_const(master, data.domain_index))) { - up(&master->master_sem); return -ENOENT; } ecrt_domain_state(domain, &state); - up(&master->master_sem); - if (copy_to_user((void __user *) data.state, &state, sizeof(state))) return -EFAULT; @@ -2615,21 +2611,17 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - ecrt_sdo_request_timeout(req, data.timeout); return 0; } @@ -2654,16 +2646,14 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { - up(&master->master_sem); return -ENOENT; } @@ -2673,8 +2663,6 @@ else data.size = 0; - up(&master->master_sem); - if (copy_to_user((void __user *) arg, &data, sizeof(data))) return -EFAULT; @@ -2701,21 +2689,17 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - ecrt_sdo_request_read(req); return 0; } @@ -2746,21 +2730,17 @@ return -EINVAL; } - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - ret = ec_sdo_request_alloc(req, data.size); if (ret) return ret; @@ -2793,21 +2773,17 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - if (copy_to_user((void __user *) data.data, ecrt_sdo_request_data(req), ecrt_sdo_request_data_size(req))) return -EFAULT; @@ -2843,21 +2819,17 @@ if (get_user(vendor_type, data.vendor_type)) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor voe will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - ecrt_voe_handler_send_header(voe, vendor_id, vendor_type); return 0; } @@ -2884,23 +2856,19 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor voe will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) { - up(&master->master_sem); return -ENOENT; } ecrt_voe_handler_received_header(voe, &vendor_id, &vendor_type); - up(&master->master_sem); - if (likely(data.vendor_id)) if (put_user(vendor_id, data.vendor_id)) return -EFAULT; @@ -2932,21 +2900,17 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor voe will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - ecrt_voe_handler_read(voe); return 0; } @@ -2971,21 +2935,17 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor voe will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - ecrt_voe_handler_read_nosync(voe); return 0; } @@ -3010,21 +2970,17 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor voe will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - if (data.size) { if (data.size > ec_voe_handler_mem_size(voe)) return -EOVERFLOW; @@ -3058,21 +3014,17 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor voe will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - data.state = ecrt_voe_handler_execute(voe); if (data.state == EC_REQUEST_SUCCESS && voe->dir == EC_DIR_INPUT) data.size = ecrt_voe_handler_data_size(voe); @@ -3105,21 +3057,17 @@ if (copy_from_user(&data, (void __user *) arg, sizeof(data))) return -EFAULT; - if (down_interruptible(&master->master_sem)) - return -EINTR; + /* no locking of master_sem needed, because neither sc nor voe will not be + * deleted in the meantime. */ if (!(sc = ec_master_get_config(master, data.config_index))) { - up(&master->master_sem); return -ENOENT; } if (!(voe = ec_slave_config_find_voe_handler(sc, data.voe_index))) { - up(&master->master_sem); return -ENOENT; } - up(&master->master_sem); - if (copy_to_user((void __user *) data.data, ecrt_voe_handler_data(voe), ecrt_voe_handler_data_size(voe))) return -EFAULT; @@ -3148,8 +3096,10 @@ ec_foe_request_read(&request.req); ec_foe_request_alloc(&request.req, 10000); // FIXME - if (down_interruptible(&master->master_sem)) + if (down_interruptible(&master->master_sem)) { + ec_foe_request_clear(&request.req); return -EINTR; + } if (!(request.slave = ec_master_find_slave( master, 0, data.slave_position))) { @@ -3254,8 +3204,10 @@ request.req.data_size = data.buffer_size; ec_foe_request_write(&request.req); - if (down_interruptible(&master->master_sem)) + if (down_interruptible(&master->master_sem)) { + ec_foe_request_clear(&request.req); return -EINTR; + } if (!(request.slave = ec_master_find_slave( master, 0, data.slave_position))) { @@ -3459,8 +3411,13 @@ */ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { +#if DEBUG_LATENCY + cycles_t a = get_cycles(), b; + unsigned int t; +#endif ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data; ec_master_t *master = priv->cdev->master; + int ret; #if DEBUG_IOCTL EC_MASTER_DBG(master, 0, "ioctl(filp = 0x%p, cmd = 0x%08x (0x%02x)," @@ -3469,246 +3426,420 @@ switch (cmd) { case EC_IOCTL_MODULE: - return ec_cdev_ioctl_module(arg); + ret = ec_cdev_ioctl_module(arg); + break; case EC_IOCTL_MASTER: - return ec_cdev_ioctl_master(master, arg); + ret = ec_cdev_ioctl_master(master, arg); + break; case EC_IOCTL_SLAVE: - return ec_cdev_ioctl_slave(master, arg); + ret = ec_cdev_ioctl_slave(master, arg); + break; case EC_IOCTL_SLAVE_SYNC: - return ec_cdev_ioctl_slave_sync(master, arg); + ret = ec_cdev_ioctl_slave_sync(master, arg); + break; case EC_IOCTL_SLAVE_SYNC_PDO: - return ec_cdev_ioctl_slave_sync_pdo(master, arg); + ret = ec_cdev_ioctl_slave_sync_pdo(master, arg); + break; case EC_IOCTL_SLAVE_SYNC_PDO_ENTRY: - return ec_cdev_ioctl_slave_sync_pdo_entry(master, arg); + ret = ec_cdev_ioctl_slave_sync_pdo_entry(master, arg); + break; case EC_IOCTL_DOMAIN: - return ec_cdev_ioctl_domain(master, arg); + ret = ec_cdev_ioctl_domain(master, arg); + break; case EC_IOCTL_DOMAIN_FMMU: - return ec_cdev_ioctl_domain_fmmu(master, arg); + ret = ec_cdev_ioctl_domain_fmmu(master, arg); + break; case EC_IOCTL_DOMAIN_DATA: - return ec_cdev_ioctl_domain_data(master, arg); + ret = ec_cdev_ioctl_domain_data(master, arg); + break; case EC_IOCTL_MASTER_DEBUG: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_master_debug(master, arg); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_master_debug(master, arg); + break; case EC_IOCTL_MASTER_RESCAN: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_master_rescan(master, arg); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_master_rescan(master, arg); + break; case EC_IOCTL_SLAVE_STATE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_slave_state(master, arg); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_slave_state(master, arg); + break; case EC_IOCTL_SLAVE_SDO: - return ec_cdev_ioctl_slave_sdo(master, arg); + ret = ec_cdev_ioctl_slave_sdo(master, arg); + break; case EC_IOCTL_SLAVE_SDO_ENTRY: - return ec_cdev_ioctl_slave_sdo_entry(master, arg); + ret = ec_cdev_ioctl_slave_sdo_entry(master, arg); + break; case EC_IOCTL_SLAVE_SDO_UPLOAD: - return ec_cdev_ioctl_slave_sdo_upload(master, arg); + ret = ec_cdev_ioctl_slave_sdo_upload(master, arg); + break; case EC_IOCTL_SLAVE_SDO_DOWNLOAD: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_slave_sdo_download(master, arg); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_slave_sdo_download(master, arg); + break; case EC_IOCTL_SLAVE_SII_READ: - return ec_cdev_ioctl_slave_sii_read(master, arg); + ret = ec_cdev_ioctl_slave_sii_read(master, arg); + break; case EC_IOCTL_SLAVE_SII_WRITE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_slave_sii_write(master, arg); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_slave_sii_write(master, arg); + break; case EC_IOCTL_SLAVE_REG_READ: - return ec_cdev_ioctl_slave_reg_read(master, arg); + ret = ec_cdev_ioctl_slave_reg_read(master, arg); + break; case EC_IOCTL_SLAVE_REG_WRITE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_slave_reg_write(master, arg); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_slave_reg_write(master, arg); + break; case EC_IOCTL_SLAVE_FOE_READ: - return ec_cdev_ioctl_slave_foe_read(master, arg); + ret = ec_cdev_ioctl_slave_foe_read(master, arg); + break; case EC_IOCTL_SLAVE_FOE_WRITE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_slave_foe_write(master, arg); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_slave_foe_write(master, arg); + break; case EC_IOCTL_SLAVE_SOE_READ: - return ec_cdev_ioctl_slave_soe_read(master, arg); + ret = ec_cdev_ioctl_slave_soe_read(master, arg); + break; case EC_IOCTL_SLAVE_SOE_WRITE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_slave_soe_write(master, arg); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_slave_soe_write(master, arg); + break; case EC_IOCTL_CONFIG: - return ec_cdev_ioctl_config(master, arg); + ret = ec_cdev_ioctl_config(master, arg); + break; case EC_IOCTL_CONFIG_PDO: - return ec_cdev_ioctl_config_pdo(master, arg); + ret = ec_cdev_ioctl_config_pdo(master, arg); + break; case EC_IOCTL_CONFIG_PDO_ENTRY: - return ec_cdev_ioctl_config_pdo_entry(master, arg); + ret = ec_cdev_ioctl_config_pdo_entry(master, arg); + break; case EC_IOCTL_CONFIG_SDO: - return ec_cdev_ioctl_config_sdo(master, arg); + ret = ec_cdev_ioctl_config_sdo(master, arg); + break; case EC_IOCTL_CONFIG_IDN: - return ec_cdev_ioctl_config_idn(master, arg); + ret = ec_cdev_ioctl_config_idn(master, arg); + break; #ifdef EC_EOE case EC_IOCTL_EOE_HANDLER: - return ec_cdev_ioctl_eoe_handler(master, arg); + ret = ec_cdev_ioctl_eoe_handler(master, arg); + break; #endif case EC_IOCTL_REQUEST: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_request(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_request(master, arg, priv); + break; case EC_IOCTL_CREATE_DOMAIN: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_create_domain(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_create_domain(master, arg, priv); + break; case EC_IOCTL_CREATE_SLAVE_CONFIG: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_create_slave_config(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_create_slave_config(master, arg, priv); + break; case EC_IOCTL_ACTIVATE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_activate(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_activate(master, arg, priv); + break; case EC_IOCTL_DEACTIVATE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_deactivate(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_deactivate(master, arg, priv); + break; case EC_IOCTL_SEND: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_send(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_send(master, arg, priv); + break; case EC_IOCTL_RECEIVE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_receive(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_receive(master, arg, priv); + break; case EC_IOCTL_MASTER_STATE: - return ec_cdev_ioctl_master_state(master, arg, priv); + ret = ec_cdev_ioctl_master_state(master, arg, priv); + break; case EC_IOCTL_APP_TIME: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_app_time(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_app_time(master, arg, priv); + break; case EC_IOCTL_SYNC_REF: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sync_ref(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sync_ref(master, arg, priv); + break; case EC_IOCTL_SYNC_SLAVES: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sync_slaves(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sync_slaves(master, arg, priv); + break; case EC_IOCTL_SYNC_MON_QUEUE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sync_mon_queue(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sync_mon_queue(master, arg, priv); + break; case EC_IOCTL_SYNC_MON_PROCESS: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sync_mon_process(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sync_mon_process(master, arg, priv); + break; case EC_IOCTL_RESET: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_reset(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_reset(master, arg, priv); + break; case EC_IOCTL_SC_SYNC: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_sync(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_sync(master, arg, priv); + break; case EC_IOCTL_SC_WATCHDOG: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_watchdog(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_watchdog(master, arg, priv); + break; case EC_IOCTL_SC_ADD_PDO: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_add_pdo(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_add_pdo(master, arg, priv); + break; case EC_IOCTL_SC_CLEAR_PDOS: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_clear_pdos(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_clear_pdos(master, arg, priv); + break; case EC_IOCTL_SC_ADD_ENTRY: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_add_entry(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_add_entry(master, arg, priv); + break; case EC_IOCTL_SC_CLEAR_ENTRIES: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_clear_entries(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_clear_entries(master, arg, priv); + break; case EC_IOCTL_SC_REG_PDO_ENTRY: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_reg_pdo_entry(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_reg_pdo_entry(master, arg, priv); + break; case EC_IOCTL_SC_DC: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_dc(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_dc(master, arg, priv); + break; case EC_IOCTL_SC_SDO: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_sdo(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_sdo(master, arg, priv); + break; case EC_IOCTL_SC_SDO_REQUEST: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_create_sdo_request(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_create_sdo_request(master, arg, priv); + break; case EC_IOCTL_SC_VOE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_create_voe_handler(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_create_voe_handler(master, arg, priv); + break; case EC_IOCTL_SC_STATE: - return ec_cdev_ioctl_sc_state(master, arg, priv); + ret = ec_cdev_ioctl_sc_state(master, arg, priv); + break; case EC_IOCTL_SC_IDN: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sc_idn(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sc_idn(master, arg, priv); + break; case EC_IOCTL_DOMAIN_OFFSET: - return ec_cdev_ioctl_domain_offset(master, arg, priv); + ret = ec_cdev_ioctl_domain_offset(master, arg, priv); + break; case EC_IOCTL_DOMAIN_PROCESS: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_domain_process(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_domain_process(master, arg, priv); + break; case EC_IOCTL_DOMAIN_QUEUE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_domain_queue(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_domain_queue(master, arg, priv); + break; case EC_IOCTL_DOMAIN_STATE: - return ec_cdev_ioctl_domain_state(master, arg, priv); + ret = ec_cdev_ioctl_domain_state(master, arg, priv); + break; case EC_IOCTL_SDO_REQUEST_TIMEOUT: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sdo_request_timeout(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sdo_request_timeout(master, arg, priv); + break; case EC_IOCTL_SDO_REQUEST_STATE: - return ec_cdev_ioctl_sdo_request_state(master, arg, priv); + ret = ec_cdev_ioctl_sdo_request_state(master, arg, priv); + break; case EC_IOCTL_SDO_REQUEST_READ: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sdo_request_read(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sdo_request_read(master, arg, priv); + break; case EC_IOCTL_SDO_REQUEST_WRITE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_sdo_request_write(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_sdo_request_write(master, arg, priv); + break; case EC_IOCTL_SDO_REQUEST_DATA: - return ec_cdev_ioctl_sdo_request_data(master, arg, priv); + ret = ec_cdev_ioctl_sdo_request_data(master, arg, priv); + break; case EC_IOCTL_VOE_SEND_HEADER: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_voe_send_header(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_voe_send_header(master, arg, priv); + break; case EC_IOCTL_VOE_REC_HEADER: - return ec_cdev_ioctl_voe_rec_header(master, arg, priv); + ret = ec_cdev_ioctl_voe_rec_header(master, arg, priv); + break; case EC_IOCTL_VOE_READ: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_voe_read(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_voe_read(master, arg, priv); + break; case EC_IOCTL_VOE_READ_NOSYNC: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_voe_read_nosync(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_voe_read_nosync(master, arg, priv); + break; case EC_IOCTL_VOE_WRITE: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_voe_write(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_voe_write(master, arg, priv); + break; case EC_IOCTL_VOE_EXEC: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_voe_exec(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_voe_exec(master, arg, priv); + break; case EC_IOCTL_VOE_DATA: - return ec_cdev_ioctl_voe_data(master, arg, priv); + ret = ec_cdev_ioctl_voe_data(master, arg, priv); + break; case EC_IOCTL_SET_SEND_INTERVAL: - if (!(filp->f_mode & FMODE_WRITE)) - return -EPERM; - return ec_cdev_ioctl_set_send_interval(master, arg, priv); + if (!(filp->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + ret = ec_cdev_ioctl_set_send_interval(master, arg, priv); + break; default: - return -ENOTTY; - } + ret = -ENOTTY; + break; + } + +#if DEBUG_LATENCY + b = get_cycles(); + t = (unsigned int) ((b - a) * 1000LL) / cpu_khz; + if (t > 50) { + EC_MASTER_WARN(master, "ioctl(0x%02x) took %u us.\n", + _IOC_NR(cmd), t); + } +#endif + + return ret; } /*****************************************************************************/