static int usf_get_tx_update(struct usf_type *usf, unsigned long arg) { struct us_tx_update_info_type upd_tx_info; unsigned long prev_jiffies = 0; uint32_t timeout = 0; struct usf_xx_type *usf_xx = &usf->usf_tx; int rc = copy_from_user(&upd_tx_info, (void *) arg, sizeof(upd_tx_info)); if (rc) { pr_err("%s: copy upd_tx_info from user; rc=%d\n", __func__, rc); return -EFAULT; } if (!usf_xx->user_upd_info_na) { usf_set_event_filters(usf, upd_tx_info.event_filters); handle_input_event(usf, upd_tx_info.event_counter, upd_tx_info.event); /* Release available regions */ rc = q6usm_read(usf_xx->usc, upd_tx_info.free_region); if (rc) return rc; } else usf_xx->user_upd_info_na = 0; /* Get data ready regions */ if (upd_tx_info.timeout == USF_INFINITIVE_TIMEOUT) { rc = wait_event_interruptible(usf_xx->wait, (usf_xx->prev_region != usf_xx->new_region) || (usf_xx->usf_state != USF_WORK_STATE)); } else { if (upd_tx_info.timeout == USF_NO_WAIT_TIMEOUT) rc = (usf_xx->prev_region != usf_xx->new_region); else { prev_jiffies = jiffies; if (upd_tx_info.timeout == USF_DEFAULT_TIMEOUT) { timeout = USF_TIMEOUT_JIFFIES; rc = wait_event_timeout( usf_xx->wait, (usf_xx->prev_region != usf_xx->new_region) || (usf_xx->usf_state != USF_WORK_STATE), timeout); } else { timeout = upd_tx_info.timeout * HZ; rc = wait_event_interruptible_timeout( usf_xx->wait, (usf_xx->prev_region != usf_xx->new_region) || (usf_xx->usf_state != USF_WORK_STATE), timeout); } } if (!rc) { pr_debug("%s: timeout. prev_j=%lu; j=%lu\n", __func__, prev_jiffies, jiffies); pr_debug("%s: timeout. prev=%d; new=%d\n", __func__, usf_xx->prev_region, usf_xx->new_region); pr_debug("%s: timeout. free_region=%d;\n", __func__, upd_tx_info.free_region); if (usf_xx->prev_region == usf_xx->new_region) { pr_err("%s:read data: timeout\n", __func__); return -ETIME; } } } if ((usf_xx->usf_state != USF_WORK_STATE) || (rc == -ERESTARTSYS)) { pr_err("%s: Get ready region failure; state[%d]; rc[%d]\n", __func__, usf_xx->usf_state, rc); return -EINTR; } upd_tx_info.ready_region = usf_xx->new_region; usf_xx->prev_region = upd_tx_info.ready_region; if (upd_tx_info.ready_region == USM_WRONG_TOKEN) { pr_err("%s: TX path corrupted; prev=%d\n", __func__, usf_xx->prev_region); return -EIO; } rc = copy_to_user((void __user *)arg, &upd_tx_info, sizeof(upd_tx_info)); if (rc) { pr_err("%s: copy upd_tx_info to user; rc=%d\n", __func__, rc); rc = -EFAULT; } return rc; } /* usf_get_tx_update */
static int usf_get_tx_update(struct usf_type *usf, unsigned long arg) { struct us_tx_update_info_type upd_tx_info; unsigned long prev_jiffies = 0; struct usf_xx_type *usf_xx = &usf->usf_tx; int rc = copy_from_user(&upd_tx_info, (void *) arg, sizeof(upd_tx_info)); if (rc) { pr_err("%s: get_update: copy_from_user() failed[%d]\n", __func__, rc); return -EINVAL; } if (!usf_xx->user_upd_info_na) { handle_input_event(usf, upd_tx_info.event_counter, upd_tx_info.event); /* Release available regions */ rc = q6usm_read(usf_xx->usc, upd_tx_info.free_region); if (rc) return rc; } else usf_xx->user_upd_info_na = 0; /* Get data ready regions */ prev_jiffies = jiffies; rc = wait_event_timeout(usf_xx->wait, (usf_xx->prev_region != usf_xx->new_region) || (usf_xx->usf_state != USF_WORK_STATE), USF_TIMEOUT_JIFFIES); if (!rc) { pr_debug("%s: timeout. prev_j=%lu; j=%lu\n", __func__, prev_jiffies, jiffies); pr_debug("%s: timeout. prev=%d; new=%d\n", __func__, usf_xx->prev_region, usf_xx->new_region); pr_debug("%s: timeout. free_region=%d;\n", __func__, upd_tx_info.free_region); if (usf_xx->prev_region == usf_xx->new_region) { pr_err("%s:read data: timeout\n", __func__); return -ETIME; } } if (usf_xx->usf_state != USF_WORK_STATE) { pr_err("%s: TX device is in not work state[%d]\n", __func__, usf_xx->usf_state); return -EINTR; } upd_tx_info.ready_region = usf_xx->new_region; rc = copy_to_user((void __user *)arg, &upd_tx_info, sizeof(upd_tx_info)); if (upd_tx_info.ready_region == USM_WRONG_TOKEN) { pr_err("%s: TX path corrupted; prev=%d\n", __func__, usf_xx->prev_region); rc = -EIO; } usf_xx->prev_region = upd_tx_info.ready_region; return rc; } /* usf_get_tx_update */