Loading drivers/soc/qcom/msm_glink_pkt.c +161 −33 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #define MODULE_NAME "msm_glinkpkt" #define DEVICE_NAME "glinkpkt" #define WAKEUPSOURCE_TIMEOUT (2000) /* two seconds */ #define CLOSE_WAIT_TIMEOUT 1000 /* one seconds */ #define GLINK_PKT_IOCTL_MAGIC (0xC3) Loading Loading @@ -89,6 +90,7 @@ * poll_mode: flag to check polling mode. * ch_read_wait_queue: reader thread wait queue. * ch_opened_wait_queue: open thread wait queue. * ch_closed_wait_queue: close thread wait queue. * pkt_list: The pending Rx packets list. * pkt_list_lock: Lock to protect @pkt_list. * pa_ws: Packet arrival Wakeup source. Loading Loading @@ -116,8 +118,9 @@ struct glink_pkt_dev { wait_queue_head_t ch_read_wait_queue; wait_queue_head_t ch_opened_wait_queue; wait_queue_head_t ch_closed_wait_queue; struct list_head pkt_list; struct mutex pkt_list_lock; spinlock_t pkt_list_lock; struct wakeup_source pa_ws; /* Packet Arrival Wakeup Source */ struct work_struct packet_arrival_work; Loading Loading @@ -154,6 +157,19 @@ struct queue_rx_intent_work { struct work_struct work; }; /** * notify_state_work - Work item to notify channel state. * state: Channel new state. * devp: Pointer to the device structure. * work: Hold the worker function information. */ struct notify_state_work { unsigned state; struct glink_pkt_dev *devp; void *handle; struct work_struct work; }; static DEFINE_MUTEX(glink_pkt_dev_lock_lha1); static LIST_HEAD(glink_pkt_dev_list); static DEFINE_MUTEX(glink_pkt_driver_lock_lha1); Loading @@ -177,7 +193,8 @@ module_param_named(debug_mask, msm_glink_pkt_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); static void glink_pkt_queue_rx_intent_worker(struct work_struct *work); static void glink_pkt_notify_state_worker(struct work_struct *work); static bool glink_pkt_read_avail(struct glink_pkt_dev *devp); #define DEBUG Loading Loading @@ -308,7 +325,7 @@ void glink_pkt_notify_rx(void *handle, const void *priv, GLINK_PKT_INFO("%s(): priv[%p] data[%p] size[%zu]\n", __func__, pkt_priv, (char *)ptr, size); pkt = kzalloc(sizeof(struct glink_rx_pkt), GFP_KERNEL); pkt = kzalloc(sizeof(*pkt), GFP_ATOMIC); if (!pkt) { GLINK_PKT_ERR("%s: memory allocation failed\n", __func__); return; Loading @@ -317,9 +334,9 @@ void glink_pkt_notify_rx(void *handle, const void *priv, pkt->data = ptr; pkt->pkt_priv = pkt_priv; pkt->size = size; mutex_lock(&devp->pkt_list_lock); spin_lock_irqsave(&devp->pkt_list_lock, flags); list_add_tail(&pkt->list, &devp->pkt_list); mutex_unlock(&devp->pkt_list_lock); spin_unlock_irqrestore(&devp->pkt_list_lock, flags); spin_lock_irqsave(&devp->pa_spinlock, flags); __pm_stay_awake(&devp->pa_ws); Loading Loading @@ -361,17 +378,27 @@ void glink_pkt_notify_tx_done(void *handle, const void *priv, void glink_pkt_notify_state(void *handle, const void *priv, unsigned event) { struct glink_pkt_dev *devp = (struct glink_pkt_dev *)priv; struct notify_state_work *work_item; if ((devp->handle != NULL) && (devp->handle != handle)) { GLINK_PKT_ERR("%s() event[%d] on incorrect channel [%s]\n", __func__, event, devp->open_cfg.name); return; } GLINK_PKT_INFO("%s(): event[%d] on [%s]\n", __func__, event, devp->open_cfg.name); devp->ch_state = event; if (event == GLINK_CONNECTED) { devp->in_reset = 0; wake_up_interruptible(&devp->ch_opened_wait_queue); } else if (event == GLINK_REMOTE_DISCONNECTED) { devp->in_reset = 1; wake_up(&devp->ch_read_wait_queue); wake_up_interruptible(&devp->ch_opened_wait_queue); work_item = kzalloc(sizeof(*work_item), GFP_ATOMIC); if (!work_item) { GLINK_PKT_ERR("%s() failed allocate work_item\n", __func__); return; } work_item->state = event; work_item->devp = devp; work_item->handle = handle; INIT_WORK(&work_item->work, glink_pkt_notify_state_worker); queue_work(glink_pkt_wq, &work_item->work); } /** Loading @@ -389,7 +416,7 @@ bool glink_pkt_rmt_rx_intent_req_cb(void *handle, const void *priv, size_t sz) GLINK_PKT_INFO("%s(): QUEUE RX INTENT to receive size[%zu]\n", __func__, sz); work_item = kmalloc(sizeof(struct queue_rx_intent_work), GFP_ATOMIC); work_item = kzalloc(sizeof(*work_item), GFP_ATOMIC); if (!work_item) { GLINK_PKT_ERR("%s failed allocate work_item\n", __func__); return false; Loading Loading @@ -453,9 +480,71 @@ static void glink_pkt_queue_rx_intent_worker(struct work_struct *work) if (ret) GLINK_PKT_ERR("%s queue_rx_intent failed\n", __func__); kfree(work_item); } /** * glink_pkt_notify_state_worker() - Notify state worker function * * work: Pointer to the work struct * * This function is used to notify the channel state and update the * internal data structure. */ static void glink_pkt_notify_state_worker(struct work_struct *work) { struct notify_state_work *work_item = container_of(work, struct notify_state_work, work); struct glink_pkt_dev *devp = work_item->devp; unsigned event = work_item->state; void *handle = work_item->handle; if (!devp) { GLINK_PKT_ERR("%s: Invalid device Handle\n", __func__); kfree(work_item); return; } GLINK_PKT_INFO("%s(): event[%d] on [%s]\n", __func__, event, devp->open_cfg.name); mutex_lock(&devp->ch_lock); devp->ch_state = event; if (event == GLINK_CONNECTED) { if (!devp->handle) devp->handle = handle; devp->in_reset = 0; wake_up_interruptible(&devp->ch_opened_wait_queue); } else if (event == GLINK_REMOTE_DISCONNECTED) { devp->in_reset = 1; wake_up(&devp->ch_read_wait_queue); wake_up_interruptible(&devp->ch_opened_wait_queue); } else if (event == GLINK_LOCAL_DISCONNECTED) { if (devp->handle == handle) devp->handle = NULL; wake_up_interruptible(&devp->ch_closed_wait_queue); } mutex_unlock(&devp->ch_lock); kfree(work_item); } /** * glink_pkt_read_avail() - check any pending packets to read * devp: pointer to G-Link packet device. * * This function is used to check any pending data packets are * available to read or not. */ static bool glink_pkt_read_avail(struct glink_pkt_dev *devp) { bool list_is_empty; unsigned long flags; spin_lock_irqsave(&devp->pkt_list_lock, flags); list_is_empty = list_empty(&devp->pkt_list); spin_unlock_irqrestore(&devp->pkt_list_lock, flags); return !list_is_empty; } /** * glink_pkt_read() - read() syscall for the glink_pkt device * file: Pointer to the file structure. Loading Loading @@ -507,9 +596,8 @@ ssize_t glink_pkt_read(struct file *file, __func__, devp->i, count); ret = wait_event_interruptible(devp->ch_read_wait_queue, !devp->handle || !list_empty(&devp->pkt_list) || devp->in_reset); !devp->handle || devp->in_reset || glink_pkt_read_avail(devp)); if (devp->in_reset) { GLINK_PKT_ERR("%s: notifying reset for glink_pkt_dev id:%d\n", __func__, devp->i); Loading @@ -530,15 +618,16 @@ ssize_t glink_pkt_read(struct file *file, return ret; } spin_lock_irqsave(&devp->pkt_list_lock, flags); pkt = list_first_entry(&devp->pkt_list, struct glink_rx_pkt, list); if (pkt->size > count) { GLINK_PKT_ERR("%s: Small Buff on dev Id:%d-[%zu > %zu]\n", __func__, devp->i, pkt->size, count); spin_unlock_irqrestore(&devp->pkt_list_lock, flags); return -ETOOSMALL; } list_del(&pkt->list); spin_unlock_irqrestore(&devp->pkt_list_lock, flags); ret = copy_to_user(buf, pkt->data, pkt->size); BUG_ON(ret != 0); Loading @@ -549,7 +638,7 @@ ssize_t glink_pkt_read(struct file *file, mutex_lock(&devp->ch_lock); spin_lock_irqsave(&devp->pa_spinlock, flags); if (devp->poll_mode && list_empty(&devp->pkt_list)) { if (devp->poll_mode && !glink_pkt_read_avail(devp)) { __pm_relax(&devp->pa_ws); devp->ws_locked = 0; devp->poll_mode = 0; Loading Loading @@ -661,7 +750,7 @@ static unsigned int glink_pkt_poll(struct file *file, poll_table *wait) return POLLHUP; } if (!list_empty(&devp->pkt_list)) { if (glink_pkt_read_avail(devp)) { mask |= POLLIN | POLLRDNORM; GLINK_PKT_INFO("%s sets POLLIN for glink_pkt_dev id: %d\n", __func__, devp->i); Loading Loading @@ -793,17 +882,44 @@ int glink_pkt_open(struct inode *inode, struct file *file) { int ret = 0; struct glink_pkt_dev *devp = NULL; int wait_time; devp = container_of(inode->i_cdev, struct glink_pkt_dev, cdev); if (!devp) { GLINK_PKT_ERR("%s on NULL device\n", __func__); return -EINVAL; } GLINK_PKT_INFO("Begin %s() on dev id:%d open_wait_time[%d] by [%s]\n", GLINK_PKT_INFO("Begin %s() on dev id:%d open_time_wait[%d] by [%s]\n", __func__, devp->i, devp->open_time_wait, current->comm); file->private_data = devp; wait_time = devp->open_time_wait; mutex_lock(&devp->ch_lock); /* waiting for previous close to complete */ if (devp->handle && devp->ref_cnt == 0) { mutex_unlock(&devp->ch_lock); if (wait_time < 0) { ret = wait_event_interruptible( devp->ch_opened_wait_queue, devp->ch_state == GLINK_LOCAL_DISCONNECTED); } else { ret = wait_event_interruptible_timeout( devp->ch_opened_wait_queue, devp->ch_state == GLINK_LOCAL_DISCONNECTED, msecs_to_jiffies(wait_time * 1000)); if (ret == 0) ret = -ETIMEDOUT; wait_time = ret; } if (ret < 0) { GLINK_PKT_ERR( "%s:failed for prev close on dev id:%d rc:%d\n", __func__, devp->i, ret); return ret; } mutex_lock(&devp->ch_lock); } if (!devp->handle) { devp->handle = glink_open(&devp->open_cfg); if (IS_ERR_OR_NULL(devp->handle)) { Loading @@ -816,14 +932,12 @@ int glink_pkt_open(struct inode *inode, struct file *file) goto error; } mutex_unlock(&devp->ch_lock); /* * Wait for the channel to be complete open state so we know * the remote is ready enough. * Default timeout 120 seconds. */ if (!devp->open_time_wait) devp->open_time_wait = 120; if (devp->open_time_wait < 0) { if (wait_time < 0) { ret = wait_event_interruptible( devp->ch_opened_wait_queue, devp->ch_state == GLINK_CONNECTED); Loading @@ -831,10 +945,11 @@ int glink_pkt_open(struct inode *inode, struct file *file) ret = wait_event_interruptible_timeout( devp->ch_opened_wait_queue, devp->ch_state == GLINK_CONNECTED, msecs_to_jiffies(devp->open_time_wait * 1000)); msecs_to_jiffies(wait_time * 1000)); if (ret == 0) ret = -ETIMEDOUT; } mutex_lock(&devp->ch_lock); if (ret < 0) { GLINK_PKT_ERR("%s: open failed on dev id:%d rc:%d\n", __func__, devp->i, ret); Loading Loading @@ -874,14 +989,24 @@ int glink_pkt_release(struct inode *inode, struct file *file) devp->ref_cnt--; if (devp->handle && devp->ref_cnt == 0) { devp->ch_state = GLINK_LOCAL_DISCONNECTED; wake_up(&devp->ch_read_wait_queue); wake_up_interruptible(&devp->ch_opened_wait_queue); ret = glink_close(devp->handle); if (ret) if (ret) { GLINK_PKT_ERR("%s: close failed ret[%d]\n", __func__, ret); devp->handle = NULL; } else { mutex_unlock(&devp->ch_lock); ret = wait_event_interruptible_timeout( devp->ch_closed_wait_queue, devp->ch_state == GLINK_LOCAL_DISCONNECTED, msecs_to_jiffies(CLOSE_WAIT_TIMEOUT)); if (ret == 0) GLINK_PKT_ERR( "%s(): close TIMEOUT on dev_id[%d]\n", __func__, devp->i); mutex_lock(&devp->ch_lock); } devp->poll_mode = 0; devp->ws_locked = 0; devp->sigs_updated = false; Loading Loading @@ -928,12 +1053,15 @@ static int glink_pkt_init_add_device(struct glink_pkt_dev *devp, int i) devp->poll_mode = 0; devp->ws_locked = 0; devp->ch_state = GLINK_LOCAL_DISCONNECTED; /* Default timeout for open wait is 120sec */ devp->open_time_wait = 120; mutex_init(&devp->ch_lock); init_waitqueue_head(&devp->ch_read_wait_queue); init_waitqueue_head(&devp->ch_opened_wait_queue); init_waitqueue_head(&devp->ch_closed_wait_queue); spin_lock_init(&devp->pa_spinlock); INIT_LIST_HEAD(&devp->pkt_list); mutex_init(&devp->pkt_list_lock); spin_lock_init(&devp->pkt_list_lock); wakeup_source_init(&devp->pa_ws, devp->dev_name); INIT_WORK(&devp->packet_arrival_work, packet_arrival_worker); Loading Loading @@ -1115,7 +1243,7 @@ static int glink_pkt_devicetree_init(struct platform_device *pdev) } for_each_child_of_node(pdev->dev.of_node, node) { glink_pkt_devp = kzalloc(sizeof(struct glink_pkt_dev), glink_pkt_devp = kzalloc(sizeof(*glink_pkt_devp), GFP_KERNEL); if (IS_ERR_OR_NULL(glink_pkt_devp)) { GLINK_PKT_ERR("%s: allocation failed id:%d\n", Loading Loading
drivers/soc/qcom/msm_glink_pkt.c +161 −33 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #define MODULE_NAME "msm_glinkpkt" #define DEVICE_NAME "glinkpkt" #define WAKEUPSOURCE_TIMEOUT (2000) /* two seconds */ #define CLOSE_WAIT_TIMEOUT 1000 /* one seconds */ #define GLINK_PKT_IOCTL_MAGIC (0xC3) Loading Loading @@ -89,6 +90,7 @@ * poll_mode: flag to check polling mode. * ch_read_wait_queue: reader thread wait queue. * ch_opened_wait_queue: open thread wait queue. * ch_closed_wait_queue: close thread wait queue. * pkt_list: The pending Rx packets list. * pkt_list_lock: Lock to protect @pkt_list. * pa_ws: Packet arrival Wakeup source. Loading Loading @@ -116,8 +118,9 @@ struct glink_pkt_dev { wait_queue_head_t ch_read_wait_queue; wait_queue_head_t ch_opened_wait_queue; wait_queue_head_t ch_closed_wait_queue; struct list_head pkt_list; struct mutex pkt_list_lock; spinlock_t pkt_list_lock; struct wakeup_source pa_ws; /* Packet Arrival Wakeup Source */ struct work_struct packet_arrival_work; Loading Loading @@ -154,6 +157,19 @@ struct queue_rx_intent_work { struct work_struct work; }; /** * notify_state_work - Work item to notify channel state. * state: Channel new state. * devp: Pointer to the device structure. * work: Hold the worker function information. */ struct notify_state_work { unsigned state; struct glink_pkt_dev *devp; void *handle; struct work_struct work; }; static DEFINE_MUTEX(glink_pkt_dev_lock_lha1); static LIST_HEAD(glink_pkt_dev_list); static DEFINE_MUTEX(glink_pkt_driver_lock_lha1); Loading @@ -177,7 +193,8 @@ module_param_named(debug_mask, msm_glink_pkt_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); static void glink_pkt_queue_rx_intent_worker(struct work_struct *work); static void glink_pkt_notify_state_worker(struct work_struct *work); static bool glink_pkt_read_avail(struct glink_pkt_dev *devp); #define DEBUG Loading Loading @@ -308,7 +325,7 @@ void glink_pkt_notify_rx(void *handle, const void *priv, GLINK_PKT_INFO("%s(): priv[%p] data[%p] size[%zu]\n", __func__, pkt_priv, (char *)ptr, size); pkt = kzalloc(sizeof(struct glink_rx_pkt), GFP_KERNEL); pkt = kzalloc(sizeof(*pkt), GFP_ATOMIC); if (!pkt) { GLINK_PKT_ERR("%s: memory allocation failed\n", __func__); return; Loading @@ -317,9 +334,9 @@ void glink_pkt_notify_rx(void *handle, const void *priv, pkt->data = ptr; pkt->pkt_priv = pkt_priv; pkt->size = size; mutex_lock(&devp->pkt_list_lock); spin_lock_irqsave(&devp->pkt_list_lock, flags); list_add_tail(&pkt->list, &devp->pkt_list); mutex_unlock(&devp->pkt_list_lock); spin_unlock_irqrestore(&devp->pkt_list_lock, flags); spin_lock_irqsave(&devp->pa_spinlock, flags); __pm_stay_awake(&devp->pa_ws); Loading Loading @@ -361,17 +378,27 @@ void glink_pkt_notify_tx_done(void *handle, const void *priv, void glink_pkt_notify_state(void *handle, const void *priv, unsigned event) { struct glink_pkt_dev *devp = (struct glink_pkt_dev *)priv; struct notify_state_work *work_item; if ((devp->handle != NULL) && (devp->handle != handle)) { GLINK_PKT_ERR("%s() event[%d] on incorrect channel [%s]\n", __func__, event, devp->open_cfg.name); return; } GLINK_PKT_INFO("%s(): event[%d] on [%s]\n", __func__, event, devp->open_cfg.name); devp->ch_state = event; if (event == GLINK_CONNECTED) { devp->in_reset = 0; wake_up_interruptible(&devp->ch_opened_wait_queue); } else if (event == GLINK_REMOTE_DISCONNECTED) { devp->in_reset = 1; wake_up(&devp->ch_read_wait_queue); wake_up_interruptible(&devp->ch_opened_wait_queue); work_item = kzalloc(sizeof(*work_item), GFP_ATOMIC); if (!work_item) { GLINK_PKT_ERR("%s() failed allocate work_item\n", __func__); return; } work_item->state = event; work_item->devp = devp; work_item->handle = handle; INIT_WORK(&work_item->work, glink_pkt_notify_state_worker); queue_work(glink_pkt_wq, &work_item->work); } /** Loading @@ -389,7 +416,7 @@ bool glink_pkt_rmt_rx_intent_req_cb(void *handle, const void *priv, size_t sz) GLINK_PKT_INFO("%s(): QUEUE RX INTENT to receive size[%zu]\n", __func__, sz); work_item = kmalloc(sizeof(struct queue_rx_intent_work), GFP_ATOMIC); work_item = kzalloc(sizeof(*work_item), GFP_ATOMIC); if (!work_item) { GLINK_PKT_ERR("%s failed allocate work_item\n", __func__); return false; Loading Loading @@ -453,9 +480,71 @@ static void glink_pkt_queue_rx_intent_worker(struct work_struct *work) if (ret) GLINK_PKT_ERR("%s queue_rx_intent failed\n", __func__); kfree(work_item); } /** * glink_pkt_notify_state_worker() - Notify state worker function * * work: Pointer to the work struct * * This function is used to notify the channel state and update the * internal data structure. */ static void glink_pkt_notify_state_worker(struct work_struct *work) { struct notify_state_work *work_item = container_of(work, struct notify_state_work, work); struct glink_pkt_dev *devp = work_item->devp; unsigned event = work_item->state; void *handle = work_item->handle; if (!devp) { GLINK_PKT_ERR("%s: Invalid device Handle\n", __func__); kfree(work_item); return; } GLINK_PKT_INFO("%s(): event[%d] on [%s]\n", __func__, event, devp->open_cfg.name); mutex_lock(&devp->ch_lock); devp->ch_state = event; if (event == GLINK_CONNECTED) { if (!devp->handle) devp->handle = handle; devp->in_reset = 0; wake_up_interruptible(&devp->ch_opened_wait_queue); } else if (event == GLINK_REMOTE_DISCONNECTED) { devp->in_reset = 1; wake_up(&devp->ch_read_wait_queue); wake_up_interruptible(&devp->ch_opened_wait_queue); } else if (event == GLINK_LOCAL_DISCONNECTED) { if (devp->handle == handle) devp->handle = NULL; wake_up_interruptible(&devp->ch_closed_wait_queue); } mutex_unlock(&devp->ch_lock); kfree(work_item); } /** * glink_pkt_read_avail() - check any pending packets to read * devp: pointer to G-Link packet device. * * This function is used to check any pending data packets are * available to read or not. */ static bool glink_pkt_read_avail(struct glink_pkt_dev *devp) { bool list_is_empty; unsigned long flags; spin_lock_irqsave(&devp->pkt_list_lock, flags); list_is_empty = list_empty(&devp->pkt_list); spin_unlock_irqrestore(&devp->pkt_list_lock, flags); return !list_is_empty; } /** * glink_pkt_read() - read() syscall for the glink_pkt device * file: Pointer to the file structure. Loading Loading @@ -507,9 +596,8 @@ ssize_t glink_pkt_read(struct file *file, __func__, devp->i, count); ret = wait_event_interruptible(devp->ch_read_wait_queue, !devp->handle || !list_empty(&devp->pkt_list) || devp->in_reset); !devp->handle || devp->in_reset || glink_pkt_read_avail(devp)); if (devp->in_reset) { GLINK_PKT_ERR("%s: notifying reset for glink_pkt_dev id:%d\n", __func__, devp->i); Loading @@ -530,15 +618,16 @@ ssize_t glink_pkt_read(struct file *file, return ret; } spin_lock_irqsave(&devp->pkt_list_lock, flags); pkt = list_first_entry(&devp->pkt_list, struct glink_rx_pkt, list); if (pkt->size > count) { GLINK_PKT_ERR("%s: Small Buff on dev Id:%d-[%zu > %zu]\n", __func__, devp->i, pkt->size, count); spin_unlock_irqrestore(&devp->pkt_list_lock, flags); return -ETOOSMALL; } list_del(&pkt->list); spin_unlock_irqrestore(&devp->pkt_list_lock, flags); ret = copy_to_user(buf, pkt->data, pkt->size); BUG_ON(ret != 0); Loading @@ -549,7 +638,7 @@ ssize_t glink_pkt_read(struct file *file, mutex_lock(&devp->ch_lock); spin_lock_irqsave(&devp->pa_spinlock, flags); if (devp->poll_mode && list_empty(&devp->pkt_list)) { if (devp->poll_mode && !glink_pkt_read_avail(devp)) { __pm_relax(&devp->pa_ws); devp->ws_locked = 0; devp->poll_mode = 0; Loading Loading @@ -661,7 +750,7 @@ static unsigned int glink_pkt_poll(struct file *file, poll_table *wait) return POLLHUP; } if (!list_empty(&devp->pkt_list)) { if (glink_pkt_read_avail(devp)) { mask |= POLLIN | POLLRDNORM; GLINK_PKT_INFO("%s sets POLLIN for glink_pkt_dev id: %d\n", __func__, devp->i); Loading Loading @@ -793,17 +882,44 @@ int glink_pkt_open(struct inode *inode, struct file *file) { int ret = 0; struct glink_pkt_dev *devp = NULL; int wait_time; devp = container_of(inode->i_cdev, struct glink_pkt_dev, cdev); if (!devp) { GLINK_PKT_ERR("%s on NULL device\n", __func__); return -EINVAL; } GLINK_PKT_INFO("Begin %s() on dev id:%d open_wait_time[%d] by [%s]\n", GLINK_PKT_INFO("Begin %s() on dev id:%d open_time_wait[%d] by [%s]\n", __func__, devp->i, devp->open_time_wait, current->comm); file->private_data = devp; wait_time = devp->open_time_wait; mutex_lock(&devp->ch_lock); /* waiting for previous close to complete */ if (devp->handle && devp->ref_cnt == 0) { mutex_unlock(&devp->ch_lock); if (wait_time < 0) { ret = wait_event_interruptible( devp->ch_opened_wait_queue, devp->ch_state == GLINK_LOCAL_DISCONNECTED); } else { ret = wait_event_interruptible_timeout( devp->ch_opened_wait_queue, devp->ch_state == GLINK_LOCAL_DISCONNECTED, msecs_to_jiffies(wait_time * 1000)); if (ret == 0) ret = -ETIMEDOUT; wait_time = ret; } if (ret < 0) { GLINK_PKT_ERR( "%s:failed for prev close on dev id:%d rc:%d\n", __func__, devp->i, ret); return ret; } mutex_lock(&devp->ch_lock); } if (!devp->handle) { devp->handle = glink_open(&devp->open_cfg); if (IS_ERR_OR_NULL(devp->handle)) { Loading @@ -816,14 +932,12 @@ int glink_pkt_open(struct inode *inode, struct file *file) goto error; } mutex_unlock(&devp->ch_lock); /* * Wait for the channel to be complete open state so we know * the remote is ready enough. * Default timeout 120 seconds. */ if (!devp->open_time_wait) devp->open_time_wait = 120; if (devp->open_time_wait < 0) { if (wait_time < 0) { ret = wait_event_interruptible( devp->ch_opened_wait_queue, devp->ch_state == GLINK_CONNECTED); Loading @@ -831,10 +945,11 @@ int glink_pkt_open(struct inode *inode, struct file *file) ret = wait_event_interruptible_timeout( devp->ch_opened_wait_queue, devp->ch_state == GLINK_CONNECTED, msecs_to_jiffies(devp->open_time_wait * 1000)); msecs_to_jiffies(wait_time * 1000)); if (ret == 0) ret = -ETIMEDOUT; } mutex_lock(&devp->ch_lock); if (ret < 0) { GLINK_PKT_ERR("%s: open failed on dev id:%d rc:%d\n", __func__, devp->i, ret); Loading Loading @@ -874,14 +989,24 @@ int glink_pkt_release(struct inode *inode, struct file *file) devp->ref_cnt--; if (devp->handle && devp->ref_cnt == 0) { devp->ch_state = GLINK_LOCAL_DISCONNECTED; wake_up(&devp->ch_read_wait_queue); wake_up_interruptible(&devp->ch_opened_wait_queue); ret = glink_close(devp->handle); if (ret) if (ret) { GLINK_PKT_ERR("%s: close failed ret[%d]\n", __func__, ret); devp->handle = NULL; } else { mutex_unlock(&devp->ch_lock); ret = wait_event_interruptible_timeout( devp->ch_closed_wait_queue, devp->ch_state == GLINK_LOCAL_DISCONNECTED, msecs_to_jiffies(CLOSE_WAIT_TIMEOUT)); if (ret == 0) GLINK_PKT_ERR( "%s(): close TIMEOUT on dev_id[%d]\n", __func__, devp->i); mutex_lock(&devp->ch_lock); } devp->poll_mode = 0; devp->ws_locked = 0; devp->sigs_updated = false; Loading Loading @@ -928,12 +1053,15 @@ static int glink_pkt_init_add_device(struct glink_pkt_dev *devp, int i) devp->poll_mode = 0; devp->ws_locked = 0; devp->ch_state = GLINK_LOCAL_DISCONNECTED; /* Default timeout for open wait is 120sec */ devp->open_time_wait = 120; mutex_init(&devp->ch_lock); init_waitqueue_head(&devp->ch_read_wait_queue); init_waitqueue_head(&devp->ch_opened_wait_queue); init_waitqueue_head(&devp->ch_closed_wait_queue); spin_lock_init(&devp->pa_spinlock); INIT_LIST_HEAD(&devp->pkt_list); mutex_init(&devp->pkt_list_lock); spin_lock_init(&devp->pkt_list_lock); wakeup_source_init(&devp->pa_ws, devp->dev_name); INIT_WORK(&devp->packet_arrival_work, packet_arrival_worker); Loading Loading @@ -1115,7 +1243,7 @@ static int glink_pkt_devicetree_init(struct platform_device *pdev) } for_each_child_of_node(pdev->dev.of_node, node) { glink_pkt_devp = kzalloc(sizeof(struct glink_pkt_dev), glink_pkt_devp = kzalloc(sizeof(*glink_pkt_devp), GFP_KERNEL); if (IS_ERR_OR_NULL(glink_pkt_devp)) { GLINK_PKT_ERR("%s: allocation failed id:%d\n", Loading