From 2da951bc3848f6d1b07a7cd2fec73a22d7923e36 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 31 Jul 2012 12:29:55 -0700 Subject: [PATCH] 3.5-stable patches added patches: arm-dt-tegra-trimslice-add-vbus-gpio-property.patch arm-dt-tegra-trimslice-enable-usb2-port.patch arm-omap2-opp-fix-to-ensure-check-of-right-oppdef-after-bad-one.patch rt2800usb-2001-3c17-is-an-rt3370-device.patch scsi-avoid-dangling-pointer-in-scsi_requeue_command.patch scsi-fix-device-removal-null-pointer-dereference.patch scsi-fix-eh-wakeup-scsi_schedule_eh-vs-scsi_restart_operations.patch scsi-fix-hot-unplug-vs-async-scan-race.patch scsi-libsas-continue-revalidation.patch scsi-libsas-fix-sas_discover_devices-return-code-handling.patch smack-off-by-one-error.patch --- ...gra-trimslice-add-vbus-gpio-property.patch | 37 +++++ ...-dt-tegra-trimslice-enable-usb2-port.patch | 30 ++++ ...-check-of-right-oppdef-after-bad-one.patch | 57 +++++++ ...800usb-2001-3c17-is-an-rt3370-device.patch | 39 +++++ ...ling-pointer-in-scsi_requeue_command.patch | 55 +++++++ ...ice-removal-null-pointer-dereference.patch | 155 ++++++++++++++++++ ...hedule_eh-vs-scsi_restart_operations.patch | 59 +++++++ ...si-fix-hot-unplug-vs-async-scan-race.patch | 118 +++++++++++++ .../scsi-libsas-continue-revalidation.patch | 47 ++++++ ...iscover_devices-return-code-handling.patch | 126 ++++++++++++++ queue-3.5/series | 11 ++ queue-3.5/smack-off-by-one-error.patch | 45 +++++ 12 files changed, 779 insertions(+) create mode 100644 queue-3.5/arm-dt-tegra-trimslice-add-vbus-gpio-property.patch create mode 100644 queue-3.5/arm-dt-tegra-trimslice-enable-usb2-port.patch create mode 100644 queue-3.5/arm-omap2-opp-fix-to-ensure-check-of-right-oppdef-after-bad-one.patch create mode 100644 queue-3.5/rt2800usb-2001-3c17-is-an-rt3370-device.patch create mode 100644 queue-3.5/scsi-avoid-dangling-pointer-in-scsi_requeue_command.patch create mode 100644 queue-3.5/scsi-fix-device-removal-null-pointer-dereference.patch create mode 100644 queue-3.5/scsi-fix-eh-wakeup-scsi_schedule_eh-vs-scsi_restart_operations.patch create mode 100644 queue-3.5/scsi-fix-hot-unplug-vs-async-scan-race.patch create mode 100644 queue-3.5/scsi-libsas-continue-revalidation.patch create mode 100644 queue-3.5/scsi-libsas-fix-sas_discover_devices-return-code-handling.patch create mode 100644 queue-3.5/smack-off-by-one-error.patch diff --git a/queue-3.5/arm-dt-tegra-trimslice-add-vbus-gpio-property.patch b/queue-3.5/arm-dt-tegra-trimslice-add-vbus-gpio-property.patch new file mode 100644 index 00000000000..cb80406607b --- /dev/null +++ b/queue-3.5/arm-dt-tegra-trimslice-add-vbus-gpio-property.patch @@ -0,0 +1,37 @@ +From 01ad8063a5db9ac8320f197577a34b423ba64eca Mon Sep 17 00:00:00 2001 +From: Stephen Warren +Date: Wed, 25 Jul 2012 14:02:44 -0600 +Subject: ARM: dt: tegra trimslice: add vbus-gpio property + +From: Stephen Warren + +commit 01ad8063a5db9ac8320f197577a34b423ba64eca upstream. + +On TrimSlice, Tegra's USB1 port may be routed to either an external micro +USB port, or an internal USB->SATA bridge for SSD or HDD. This muxing is +controlled by a GPIO. Whilst not strictly a VBUS GPIO, the TrimSlice +board files caused this GPIO to be set appropriately to enable the SATA +bridge by passing it as the VBUS GPIO to the USB driver. Echo this same +configuration in device tree to enable the SATA bridge. + +An alternative might be to implement a full USB bus mux driver. However, +that seems over-complex right now. + +Signed-off-by: Stephen Warren +Signed-off-by: Arnd Bergmann +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/boot/dts/tegra-trimslice.dts | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/tegra-trimslice.dts ++++ b/arch/arm/boot/dts/tegra-trimslice.dts +@@ -276,6 +276,7 @@ + + usb@c5000000 { + status = "okay"; ++ nvidia,vbus-gpio = <&gpio 170 0>; /* gpio PV2 */ + }; + + usb@c5004000 { diff --git a/queue-3.5/arm-dt-tegra-trimslice-enable-usb2-port.patch b/queue-3.5/arm-dt-tegra-trimslice-enable-usb2-port.patch new file mode 100644 index 00000000000..fe4bd3c5d51 --- /dev/null +++ b/queue-3.5/arm-dt-tegra-trimslice-enable-usb2-port.patch @@ -0,0 +1,30 @@ +From a6a3dd1aed31ace7c827236c53d83f4e845dcff2 Mon Sep 17 00:00:00 2001 +From: Stephen Warren +Date: Wed, 25 Jul 2012 14:02:43 -0600 +Subject: ARM: dt: tegra trimslice: enable USB2 port + +From: Stephen Warren + +commit a6a3dd1aed31ace7c827236c53d83f4e845dcff2 upstream. + +This was accidentally disabled by commit 2a5fdc9 "ARM: dt: tegra: +invert status=disable vs status=okay". + +Signed-off-by: Stephen Warren +Signed-off-by: Arnd Bergmann +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/boot/dts/tegra-trimslice.dts | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/tegra-trimslice.dts ++++ b/arch/arm/boot/dts/tegra-trimslice.dts +@@ -279,6 +279,7 @@ + }; + + usb@c5004000 { ++ status = "okay"; + nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + }; + diff --git a/queue-3.5/arm-omap2-opp-fix-to-ensure-check-of-right-oppdef-after-bad-one.patch b/queue-3.5/arm-omap2-opp-fix-to-ensure-check-of-right-oppdef-after-bad-one.patch new file mode 100644 index 00000000000..6ccb712f385 --- /dev/null +++ b/queue-3.5/arm-omap2-opp-fix-to-ensure-check-of-right-oppdef-after-bad-one.patch @@ -0,0 +1,57 @@ +From b110547e586eb5825bc1d04aa9147bff83b57672 Mon Sep 17 00:00:00 2001 +From: Nishanth Menon +Date: Fri, 18 May 2012 12:26:19 -0500 +Subject: ARM: OMAP2+: OPP: Fix to ensure check of right oppdef after bad one + +From: Nishanth Menon + +commit b110547e586eb5825bc1d04aa9147bff83b57672 upstream. + +Commit 9fa2df6b90786301b175e264f5fa9846aba81a65 +(ARM: OMAP2+: OPP: allow OPP enumeration to continue if device is not present) +makes the logic: +for (i = 0; i < opp_def_size; i++) { + + if (!oh || !oh->od) { + + continue; + } + +opp_def++; +} + +In short, the moment we hit a "Bad OPP", we end up looping the list +comparing against the bad opp definition pointer for the rest of the +iteration count. Instead, increment opp_def in the for loop itself +and allow continue to be used in code without much thought so that +we check the next set of OPP definition pointers :) + +Cc: Steve Sakoman +Cc: Tony Lindgren +Signed-off-by: Nishanth Menon +Signed-off-by: Kevin Hilman +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-omap2/opp.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/arch/arm/mach-omap2/opp.c ++++ b/arch/arm/mach-omap2/opp.c +@@ -53,7 +53,7 @@ int __init omap_init_opp_table(struct om + omap_table_init = 1; + + /* Lets now register with OPP library */ +- for (i = 0; i < opp_def_size; i++) { ++ for (i = 0; i < opp_def_size; i++, opp_def++) { + struct omap_hwmod *oh; + struct device *dev; + +@@ -86,7 +86,6 @@ int __init omap_init_opp_table(struct om + __func__, opp_def->freq, + opp_def->hwmod_name, i, r); + } +- opp_def++; + } + + return 0; diff --git a/queue-3.5/rt2800usb-2001-3c17-is-an-rt3370-device.patch b/queue-3.5/rt2800usb-2001-3c17-is-an-rt3370-device.patch new file mode 100644 index 00000000000..7dcb4e11834 --- /dev/null +++ b/queue-3.5/rt2800usb-2001-3c17-is-an-rt3370-device.patch @@ -0,0 +1,39 @@ +From 8fd9d059af12786341dec5a688e607bcdb372238 Mon Sep 17 00:00:00 2001 +From: Albert Pool +Date: Mon, 14 May 2012 18:08:32 +0200 +Subject: rt2800usb: 2001:3c17 is an RT3370 device + +From: Albert Pool + +commit 8fd9d059af12786341dec5a688e607bcdb372238 upstream. + +D-Link DWA-123 rev A1 + +Signed-off-by: Albert Pool +Acked-by: Gertjan van Wingerde +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rt2x00/rt2800usb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -1137,6 +1137,8 @@ static struct usb_device_id rt2800usb_de + #ifdef CONFIG_RT2800USB_RT33XX + /* Belkin */ + { USB_DEVICE(0x050d, 0x945b) }, ++ /* D-Link */ ++ { USB_DEVICE(0x2001, 0x3c17) }, + /* Panasonic */ + { USB_DEVICE(0x083a, 0xb511) }, + /* Philips */ +@@ -1237,7 +1239,6 @@ static struct usb_device_id rt2800usb_de + /* D-Link */ + { USB_DEVICE(0x07d1, 0x3c0b) }, + { USB_DEVICE(0x07d1, 0x3c17) }, +- { USB_DEVICE(0x2001, 0x3c17) }, + /* Encore */ + { USB_DEVICE(0x203d, 0x14a1) }, + /* Gemtek */ diff --git a/queue-3.5/scsi-avoid-dangling-pointer-in-scsi_requeue_command.patch b/queue-3.5/scsi-avoid-dangling-pointer-in-scsi_requeue_command.patch new file mode 100644 index 00000000000..2739a721a98 --- /dev/null +++ b/queue-3.5/scsi-avoid-dangling-pointer-in-scsi_requeue_command.patch @@ -0,0 +1,55 @@ +From 940f5d47e2f2e1fa00443921a0abf4822335b54d Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Fri, 29 Jun 2012 15:34:26 +0000 +Subject: SCSI: Avoid dangling pointer in scsi_requeue_command() + +From: Bart Van Assche + +commit 940f5d47e2f2e1fa00443921a0abf4822335b54d upstream. + +When we call scsi_unprep_request() the command associated with the request +gets destroyed and therefore drops its reference on the device. If this was +the only reference, the device may get released and we end up with a NULL +pointer deref when we call blk_requeue_request. + +Reported-by: Mike Christie +Signed-off-by: Bart Van Assche +Reviewed-by: Mike Christie +Reviewed-by: Tejun Heo +[jejb: enhance commend and add commit log for stable] +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/scsi_lib.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -479,15 +479,26 @@ void scsi_requeue_run_queue(struct work_ + */ + static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) + { ++ struct scsi_device *sdev = cmd->device; + struct request *req = cmd->request; + unsigned long flags; + ++ /* ++ * We need to hold a reference on the device to avoid the queue being ++ * killed after the unlock and before scsi_run_queue is invoked which ++ * may happen because scsi_unprep_request() puts the command which ++ * releases its reference on the device. ++ */ ++ get_device(&sdev->sdev_gendev); ++ + spin_lock_irqsave(q->queue_lock, flags); + scsi_unprep_request(req); + blk_requeue_request(q, req); + spin_unlock_irqrestore(q->queue_lock, flags); + + scsi_run_queue(q); ++ ++ put_device(&sdev->sdev_gendev); + } + + void scsi_next_command(struct scsi_cmnd *cmd) diff --git a/queue-3.5/scsi-fix-device-removal-null-pointer-dereference.patch b/queue-3.5/scsi-fix-device-removal-null-pointer-dereference.patch new file mode 100644 index 00000000000..1c45c81e2bc --- /dev/null +++ b/queue-3.5/scsi-fix-device-removal-null-pointer-dereference.patch @@ -0,0 +1,155 @@ +From 67bd94130015c507011af37858989b199c52e1de Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Fri, 29 Jun 2012 15:33:22 +0000 +Subject: SCSI: Fix device removal NULL pointer dereference + +From: Bart Van Assche + +commit 67bd94130015c507011af37858989b199c52e1de upstream. + +Use blk_queue_dead() to test whether the queue is dead instead +of !sdev. Since scsi_prep_fn() may be invoked concurrently with +__scsi_remove_device(), keep the queuedata (sdev) pointer in +__scsi_remove_device(). This patch fixes a kernel oops that +can be triggered by USB device removal. See also +http://www.spinics.net/lists/linux-scsi/msg56254.html. + +Other changes included in this patch: +- Swap the blk_cleanup_queue() and kfree() calls in + scsi_host_dev_release() to make that code easier to grasp. +- Remove the queue dead check from scsi_run_queue() since the + queue state can change anyway at any point in that function + where the queue lock is not held. +- Remove the queue dead check from the start of scsi_request_fn() + since it is redundant with the scsi_device_online() check. + +Reported-by: Jun'ichi Nomura +Signed-off-by: Bart Van Assche +Reviewed-by: Mike Christie +Reviewed-by: Tejun Heo +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/hosts.c | 7 ++++--- + drivers/scsi/scsi_lib.c | 32 ++++---------------------------- + drivers/scsi/scsi_priv.h | 1 - + drivers/scsi/scsi_sysfs.c | 5 +---- + 4 files changed, 9 insertions(+), 36 deletions(-) + +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -290,6 +290,7 @@ static void scsi_host_dev_release(struct + struct Scsi_Host *shost = dev_to_shost(dev); + struct device *parent = dev->parent; + struct request_queue *q; ++ void *queuedata; + + scsi_proc_hostdir_rm(shost->hostt); + +@@ -299,9 +300,9 @@ static void scsi_host_dev_release(struct + destroy_workqueue(shost->work_q); + q = shost->uspace_req_q; + if (q) { +- kfree(q->queuedata); +- q->queuedata = NULL; +- scsi_free_queue(q); ++ queuedata = q->queuedata; ++ blk_cleanup_queue(q); ++ kfree(queuedata); + } + + scsi_destroy_command_freelist(shost); +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -406,10 +406,6 @@ static void scsi_run_queue(struct reques + LIST_HEAD(starved_list); + unsigned long flags; + +- /* if the device is dead, sdev will be NULL, so no queue to run */ +- if (!sdev) +- return; +- + shost = sdev->host; + if (scsi_target(sdev)->single_lun) + scsi_single_lun_run(sdev); +@@ -1370,16 +1366,16 @@ static inline int scsi_host_queue_ready( + * may be changed after request stacking drivers call the function, + * regardless of taking lock or not. + * +- * When scsi can't dispatch I/Os anymore and needs to kill I/Os +- * (e.g. !sdev), scsi needs to return 'not busy'. +- * Otherwise, request stacking drivers may hold requests forever. ++ * When scsi can't dispatch I/Os anymore and needs to kill I/Os scsi ++ * needs to return 'not busy'. Otherwise, request stacking drivers ++ * may hold requests forever. + */ + static int scsi_lld_busy(struct request_queue *q) + { + struct scsi_device *sdev = q->queuedata; + struct Scsi_Host *shost; + +- if (!sdev) ++ if (blk_queue_dead(q)) + return 0; + + shost = sdev->host; +@@ -1490,12 +1486,6 @@ static void scsi_request_fn(struct reque + struct scsi_cmnd *cmd; + struct request *req; + +- if (!sdev) { +- while ((req = blk_peek_request(q)) != NULL) +- scsi_kill_request(req, q); +- return; +- } +- + if(!get_device(&sdev->sdev_gendev)) + /* We must be tearing the block queue down already */ + return; +@@ -1697,20 +1687,6 @@ struct request_queue *scsi_alloc_queue(s + return q; + } + +-void scsi_free_queue(struct request_queue *q) +-{ +- unsigned long flags; +- +- WARN_ON(q->queuedata); +- +- /* cause scsi_request_fn() to kill all non-finished requests */ +- spin_lock_irqsave(q->queue_lock, flags); +- q->request_fn(q); +- spin_unlock_irqrestore(q->queue_lock, flags); +- +- blk_cleanup_queue(q); +-} +- + /* + * Function: scsi_block_requests() + * +--- a/drivers/scsi/scsi_priv.h ++++ b/drivers/scsi/scsi_priv.h +@@ -84,7 +84,6 @@ extern void scsi_next_command(struct scs + extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); + extern void scsi_run_host_queues(struct Scsi_Host *shost); + extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); +-extern void scsi_free_queue(struct request_queue *q); + extern int scsi_init_queue(void); + extern void scsi_exit_queue(void); + struct request_queue; +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -971,11 +971,8 @@ void __scsi_remove_device(struct scsi_de + sdev->host->hostt->slave_destroy(sdev); + transport_destroy_device(dev); + +- /* cause the request function to reject all I/O requests */ +- sdev->request_queue->queuedata = NULL; +- + /* Freeing the queue signals to block that we're done */ +- scsi_free_queue(sdev->request_queue); ++ blk_cleanup_queue(sdev->request_queue); + put_device(dev); + } + diff --git a/queue-3.5/scsi-fix-eh-wakeup-scsi_schedule_eh-vs-scsi_restart_operations.patch b/queue-3.5/scsi-fix-eh-wakeup-scsi_schedule_eh-vs-scsi_restart_operations.patch new file mode 100644 index 00000000000..b21a85ceaea --- /dev/null +++ b/queue-3.5/scsi-fix-eh-wakeup-scsi_schedule_eh-vs-scsi_restart_operations.patch @@ -0,0 +1,59 @@ +From 57fc2e335fd3c2f898ee73570dc81426c28dc7b4 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Thu, 21 Jun 2012 23:25:32 -0700 +Subject: SCSI: fix eh wakeup (scsi_schedule_eh vs scsi_restart_operations) + +From: Dan Williams + +commit 57fc2e335fd3c2f898ee73570dc81426c28dc7b4 upstream. + +Rapid ata hotplug on a libsas controller results in cases where libsas +is waiting indefinitely on eh to perform an ata probe. + +A race exists between scsi_schedule_eh() and scsi_restart_operations() +in the case when scsi_restart_operations() issues i/o to other devices +in the sas domain. When this happens the host state transitions from +SHOST_RECOVERY (set by scsi_schedule_eh) back to SHOST_RUNNING and +->host_busy is non-zero so we put the eh thread to sleep even though +->host_eh_scheduled is active. + +Before putting the error handler to sleep we need to check if the +host_state needs to return to SHOST_RECOVERY for another trip through +eh. Since i/o that is released by scsi_restart_operations has been +blocked for at least one eh cycle, this implementation allows those +i/o's to run before another eh cycle starts to discourage hung task +timeouts. + +Reported-by: Tom Jackson +Tested-by: Tom Jackson +Signed-off-by: Dan Williams +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/scsi_error.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -1687,6 +1687,20 @@ static void scsi_restart_operations(stru + * requests are started. + */ + scsi_run_host_queues(shost); ++ ++ /* ++ * if eh is active and host_eh_scheduled is pending we need to re-run ++ * recovery. we do this check after scsi_run_host_queues() to allow ++ * everything pent up since the last eh run a chance to make forward ++ * progress before we sync again. Either we'll immediately re-run ++ * recovery or scsi_device_unbusy() will wake us again when these ++ * pending commands complete. ++ */ ++ spin_lock_irqsave(shost->host_lock, flags); ++ if (shost->host_eh_scheduled) ++ if (scsi_host_set_state(shost, SHOST_RECOVERY)) ++ WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)); ++ spin_unlock_irqrestore(shost->host_lock, flags); + } + + /** diff --git a/queue-3.5/scsi-fix-hot-unplug-vs-async-scan-race.patch b/queue-3.5/scsi-fix-hot-unplug-vs-async-scan-race.patch new file mode 100644 index 00000000000..f0f8b9cbeeb --- /dev/null +++ b/queue-3.5/scsi-fix-hot-unplug-vs-async-scan-race.patch @@ -0,0 +1,118 @@ +From 3b661a92e869ebe2358de8f4b3230ad84f7fce51 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Thu, 21 Jun 2012 23:47:28 -0700 +Subject: SCSI: fix hot unplug vs async scan race + +From: Dan Williams + +commit 3b661a92e869ebe2358de8f4b3230ad84f7fce51 upstream. + +The following crash results from cases where the end_device has been +removed before scsi_sysfs_add_sdev has had a chance to run. + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000098 + IP: [] sysfs_create_dir+0x32/0xb6 + ... + Call Trace: + [] kobject_add_internal+0x120/0x1e3 + [] ? trace_hardirqs_on+0xd/0xf + [] kobject_add_varg+0x41/0x50 + [] kobject_add+0x64/0x66 + [] device_add+0x12d/0x63a + [] ? _raw_spin_unlock_irqrestore+0x47/0x56 + [] ? module_refcount+0x89/0xa0 + [] scsi_sysfs_add_sdev+0x4e/0x28a + [] do_scan_async+0x9c/0x145 + +...teach scsi_sysfs_add_devices() to check for deleted devices() before +trying to add them, and teach scsi_remove_target() how to remove targets +that have not been added via device_add(). + +Reported-by: Dariusz Majchrzak +Signed-off-by: Dan Williams +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/scsi_scan.c | 3 +++ + drivers/scsi/scsi_sysfs.c | 41 ++++++++++++++++++++++++++--------------- + 2 files changed, 29 insertions(+), 15 deletions(-) + +--- a/drivers/scsi/scsi_scan.c ++++ b/drivers/scsi/scsi_scan.c +@@ -1717,6 +1717,9 @@ static void scsi_sysfs_add_devices(struc + { + struct scsi_device *sdev; + shost_for_each_device(sdev, shost) { ++ /* target removed before the device could be added */ ++ if (sdev->sdev_state == SDEV_DEL) ++ continue; + if (!scsi_host_scan_allowed(shost) || + scsi_sysfs_add_sdev(sdev) != 0) + __scsi_remove_device(sdev); +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -1000,7 +1000,6 @@ static void __scsi_remove_target(struct + struct scsi_device *sdev; + + spin_lock_irqsave(shost->host_lock, flags); +- starget->reap_ref++; + restart: + list_for_each_entry(sdev, &shost->__devices, siblings) { + if (sdev->channel != starget->channel || +@@ -1014,14 +1013,6 @@ static void __scsi_remove_target(struct + goto restart; + } + spin_unlock_irqrestore(shost->host_lock, flags); +- scsi_target_reap(starget); +-} +- +-static int __remove_child (struct device * dev, void * data) +-{ +- if (scsi_is_target_device(dev)) +- __scsi_remove_target(to_scsi_target(dev)); +- return 0; + } + + /** +@@ -1034,14 +1025,34 @@ static int __remove_child (struct device + */ + void scsi_remove_target(struct device *dev) + { +- if (scsi_is_target_device(dev)) { +- __scsi_remove_target(to_scsi_target(dev)); +- return; ++ struct Scsi_Host *shost = dev_to_shost(dev->parent); ++ struct scsi_target *starget, *found; ++ unsigned long flags; ++ ++ restart: ++ found = NULL; ++ spin_lock_irqsave(shost->host_lock, flags); ++ list_for_each_entry(starget, &shost->__targets, siblings) { ++ if (starget->state == STARGET_DEL) ++ continue; ++ if (starget->dev.parent == dev || &starget->dev == dev) { ++ found = starget; ++ found->reap_ref++; ++ break; ++ } + } ++ spin_unlock_irqrestore(shost->host_lock, flags); + +- get_device(dev); +- device_for_each_child(dev, NULL, __remove_child); +- put_device(dev); ++ if (found) { ++ __scsi_remove_target(found); ++ scsi_target_reap(found); ++ /* in the case where @dev has multiple starget children, ++ * continue removing. ++ * ++ * FIXME: does such a case exist? ++ */ ++ goto restart; ++ } + } + EXPORT_SYMBOL(scsi_remove_target); + diff --git a/queue-3.5/scsi-libsas-continue-revalidation.patch b/queue-3.5/scsi-libsas-continue-revalidation.patch new file mode 100644 index 00000000000..22ceb7fdb99 --- /dev/null +++ b/queue-3.5/scsi-libsas-continue-revalidation.patch @@ -0,0 +1,47 @@ +From 26f2f199ff150d8876b2641c41e60d1c92d2fb81 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Thu, 21 Jun 2012 23:36:15 -0700 +Subject: SCSI: libsas: continue revalidation + +From: Dan Williams + +commit 26f2f199ff150d8876b2641c41e60d1c92d2fb81 upstream. + +Continue running revalidation until no more broadcast devices are +discovered. Fixes cases where re-discovery completes too early in a +domain with multiple expanders with pending re-discovery events. +Servicing BCNs can get backed up behind error recovery. + +Signed-off-by: Dan Williams +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/libsas/sas_expander.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -2109,9 +2109,7 @@ int sas_ex_revalidate_domain(struct doma + struct domain_device *dev = NULL; + + res = sas_find_bcast_dev(port_dev, &dev); +- if (res) +- goto out; +- if (dev) { ++ while (res == 0 && dev) { + struct expander_device *ex = &dev->ex_dev; + int i = 0, phy_id; + +@@ -2123,8 +2121,10 @@ int sas_ex_revalidate_domain(struct doma + res = sas_rediscover(dev, phy_id); + i = phy_id + 1; + } while (i < ex->num_phys); ++ ++ dev = NULL; ++ res = sas_find_bcast_dev(port_dev, &dev); + } +-out: + return res; + } + diff --git a/queue-3.5/scsi-libsas-fix-sas_discover_devices-return-code-handling.patch b/queue-3.5/scsi-libsas-fix-sas_discover_devices-return-code-handling.patch new file mode 100644 index 00000000000..86c2ea285e3 --- /dev/null +++ b/queue-3.5/scsi-libsas-fix-sas_discover_devices-return-code-handling.patch @@ -0,0 +1,126 @@ +From b17caa174a7e1fd2e17b26e210d4ee91c4c28b37 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Thu, 21 Jun 2012 23:36:20 -0700 +Subject: SCSI: libsas: fix sas_discover_devices return code handling + +From: Dan Williams + +commit b17caa174a7e1fd2e17b26e210d4ee91c4c28b37 upstream. + +commit 198439e4 [SCSI] libsas: do not set res = 0 in sas_ex_discover_dev() +commit 19252de6 [SCSI] libsas: fix wide port hotplug issues + +The above commits seem to have confused the return value of +sas_ex_discover_dev which is non-zero on failure and +sas_ex_join_wide_port which just indicates short circuiting discovery on +already established ports. The result is random discovery failures +depending on configuration. + +Calls to sas_ex_join_wide_port are the source of the trouble as its +return value is errantly assigned to 'res'. Convert it to bool and stop +returning its result up the stack. + +Tested-by: Dan Melnic +Reported-by: Dan Melnic +Signed-off-by: Dan Williams +Reviewed-by: Jack Wang +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/libsas/sas_expander.c | 39 +++++++++++-------------------------- + 1 file changed, 12 insertions(+), 27 deletions(-) + +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -868,7 +868,7 @@ static struct domain_device *sas_ex_disc + } + + /* See if this phy is part of a wide port */ +-static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) ++static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id) + { + struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; + int i; +@@ -884,11 +884,11 @@ static int sas_ex_join_wide_port(struct + sas_port_add_phy(ephy->port, phy->phy); + phy->port = ephy->port; + phy->phy_state = PHY_DEVICE_DISCOVERED; +- return 0; ++ return true; + } + } + +- return -ENODEV; ++ return false; + } + + static struct domain_device *sas_ex_discover_expander( +@@ -1030,8 +1030,7 @@ static int sas_ex_discover_dev(struct do + return res; + } + +- res = sas_ex_join_wide_port(dev, phy_id); +- if (!res) { ++ if (sas_ex_join_wide_port(dev, phy_id)) { + SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", + phy_id, SAS_ADDR(ex_phy->attached_sas_addr)); + return res; +@@ -1077,8 +1076,7 @@ static int sas_ex_discover_dev(struct do + if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == + SAS_ADDR(child->sas_addr)) { + ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; +- res = sas_ex_join_wide_port(dev, i); +- if (!res) ++ if (sas_ex_join_wide_port(dev, i)) + SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", + i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); + +@@ -1943,32 +1941,20 @@ static int sas_discover_new(struct domai + { + struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; + struct domain_device *child; +- bool found = false; +- int res, i; ++ int res; + + SAS_DPRINTK("ex %016llx phy%d new device attached\n", + SAS_ADDR(dev->sas_addr), phy_id); + res = sas_ex_phy_discover(dev, phy_id); + if (res) +- goto out; +- /* to support the wide port inserted */ +- for (i = 0; i < dev->ex_dev.num_phys; i++) { +- struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i]; +- if (i == phy_id) +- continue; +- if (SAS_ADDR(ex_phy_temp->attached_sas_addr) == +- SAS_ADDR(ex_phy->attached_sas_addr)) { +- found = true; +- break; +- } +- } +- if (found) { +- sas_ex_join_wide_port(dev, phy_id); ++ return res; ++ ++ if (sas_ex_join_wide_port(dev, phy_id)) + return 0; +- } ++ + res = sas_ex_discover_devices(dev, phy_id); +- if (!res) +- goto out; ++ if (res) ++ return res; + list_for_each_entry(child, &dev->ex_dev.children, siblings) { + if (SAS_ADDR(child->sas_addr) == + SAS_ADDR(ex_phy->attached_sas_addr)) { +@@ -1978,7 +1964,6 @@ static int sas_discover_new(struct domai + break; + } + } +-out: + return res; + } + diff --git a/queue-3.5/series b/queue-3.5/series index b4d7b312c10..dcaba3852f5 100644 --- a/queue-3.5/series +++ b/queue-3.5/series @@ -7,3 +7,14 @@ powerpc-add-memory-attribute-for-mfmsr.patch powerpc-eeh-check-handle_eeh_events-return-value.patch be2net-missing-byteswap-in-be_get_fw_log_level-causes-oops-on-powerpc.patch powerpc-85xx-use-the-brx-registers-to-enable-indirect-mode-on-the-p1022ds.patch +smack-off-by-one-error.patch +scsi-libsas-continue-revalidation.patch +scsi-libsas-fix-sas_discover_devices-return-code-handling.patch +scsi-fix-eh-wakeup-scsi_schedule_eh-vs-scsi_restart_operations.patch +scsi-fix-hot-unplug-vs-async-scan-race.patch +scsi-fix-device-removal-null-pointer-dereference.patch +scsi-avoid-dangling-pointer-in-scsi_requeue_command.patch +rt2800usb-2001-3c17-is-an-rt3370-device.patch +arm-dt-tegra-trimslice-enable-usb2-port.patch +arm-omap2-opp-fix-to-ensure-check-of-right-oppdef-after-bad-one.patch +arm-dt-tegra-trimslice-add-vbus-gpio-property.patch diff --git a/queue-3.5/smack-off-by-one-error.patch b/queue-3.5/smack-off-by-one-error.patch new file mode 100644 index 00000000000..2cda202752f --- /dev/null +++ b/queue-3.5/smack-off-by-one-error.patch @@ -0,0 +1,45 @@ +From 3b9fc37280c521b086943f9aedda767f5bf3b2d3 Mon Sep 17 00:00:00 2001 +From: Alan Cox +Date: Thu, 26 Jul 2012 14:47:11 -0700 +Subject: smack: off by one error + +From: Alan Cox + +commit 3b9fc37280c521b086943f9aedda767f5bf3b2d3 upstream. + +Consider the input case of a rule that consists entirely of non space +symbols followed by a \0. Say 64 + \0 + +In this case strlen(data) = 64 +kzalloc of subject and object are 64 byte objects +sscanfdata, "%s %s %s", subject, ...) + +will put 65 bytes into subject. + +Signed-off-by: Alan Cox +Acked-by: Casey Schaufler +Signed-off-by: James Morris +Signed-off-by: Greg Kroah-Hartman + +--- + security/smack/smackfs.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -325,11 +325,11 @@ static int smk_parse_long_rule(const cha + int datalen; + int rc = -1; + +- /* +- * This is probably inefficient, but safe. +- */ ++ /* This is inefficient */ + datalen = strlen(data); +- subject = kzalloc(datalen, GFP_KERNEL); ++ ++ /* Our first element can be 64 + \0 with no spaces */ ++ subject = kzalloc(datalen + 1, GFP_KERNEL); + if (subject == NULL) + return -1; + object = kzalloc(datalen, GFP_KERNEL); -- 2.47.3