Merge "soc: qcom: glink: Fix queue intent after glink close"

This commit is contained in:
Linux Build Service Account 2017-01-03 17:56:48 -08:00 committed by Gerrit - the friendly Code Review server
commit 40c4e57f2a

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -502,13 +502,21 @@ static void glink_pkt_queue_rx_intent_worker(struct work_struct *work)
struct queue_rx_intent_work, work);
struct glink_pkt_dev *devp = work_item->devp;
if (!devp || !devp->handle) {
if (!devp) {
GLINK_PKT_ERR("%s: Invalid device\n", __func__);
kfree(work_item);
return;
}
mutex_lock(&devp->ch_lock);
if (!devp->handle) {
GLINK_PKT_ERR("%s: Invalid device Handle\n", __func__);
mutex_unlock(&devp->ch_lock);
kfree(work_item);
return;
}
ret = glink_queue_rx_intent(devp->handle, devp, work_item->intent_size);
mutex_unlock(&devp->ch_lock);
GLINK_PKT_INFO("%s: Triggered with size[%zu] ret[%d]\n",
__func__, work_item->intent_size, ret);
if (ret)
@ -1050,6 +1058,27 @@ error:
return ret;
}
/**
* pop_rx_pkt() - return first pkt from rx pkt_list
* devp: pointer to G-Link packet device.
*
* This function return first item from rx pkt_list and NULL if list is empty.
*/
struct glink_rx_pkt *pop_rx_pkt(struct glink_pkt_dev *devp)
{
unsigned long flags;
struct glink_rx_pkt *pkt = NULL;
spin_lock_irqsave(&devp->pkt_list_lock, flags);
if (!list_empty(&devp->pkt_list)) {
pkt = list_first_entry(&devp->pkt_list,
struct glink_rx_pkt, list);
list_del(&pkt->list);
}
spin_unlock_irqrestore(&devp->pkt_list_lock, flags);
return pkt;
}
/**
* glink_pkt_release() - release operation on glink_pkt device
* inode: Pointer to the inode structure.
@ -1064,6 +1093,7 @@ int glink_pkt_release(struct inode *inode, struct file *file)
int ret = 0;
struct glink_pkt_dev *devp = file->private_data;
unsigned long flags;
struct glink_rx_pkt *pkt;
GLINK_PKT_INFO("%s() on dev id:%d by [%s] ref_cnt[%d]\n",
__func__, devp->i, current->comm, devp->ref_cnt);
@ -1072,9 +1102,14 @@ int glink_pkt_release(struct inode *inode, struct file *file)
devp->ref_cnt--;
if (devp->handle && devp->ref_cnt == 0) {
while ((pkt = pop_rx_pkt(devp))) {
glink_rx_done(devp->handle, pkt->data, false);
kfree(pkt);
}
wake_up(&devp->ch_read_wait_queue);
wake_up_interruptible(&devp->ch_opened_wait_queue);
ret = glink_close(devp->handle);
devp->handle = NULL;
if (ret) {
GLINK_PKT_ERR("%s: close failed ret[%d]\n",
__func__, ret);