usb: gadget: Fixed QMI packets error handling
When notify packet transfer failed, notify_count and cpkt_resp_q
would go out of sync. After the fix the packets are also removed from
the queue.
Change-Id: If33ea5070f460617179a77063a9e58c47ed93167
CRs-Fixed: 383661
Signed-off-by: Anna Perel <aperel@codeaurora.org>
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 414a7b9..1d0b6d4 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -607,6 +607,7 @@
struct usb_cdc_notification *event;
unsigned long flags;
int ret;
+ struct rmnet_ctrl_pkt *cpkt;
pr_debug("%s:dev:%p portno#%d\n", __func__, dev, dev->port_num);
@@ -633,6 +634,14 @@
ret = usb_ep_queue(dev->notify, dev->notify_req, GFP_ATOMIC);
if (ret) {
atomic_dec(&dev->notify_count);
+ spin_lock_irqsave(&dev->lock, flags);
+ cpkt = list_first_entry(&dev->cpkt_resp_q,
+ struct rmnet_ctrl_pkt, list);
+ if (cpkt) {
+ list_del(&cpkt->list);
+ rmnet_free_ctrl_pkt(cpkt);
+ }
+ spin_unlock_irqrestore(&dev->lock, flags);
pr_debug("ep enqueue error %d\n", ret);
}
}
@@ -768,6 +777,8 @@
{
struct f_rmnet *dev = req->context;
int status = req->status;
+ unsigned long flags;
+ struct rmnet_ctrl_pkt *cpkt;
pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
@@ -790,6 +801,14 @@
status = usb_ep_queue(dev->notify, req, GFP_ATOMIC);
if (status) {
atomic_dec(&dev->notify_count);
+ spin_lock_irqsave(&dev->lock, flags);
+ cpkt = list_first_entry(&dev->cpkt_resp_q,
+ struct rmnet_ctrl_pkt, list);
+ if (cpkt) {
+ list_del(&cpkt->list);
+ rmnet_free_ctrl_pkt(cpkt);
+ }
+ spin_unlock_irqrestore(&dev->lock, flags);
pr_debug("ep enqueue error %d\n", status);
}
break;