From 64fc8cb766bcbd564b3f60a1df64644c9482f253 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Fri, 29 Nov 2019 17:27:29 +0530 Subject: [PATCH] usb: mdm_data: Add support for QDLOADER bridging Add necessary support to flash images to connected MDM in EDL mode from host PC, via external AP. Also, add a module parameter 'prevent_edl_probe' to prevent 9008 PID (EDL PID) to bind to ks_bridge driver. Usage: To prevent binding to ks_bridge and bind to mdm_data_bridge: echo 1 > /sys/module/ks_bridge/parameters/prevent_edl_probe To switch back to default behavior (allow bind to ks_bridge): echo 0 > /sys/module/ks_bridge/parameters/prevent_edl_probe While at it, fix potential null pointer dereference in data_bridge_write. Change-Id: I170c820803f016a03dcc5952424358e1a9835cfa Signed-off-by: Ajay Agarwal --- drivers/usb/gadget/function/f_mdm_data.c | 1 + drivers/usb/misc/ks_bridge.c | 8 ++++++++ drivers/usb/misc/mdm_data_bridge.c | 4 +++- include/linux/usb/usb_bridge.h | 3 +++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_mdm_data.c b/drivers/usb/gadget/function/f_mdm_data.c index 357315a23844..ba69a027a38c 100644 --- a/drivers/usb/gadget/function/f_mdm_data.c +++ b/drivers/usb/gadget/function/f_mdm_data.c @@ -1231,6 +1231,7 @@ mdm_data_set_alt(struct usb_function *f, unsigned int intf, unsigned int alt) pr_debug("%s: mdm_data_port: %pK\n", __func__, port); port->tx_q_size = mdm_data_tx_q_size; + port->rx_q_size = mdm_data_rx_q_size; ret = config_ep_by_speed(cdev->gadget, f, port->in); if (ret) { port->in->desc = NULL; diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c index 9c1bea945fd1..4cdd81bd6874 100644 --- a/drivers/usb/misc/ks_bridge.c +++ b/drivers/usb/misc/ks_bridge.c @@ -88,6 +88,9 @@ static rwlock_t dbg_lock = __RW_LOCK_UNLOCKED(lck); static unsigned int enable_dbg = 1; module_param(enable_dbg, uint, 0644); +static bool prevent_edl_probe; +module_param(prevent_edl_probe, bool, 0644); + /*get_timestamp - returns time of day in us */ static unsigned int get_timestamp(void) { @@ -633,6 +636,11 @@ ksb_usb_probe(struct usb_interface *ifc, const struct usb_device_id *id) pr_debug("%s: id: %lu\n", __func__, id->driver_info); + if (prevent_edl_probe && (le16_to_cpu(id->idProduct) == 0x9008)) { + pr_err("%s: Preventing EDL device enumeration\n", __func__); + return -EINVAL; + } + udev = interface_to_usbdev(ifc); if (udev->actconfig->desc.bNumInterfaces > 1) { pr_err("%s: Invalid configuration: More than 1 interface\n", diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c index 85ff4c83618a..9591466bd129 100644 --- a/drivers/usb/misc/mdm_data_bridge.c +++ b/drivers/usb/misc/mdm_data_bridge.c @@ -513,7 +513,7 @@ int data_bridge_write(unsigned int id, struct sk_buff *skb) struct urb *txurb; struct timestamp_info *info = (struct timestamp_info *)skb->cb; struct data_bridge *dev = __mdm_dev[id]; - struct bridge *brdg; + struct bridge *brdg = dev->brdg; if (!dev->brdg || dev->err) { pr_err("%s: Bridge closed or device disconnected\n", __func__); @@ -968,6 +968,8 @@ static void bridge_disconnect(struct usb_interface *intf) /*driver info stores data bridge name used to match bridge xport name*/ static const struct usb_device_id bridge_ids[] = { + { USB_DEVICE_INTERFACE_NUMBER(0x05c6, 0x9008, 0), + .driver_info = (kernel_ulong_t)("edl"), }, { USB_DEVICE_INTERFACE_NUMBER(0x05c6, 0x9102, 6), .driver_info = (kernel_ulong_t)("qdss"), }, { USB_DEVICE_INTERFACE_NUMBER(0x05c6, 0x9102, 7), diff --git a/include/linux/usb/usb_bridge.h b/include/linux/usb/usb_bridge.h index 3701c17b51dd..ba5fbcebb892 100644 --- a/include/linux/usb/usb_bridge.h +++ b/include/linux/usb/usb_bridge.h @@ -22,6 +22,7 @@ enum bridge_id { USB_BRIDGE_QDSS, USB_BRIDGE_DPL, + USB_BRIDGE_EDL, MAX_BRIDGE_DEVICES, }; @@ -34,6 +35,8 @@ static int bridge_name_to_id(const char *name) return USB_BRIDGE_QDSS; if (!strncasecmp(name, "dpl", MAX_INST_NAME_LEN)) return USB_BRIDGE_DPL; + if (!strncasecmp(name, "edl", MAX_INST_NAME_LEN)) + return USB_BRIDGE_EDL; fail: return -EINVAL;