usb: ks_bridge: Free up stale buffers in probe
Driver can add data buffer to the link list of rx/tx
buffers after emptying the list during disconnect.
These stale buffers can confuse efs sync server when
mdm device connects back. Hence free up the rx/tx
buffers again during probe. Avoid further addition of
tx buffers after disconnect by checking device
connection status in write API. Also, move
misc_deregister() after cancelling the work in order
to remove device node early during disconnect to avoid
any write call further.
Change-Id: I0641669afcf1e1aec36d7c619dc8922495f446d0
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c
index 656e379..d2461a5 100644
--- a/drivers/usb/misc/ks_bridge.c
+++ b/drivers/usb/misc/ks_bridge.c
@@ -277,6 +277,9 @@
unsigned long flags;
struct ks_bridge *ksb = fp->private_data;
+ if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
+ return -ENODEV;
+
pkt = ksb_alloc_data_pkt(count, GFP_KERNEL, ksb);
if (IS_ERR(pkt)) {
pr_err("unable to allocate data packet");
@@ -540,6 +543,8 @@
struct usb_endpoint_descriptor *ep_desc;
int i;
struct ks_bridge *ksb;
+ unsigned long flags;
+ struct data_pkt *pkt;
ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
@@ -593,6 +598,23 @@
dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);
+ /*free up stale buffers if any from previous disconnect*/
+ spin_lock_irqsave(&ksb->lock, flags);
+ while (!list_empty(&ksb->to_ks_list)) {
+ pkt = list_first_entry(&ksb->to_ks_list,
+ struct data_pkt, list);
+ list_del_init(&pkt->list);
+ ksb_free_data_pkt(pkt);
+ ksb->alloced_read_pkts--;
+ }
+ while (!list_empty(&ksb->to_mdm_list)) {
+ pkt = list_first_entry(&ksb->to_mdm_list,
+ struct data_pkt, list);
+ list_del_init(&pkt->list);
+ ksb_free_data_pkt(pkt);
+ }
+ spin_unlock_irqrestore(&ksb->lock, flags);
+
ksb->fs_dev = (struct miscdevice *)id->driver_info;
misc_register(ksb->fs_dev);
@@ -641,6 +663,8 @@
wake_up(&ksb->ks_wait_q);
cancel_work_sync(&ksb->to_mdm_work);
+ misc_deregister(ksb->fs_dev);
+
usb_kill_anchored_urbs(&ksb->submitted);
spin_lock_irqsave(&ksb->lock, flags);
@@ -649,6 +673,7 @@
struct data_pkt, list);
list_del_init(&pkt->list);
ksb_free_data_pkt(pkt);
+ ksb->alloced_read_pkts--;
}
while (!list_empty(&ksb->to_mdm_list)) {
pkt = list_first_entry(&ksb->to_mdm_list,
@@ -658,7 +683,6 @@
}
spin_unlock_irqrestore(&ksb->lock, flags);
- misc_deregister(ksb->fs_dev);
ifc->needs_remote_wakeup = 0;
usb_put_dev(ksb->udev);
ksb->ifc = NULL;