usb: gadget: mbim: Synchronize reset_function handling
On reception of reset_function from host,
queue for QBI an empty message instead of sending signal.
This is done to insure chronological order among all commands
and reset_function.
Change-Id: Id4eecacc392519475f09407f079971bf9fc34396
Signed-off-by: Anna Perel <aperel@codeaurora.org>
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 0598c7b..02b2cc3 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -100,8 +100,6 @@
u32 ntb_input_size;
u16 ntb_max_datagrams;
- pid_t user_pid;
-
atomic_t error;
};
@@ -619,6 +617,59 @@
atomic_set(&mbim->online, 0);
}
+static void mbim_reset_function_queue(struct f_mbim *dev)
+{
+ struct ctrl_pkt *cpkt = NULL;
+
+ pr_debug("Queue empty packet for QBI");
+
+ spin_lock(&dev->lock);
+ if (!dev->is_open) {
+ pr_err("%s: mbim file handler %p is not open", __func__, dev);
+ spin_unlock(&dev->lock);
+ return;
+ }
+
+ cpkt = mbim_alloc_ctrl_pkt(0, GFP_ATOMIC);
+ if (!cpkt) {
+ pr_err("%s: Unable to allocate reset function pkt\n", __func__);
+ spin_unlock(&dev->lock);
+ return;
+ }
+
+ list_add_tail(&cpkt->list, &dev->cpkt_req_q);
+ spin_unlock(&dev->lock);
+
+ pr_debug("%s: Wake up read queue", __func__);
+ wake_up(&dev->read_wq);
+}
+
+static void fmbim_reset_cmd_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_mbim *dev = req->context;
+
+ mbim_reset_function_queue(dev);
+}
+
+static void mbim_clear_queues(struct f_mbim *mbim)
+{
+ struct ctrl_pkt *cpkt = NULL;
+ struct list_head *act, *tmp;
+
+ spin_lock(&mbim->lock);
+ list_for_each_safe(act, tmp, &mbim->cpkt_req_q) {
+ cpkt = list_entry(act, struct ctrl_pkt, list);
+ list_del(&cpkt->list);
+ mbim_free_ctrl_pkt(cpkt);
+ }
+ list_for_each_safe(act, tmp, &mbim->cpkt_resp_q) {
+ cpkt = list_entry(act, struct ctrl_pkt, list);
+ list_del(&cpkt->list);
+ mbim_free_ctrl_pkt(cpkt);
+ }
+ spin_unlock(&mbim->lock);
+}
+
/*
* Context: mbim->lock held
*/
@@ -741,6 +792,9 @@
mbim->not_port.notify_state = NCM_NOTIFY_NONE;
atomic_set(&mbim->not_port.notify_count, 0);
pr_info("ESHUTDOWN/ECONNRESET, connection gone");
+ spin_unlock(&mbim->lock);
+ mbim_clear_queues(mbim);
+ mbim_reset_function_queue(mbim);
break;
default:
pr_err("Unknown event %02x --> %d\n",
@@ -880,21 +934,8 @@
pr_info("USB_CDC_RESET_FUNCTION");
value = 0;
- if (!_mbim_dev->user_pid) {
- pr_err("QBI pid is not set");
- break;
- }
-
- if (!_mbim_dev->is_open) {
- pr_err("QBI is not up yet");
- break;
- }
-
- send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
- find_task_by_vpid(_mbim_dev->user_pid));
-
- pr_info("Sent signal to QBI pid %d",
- _mbim_dev->user_pid);
+ req->complete = fmbim_reset_cmd_complete;
+ req->context = mbim;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
@@ -1200,12 +1241,8 @@
pr_info("SET DEVICE OFFLINE");
atomic_set(&mbim->online, 0);
- if (_mbim_dev && _mbim_dev->user_pid && _mbim_dev->is_open) {
- send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
- find_task_by_vpid(_mbim_dev->user_pid));
- pr_info("Sending reset signal to QBI pid %d",
- _mbim_dev->user_pid);
- }
+ mbim_clear_queues(mbim);
+ mbim_reset_function_queue(mbim);
mbim_bam_disconnect(mbim);
@@ -1599,9 +1636,6 @@
if (!atomic_read(&_mbim_dev->online))
pr_err("USB cable not connected\n");
- pr_info("Set QBI pid %d\n", pid_nr(task_pid(current)));
- _mbim_dev->user_pid = pid_nr(task_pid(current));
-
fp->private_data = _mbim_dev;
atomic_set(&_mbim_dev->error, 0);
@@ -1627,8 +1661,6 @@
mbim_notify(mbim);
spin_unlock(&mbim->lock);
- mbim->user_pid = 0;
-
mbim_unlock(&_mbim_dev->open_excl);
return 0;