From d0cde88e6c21183f4c6f897b5694419fe3d9bcd8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 1 Aug 2012 08:42:43 -0700 Subject: [PATCH] 3.5-stable patches added patches: revert-usb-uas-make-sure-data-urb-is-gone-if-we-receive-status-before-that.patch usbdevfs-correct-amount-of-data-copied-to-user-in-processcompl_compat.patch usb-gadget-fix-g_ether-interface-link-status.patch usb-option-add-zte-mf821d.patch --- ...one-if-we-receive-status-before-that.patch | 214 ++++++++++++++++++ queue-3.5/series | 4 + ...et-fix-g_ether-interface-link-status.patch | 59 +++++ queue-3.5/usb-option-add-zte-mf821d.patch | 30 +++ ...opied-to-user-in-processcompl_compat.patch | 41 ++++ 5 files changed, 348 insertions(+) create mode 100644 queue-3.5/revert-usb-uas-make-sure-data-urb-is-gone-if-we-receive-status-before-that.patch create mode 100644 queue-3.5/usb-gadget-fix-g_ether-interface-link-status.patch create mode 100644 queue-3.5/usb-option-add-zte-mf821d.patch create mode 100644 queue-3.5/usbdevfs-correct-amount-of-data-copied-to-user-in-processcompl_compat.patch diff --git a/queue-3.5/revert-usb-uas-make-sure-data-urb-is-gone-if-we-receive-status-before-that.patch b/queue-3.5/revert-usb-uas-make-sure-data-urb-is-gone-if-we-receive-status-before-that.patch new file mode 100644 index 00000000000..5af7de3e427 --- /dev/null +++ b/queue-3.5/revert-usb-uas-make-sure-data-urb-is-gone-if-we-receive-status-before-that.patch @@ -0,0 +1,214 @@ +From c621a81edecdee85da32c566c21836332c764fda Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 19 Jun 2012 09:54:48 +0200 +Subject: Revert "usb/uas: make sure data urb is gone if we receive status before that" + +From: Gerd Hoffmann + +commit c621a81edecdee85da32c566c21836332c764fda upstream. + +This reverts commit e4d8318a85779b25b880187b1b1c44e797bd7d4b. + +This patch makes uas.c call usb_unlink_urb on data urbs. The data urbs +get freed in the completion callback. This is illegal according to the +usb_unlink_urb documentation. + +This patch also makes the code expect the data completion callback +being called before the status completion callback. This isn't +guaranteed to be the case, even though the actual data transfer should +be finished by the time the status is received. + +Background: The ehci irq handler for example only know that there are +finished transfers, it then has go check the QHs & TDs to see which +transfers did actually finish. It has no way to figure in which order +the transfers did complete. The xhci driver can call the callbacks in +completion order thanks to the event queue. This does nicely explain +why the driver is solid on a (usb2) xhci port whereas it goes crazy on +ehci in my testing. + +Signed-off-by: Gerd Hoffmann +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/storage/uas.c | 90 +++++++--------------------------------------- + 1 file changed, 15 insertions(+), 75 deletions(-) + +--- a/drivers/usb/storage/uas.c ++++ b/drivers/usb/storage/uas.c +@@ -58,9 +58,6 @@ enum { + SUBMIT_DATA_OUT_URB = (1 << 5), + ALLOC_CMD_URB = (1 << 6), + SUBMIT_CMD_URB = (1 << 7), +- COMPLETED_DATA_IN = (1 << 8), +- COMPLETED_DATA_OUT = (1 << 9), +- DATA_COMPLETES_CMD = (1 << 10), + }; + + /* Overrides scsi_pointer */ +@@ -114,7 +111,6 @@ static void uas_sense(struct urb *urb, s + { + struct sense_iu *sense_iu = urb->transfer_buffer; + struct scsi_device *sdev = cmnd->device; +- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + + if (urb->actual_length > 16) { + unsigned len = be16_to_cpup(&sense_iu->len); +@@ -132,15 +128,13 @@ static void uas_sense(struct urb *urb, s + } + + cmnd->result = sense_iu->status; +- if (!(cmdinfo->state & DATA_COMPLETES_CMD)) +- cmnd->scsi_done(cmnd); ++ cmnd->scsi_done(cmnd); + } + + static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) + { + struct sense_iu_old *sense_iu = urb->transfer_buffer; + struct scsi_device *sdev = cmnd->device; +- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + + if (urb->actual_length > 8) { + unsigned len = be16_to_cpup(&sense_iu->len) - 2; +@@ -158,8 +152,7 @@ static void uas_sense_old(struct urb *ur + } + + cmnd->result = sense_iu->status; +- if (!(cmdinfo->state & DATA_COMPLETES_CMD)) +- cmnd->scsi_done(cmnd); ++ cmnd->scsi_done(cmnd); + } + + static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, +@@ -184,7 +177,6 @@ static void uas_stat_cmplt(struct urb *u + struct Scsi_Host *shost = urb->context; + struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; + struct scsi_cmnd *cmnd; +- struct uas_cmd_info *cmdinfo; + u16 tag; + int ret; + +@@ -210,32 +202,12 @@ static void uas_stat_cmplt(struct urb *u + dev_err(&urb->dev->dev, "failed submit status urb\n"); + return; + } +- cmdinfo = (void *)&cmnd->SCp; + + switch (iu->iu_id) { + case IU_ID_STATUS: + if (devinfo->cmnd == cmnd) + devinfo->cmnd = NULL; + +- if (!(cmdinfo->state & COMPLETED_DATA_IN) && +- cmdinfo->data_in_urb) { +- if (devinfo->use_streams) { +- cmdinfo->state |= DATA_COMPLETES_CMD; +- usb_unlink_urb(cmdinfo->data_in_urb); +- } else { +- usb_free_urb(cmdinfo->data_in_urb); +- } +- } +- if (!(cmdinfo->state & COMPLETED_DATA_OUT) && +- cmdinfo->data_out_urb) { +- if (devinfo->use_streams) { +- cmdinfo->state |= DATA_COMPLETES_CMD; +- usb_unlink_urb(cmdinfo->data_in_urb); +- } else { +- usb_free_urb(cmdinfo->data_out_urb); +- } +- } +- + if (urb->actual_length < 16) + devinfo->uas_sense_old = 1; + if (devinfo->uas_sense_old) +@@ -264,59 +236,27 @@ static void uas_stat_cmplt(struct urb *u + dev_err(&urb->dev->dev, "failed submit status urb\n"); + } + +-static void uas_data_out_cmplt(struct urb *urb) +-{ +- struct scsi_cmnd *cmnd = urb->context; +- struct scsi_data_buffer *sdb = scsi_out(cmnd); +- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; +- +- cmdinfo->state |= COMPLETED_DATA_OUT; +- +- sdb->resid = sdb->length - urb->actual_length; +- usb_free_urb(urb); +- +- if (cmdinfo->state & DATA_COMPLETES_CMD) +- cmnd->scsi_done(cmnd); +-} +- +-static void uas_data_in_cmplt(struct urb *urb) ++static void uas_data_cmplt(struct urb *urb) + { +- struct scsi_cmnd *cmnd = urb->context; +- struct scsi_data_buffer *sdb = scsi_in(cmnd); +- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; +- +- cmdinfo->state |= COMPLETED_DATA_IN; +- ++ struct scsi_data_buffer *sdb = urb->context; + sdb->resid = sdb->length - urb->actual_length; + usb_free_urb(urb); +- +- if (cmdinfo->state & DATA_COMPLETES_CMD) +- cmnd->scsi_done(cmnd); + } + + static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, +- unsigned int pipe, struct scsi_cmnd *cmnd, +- enum dma_data_direction dir) ++ unsigned int pipe, u16 stream_id, ++ struct scsi_data_buffer *sdb, ++ enum dma_data_direction dir) + { +- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + struct usb_device *udev = devinfo->udev; + struct urb *urb = usb_alloc_urb(0, gfp); +- struct scsi_data_buffer *sdb; +- usb_complete_t complete_fn; +- u16 stream_id = cmdinfo->stream; + + if (!urb) + goto out; +- if (dir == DMA_FROM_DEVICE) { +- sdb = scsi_in(cmnd); +- complete_fn = uas_data_in_cmplt; +- } else { +- sdb = scsi_out(cmnd); +- complete_fn = uas_data_out_cmplt; +- } +- usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, +- complete_fn, cmnd); +- urb->stream_id = stream_id; ++ usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt, ++ sdb); ++ if (devinfo->use_streams) ++ urb->stream_id = stream_id; + urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0; + urb->sg = sdb->table.sgl; + out: +@@ -418,8 +358,8 @@ static int uas_submit_urbs(struct scsi_c + + if (cmdinfo->state & ALLOC_DATA_IN_URB) { + cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp, +- devinfo->data_in_pipe, cmnd, +- DMA_FROM_DEVICE); ++ devinfo->data_in_pipe, cmdinfo->stream, ++ scsi_in(cmnd), DMA_FROM_DEVICE); + if (!cmdinfo->data_in_urb) + return SCSI_MLQUEUE_DEVICE_BUSY; + cmdinfo->state &= ~ALLOC_DATA_IN_URB; +@@ -436,8 +376,8 @@ static int uas_submit_urbs(struct scsi_c + + if (cmdinfo->state & ALLOC_DATA_OUT_URB) { + cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp, +- devinfo->data_out_pipe, cmnd, +- DMA_TO_DEVICE); ++ devinfo->data_out_pipe, cmdinfo->stream, ++ scsi_out(cmnd), DMA_TO_DEVICE); + if (!cmdinfo->data_out_urb) + return SCSI_MLQUEUE_DEVICE_BUSY; + cmdinfo->state &= ~ALLOC_DATA_OUT_URB; diff --git a/queue-3.5/series b/queue-3.5/series index 83c8507f2c0..4f7bd1034ee 100644 --- a/queue-3.5/series +++ b/queue-3.5/series @@ -25,3 +25,7 @@ alsa-hda-add-support-for-realtek-alc282.patch alsa-hda-turn-on-pin_out-from-hdmi-playback-prepare.patch alsa-hda-don-t-power-up-when-not-powered-down.patch hid-hid-multitouch-fix-input-mode-feature-command.patch +usbdevfs-correct-amount-of-data-copied-to-user-in-processcompl_compat.patch +usb-gadget-fix-g_ether-interface-link-status.patch +usb-option-add-zte-mf821d.patch +revert-usb-uas-make-sure-data-urb-is-gone-if-we-receive-status-before-that.patch diff --git a/queue-3.5/usb-gadget-fix-g_ether-interface-link-status.patch b/queue-3.5/usb-gadget-fix-g_ether-interface-link-status.patch new file mode 100644 index 00000000000..903a89cb8c0 --- /dev/null +++ b/queue-3.5/usb-gadget-fix-g_ether-interface-link-status.patch @@ -0,0 +1,59 @@ +From 31bde1ceaa873bcaecd49e829bfabceacc4c512d Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Sun, 24 Jun 2012 21:11:22 -0700 +Subject: usb: gadget: Fix g_ether interface link status + +From: Kevin Cernekee + +commit 31bde1ceaa873bcaecd49e829bfabceacc4c512d upstream. + +A "usb0" interface that has never been connected to a host has an unknown +operstate, and therefore the IFF_RUNNING flag is (incorrectly) asserted +when queried by ifconfig, ifplugd, etc. This is a result of calling +netif_carrier_off() too early in the probe function; it should be called +after register_netdev(). + +Similar problems have been fixed in many other drivers, e.g.: + + e826eafa6 (bonding: Call netif_carrier_off after register_netdevice) + 0d672e9f8 (drivers/net: Call netif_carrier_off at the end of the probe) + 6a3c869a6 (cxgb4: fix reported state of interfaces without link) + +Fix is to move netif_carrier_off() to the end of the function. + +Signed-off-by: Kevin Cernekee +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/u_ether.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/usb/gadget/u_ether.c ++++ b/drivers/usb/gadget/u_ether.c +@@ -798,12 +798,6 @@ int gether_setup_name(struct usb_gadget + + SET_ETHTOOL_OPS(net, &ops); + +- /* two kinds of host-initiated state changes: +- * - iff DATA transfer is active, carrier is "on" +- * - tx queueing enabled if open *and* carrier is "on" +- */ +- netif_carrier_off(net); +- + dev->gadget = g; + SET_NETDEV_DEV(net, &g->dev); + SET_NETDEV_DEVTYPE(net, &gadget_type); +@@ -817,6 +811,12 @@ int gether_setup_name(struct usb_gadget + INFO(dev, "HOST MAC %pM\n", dev->host_mac); + + the_dev = dev; ++ ++ /* two kinds of host-initiated state changes: ++ * - iff DATA transfer is active, carrier is "on" ++ * - tx queueing enabled if open *and* carrier is "on" ++ */ ++ netif_carrier_off(net); + } + + return status; diff --git a/queue-3.5/usb-option-add-zte-mf821d.patch b/queue-3.5/usb-option-add-zte-mf821d.patch new file mode 100644 index 00000000000..1c51853b21d --- /dev/null +++ b/queue-3.5/usb-option-add-zte-mf821d.patch @@ -0,0 +1,30 @@ +From 09110529780890804b22e997ae6b4fe3f0b3b158 Mon Sep 17 00:00:00 2001 +From: Bjørn Mork +Date: Thu, 12 Jul 2012 12:37:32 +0200 +Subject: USB: option: add ZTE MF821D + +From: Bjørn Mork + +commit 09110529780890804b22e997ae6b4fe3f0b3b158 upstream. + +Sold by O2 (telefonica germany) under the name "LTE4G" + +Tested-by: Thomas Schäfer +Signed-off-by: Bjørn Mork +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -936,6 +936,8 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), diff --git a/queue-3.5/usbdevfs-correct-amount-of-data-copied-to-user-in-processcompl_compat.patch b/queue-3.5/usbdevfs-correct-amount-of-data-copied-to-user-in-processcompl_compat.patch new file mode 100644 index 00000000000..a6ecdae308b --- /dev/null +++ b/queue-3.5/usbdevfs-correct-amount-of-data-copied-to-user-in-processcompl_compat.patch @@ -0,0 +1,41 @@ +From 2102e06a5f2e414694921f23591f072a5ba7db9f Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 4 Jul 2012 09:18:01 +0200 +Subject: usbdevfs: Correct amount of data copied to user in processcompl_compat + +From: Hans de Goede + +commit 2102e06a5f2e414694921f23591f072a5ba7db9f upstream. + +iso data buffers may have holes in them if some packets were short, so for +iso urbs we should always copy the entire buffer, just like the regular +processcompl does. + +Signed-off-by: Hans de Goede +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/devio.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -1604,10 +1604,14 @@ static int processcompl_compat(struct as + void __user *addr = as->userurb; + unsigned int i; + +- if (as->userbuffer && urb->actual_length) +- if (copy_to_user(as->userbuffer, urb->transfer_buffer, +- urb->actual_length)) ++ if (as->userbuffer && urb->actual_length) { ++ if (urb->number_of_packets > 0) /* Isochronous */ ++ i = urb->transfer_buffer_length; ++ else /* Non-Isoc */ ++ i = urb->actual_length; ++ if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) + return -EFAULT; ++ } + if (put_user(as->status, &userurb->status)) + return -EFAULT; + if (put_user(urb->actual_length, &userurb->actual_length)) -- 2.47.3