]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
start .31 queue
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 15 Sep 2009 23:17:08 +0000 (16:17 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 15 Sep 2009 23:17:08 +0000 (16:17 -0700)
queue-2.6.31/ath5k-write-pcu-registers-on-initial-reset.patch [new file with mode: 0644]
queue-2.6.31/cfg80211-fix-looping-soft-lockup-in-find_ie.patch [new file with mode: 0644]
queue-2.6.31/mpt2sas-prevent-sending-command-to-fw-while-host-reset.patch [new file with mode: 0644]
queue-2.6.31/mpt2sas-raid-10-volume-is-showing-as-raid-1e-in-dmesg.patch [new file with mode: 0644]
queue-2.6.31/mpt2sas-rescan-topology-from-interrupt-context-instead-of-work-thread.patch [new file with mode: 0644]
queue-2.6.31/mpt2sas-setting-sdev-into-running-state-from-interrupt-context.patch [new file with mode: 0644]
queue-2.6.31/scsi-fix-oops-during-scsi-scanning.patch [new file with mode: 0644]
queue-2.6.31/scsi-libsrp-fix-memory-leak-in-srp_ring_free.patch [new file with mode: 0644]
queue-2.6.31/series [new file with mode: 0644]
queue-2.6.31/sg-fix-oops-in-the-error-path-in-sg_build_indirect.patch [new file with mode: 0644]

diff --git a/queue-2.6.31/ath5k-write-pcu-registers-on-initial-reset.patch b/queue-2.6.31/ath5k-write-pcu-registers-on-initial-reset.patch
new file mode 100644 (file)
index 0000000..ebf7410
--- /dev/null
@@ -0,0 +1,35 @@
+From 3355443ad7601991affa5992b0d53870335af765 Mon Sep 17 00:00:00 2001
+From: Bob Copeland <me@bobcopeland.com>
+Date: Sat, 4 Jul 2009 21:03:13 -0400
+Subject: ath5k: write PCU registers on initial reset
+
+From: Bob Copeland <me@bobcopeland.com>
+
+commit 3355443ad7601991affa5992b0d53870335af765 upstream.
+
+"Ath5k: unify resets"
+introduced a regression into 2.6.28 where the PCU registers are never
+initialized, due to ath5k_reset() always passing true for change_channel.
+We subsequently program a lot of these registers but several may start
+in an unknown state.
+
+Reported-by: Forrest Zhang <forrest@hifulltech.com>
+Signed-off-by: Bob Copeland <me@bobcopeland.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath5k/base.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -2676,7 +2676,7 @@ ath5k_reset(struct ath5k_softc *sc, stru
+               sc->curchan = chan;
+               sc->curband = &sc->sbands[chan->band];
+       }
+-      ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
++      ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL);
+       if (ret) {
+               ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
+               goto err;
diff --git a/queue-2.6.31/cfg80211-fix-looping-soft-lockup-in-find_ie.patch b/queue-2.6.31/cfg80211-fix-looping-soft-lockup-in-find_ie.patch
new file mode 100644 (file)
index 0000000..c9689ba
--- /dev/null
@@ -0,0 +1,83 @@
+From fcc6cb0c13555e78c2d47257b6d1b5e59b0c419a Mon Sep 17 00:00:00 2001
+From: Bob Copeland <me@bobcopeland.com>
+Date: Tue, 1 Sep 2009 18:12:11 -0400
+Subject: cfg80211: fix looping soft lockup in find_ie()
+
+From: Bob Copeland <me@bobcopeland.com>
+
+commit fcc6cb0c13555e78c2d47257b6d1b5e59b0c419a upstream.
+
+The find_ie() function uses a size_t for the len parameter, and
+directly uses len as a loop variable.  If any received packets
+are malformed, it is possible for the decrease of len to overflow,
+and since the result is unsigned, the loop will not terminate.
+Change it to a signed int so the loop conditional works for
+negative values.
+
+This fixes the following soft lockup:
+
+[38573.102007] BUG: soft lockup - CPU#0 stuck for 61s! [phy0:2230]
+[38573.102007] Modules linked in: aes_i586 aes_generic fuse af_packet ipt_REJECT xt_tcpudp nf_conntrack_ipv4 nf_defrag_ipv4 xt_state iptable_filter ip_tables x_tables acpi_cpufreq binfmt_misc dm_mirror dm_region_hash dm_log dm_multipath dm_mod kvm_intel kvm uinput i915 arc4 ecb drm snd_hda_codec_idt ath5k snd_hda_intel hid_apple mac80211 usbhid appletouch snd_hda_codec snd_pcm ath cfg80211 snd_timer i2c_algo_bit ohci1394 video snd processor ieee1394 rfkill ehci_hcd sg sky2 backlight snd_page_alloc uhci_hcd joydev output ac thermal button battery sr_mod applesmc cdrom input_polldev evdev unix [last unloaded: scsi_wait_scan]
+[38573.102007] irq event stamp: 2547724535
+[38573.102007] hardirqs last  enabled at (2547724534): [<c1002ffc>] restore_all_notrace+0x0/0x18
+[38573.102007] hardirqs last disabled at (2547724535): [<c10038f4>] apic_timer_interrupt+0x28/0x34
+[38573.102007] softirqs last  enabled at (92950144): [<c103ab48>] __do_softirq+0x108/0x210
+[38573.102007] softirqs last disabled at (92950274): [<c1348e74>] _spin_lock_bh+0x14/0x80
+[38573.102007]
+[38573.102007] Pid: 2230, comm: phy0 Tainted: G        W  (2.6.31-rc7-wl #8) MacBook1,1
+[38573.102007] EIP: 0060:[<f8ea2d50>] EFLAGS: 00010292 CPU: 0
+[38573.102007] EIP is at cmp_ies+0x30/0x180 [cfg80211]
+[38573.102007] EAX: 00000082 EBX: 00000000 ECX: ffffffc1 EDX: d8efd014
+[38573.102007] ESI: ffffff7c EDI: 0000004d EBP: eee2dc50 ESP: eee2dc3c
+[38573.102007]  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
+[38573.102007] CR0: 8005003b CR2: d8efd014 CR3: 01694000 CR4: 000026d0
+[38573.102007] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
+[38573.102007] DR6: ffff0ff0 DR7: 00000400
+[38573.102007] Call Trace:
+[38573.102007]  [<f8ea2f8d>] cmp_bss+0xed/0x100 [cfg80211]
+[38573.102007]  [<f8ea33e4>] cfg80211_bss_update+0x84/0x410 [cfg80211]
+[38573.102007]  [<f8ea3884>] cfg80211_inform_bss_frame+0x114/0x180 [cfg80211]
+[38573.102007]  [<f97255ff>] ieee80211_bss_info_update+0x4f/0x180 [mac80211]
+[38573.102007]  [<f972b118>] ieee80211_rx_bss_info+0x88/0xf0 [mac80211]
+[38573.102007]  [<f9739297>] ? ieee802_11_parse_elems+0x27/0x30 [mac80211]
+[38573.102007]  [<f972b224>] ieee80211_rx_mgmt_probe_resp+0xa4/0x1c0 [mac80211]
+[38573.102007]  [<f972bc59>] ieee80211_sta_rx_queued_mgmt+0x919/0xc50 [mac80211]
+[38573.102007]  [<c1009707>] ? sched_clock+0x27/0xa0
+[38573.102007]  [<c1009707>] ? sched_clock+0x27/0xa0
+[38573.102007]  [<c105ffd0>] ? mark_held_locks+0x60/0x80
+[38573.102007]  [<c1348be5>] ? _spin_unlock_irqrestore+0x55/0x70
+[38573.102007]  [<c134baa5>] ? sub_preempt_count+0x85/0xc0
+[38573.102007]  [<c1348bce>] ? _spin_unlock_irqrestore+0x3e/0x70
+[38573.102007]  [<c12c1c0f>] ? skb_dequeue+0x4f/0x70
+[38573.102007]  [<f972c021>] ieee80211_sta_work+0x91/0xb80 [mac80211]
+[38573.102007]  [<c1009707>] ? sched_clock+0x27/0xa0
+[38573.102007]  [<c134baa5>] ? sub_preempt_count+0x85/0xc0
+[38573.102007]  [<c10479af>] worker_thread+0x18f/0x320
+[38573.102007]  [<c104794e>] ? worker_thread+0x12e/0x320
+[38573.102007]  [<c1348be5>] ? _spin_unlock_irqrestore+0x55/0x70
+[38573.102007]  [<f972bf90>] ? ieee80211_sta_work+0x0/0xb80 [mac80211]
+[38573.102007]  [<c104cbb0>] ? autoremove_wake_function+0x0/0x50
+[38573.102007]  [<c1047820>] ? worker_thread+0x0/0x320
+[38573.102007]  [<c104c854>] kthread+0x84/0x90
+[38573.102007]  [<c104c7d0>] ? kthread+0x0/0x90
+[38573.102007]  [<c1003ab7>] kernel_thread_helper+0x7/0x10
+
+Signed-off-by: Bob Copeland <me@bobcopeland.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/wireless/scan.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -97,7 +97,7 @@ void cfg80211_bss_expire(struct cfg80211
+               dev->bss_generation++;
+ }
+-static u8 *find_ie(u8 num, u8 *ies, size_t len)
++static u8 *find_ie(u8 num, u8 *ies, int len)
+ {
+       while (len > 2 && ies[0] != num) {
+               len -= ies[1] + 2;
diff --git a/queue-2.6.31/mpt2sas-prevent-sending-command-to-fw-while-host-reset.patch b/queue-2.6.31/mpt2sas-prevent-sending-command-to-fw-while-host-reset.patch
new file mode 100644 (file)
index 0000000..7f4a434
--- /dev/null
@@ -0,0 +1,352 @@
+From 155dd4c763694222c125e65438d823f58ea653bc Mon Sep 17 00:00:00 2001
+From: Kashyap, Desai <kashyap.desai@lsi.com>
+Date: Thu, 20 Aug 2009 13:22:00 +0530
+Subject: [SCSI] mpt2sas: Prevent sending command to FW while Host Reset
+
+From: Kashyap, Desai <kashyap.desai@lsi.com>
+
+commit 155dd4c763694222c125e65438d823f58ea653bc upstream.
+
+This patch renames the flag for indicating host reset from
+ioc_reset_in_progress to shost_recovery. It also removes the spin locks
+surrounding the setting of this flag, which are unnecessary.   Sanity checks on
+the shost_recovery flag were added thru out the code so as to prevent sending
+firmware commands during host reset.  Also, the setting of the shost state to
+SHOST_RECOVERY was removed to prevent deadlocks, this is actually better
+handled by the shost_recovery flag.
+
+Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
+Reviewed-by: Eric Moore <Eric.moore@lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/mpt2sas/mpt2sas_base.c      |   13 ++--------
+ drivers/scsi/mpt2sas/mpt2sas_base.h      |    3 --
+ drivers/scsi/mpt2sas/mpt2sas_ctl.c       |   16 +-----------
+ drivers/scsi/mpt2sas/mpt2sas_scsih.c     |   40 ++++++++++++++++++-------------
+ drivers/scsi/mpt2sas/mpt2sas_transport.c |   29 +++++++++++++---------
+ 5 files changed, 47 insertions(+), 54 deletions(-)
+
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
+@@ -94,7 +94,7 @@ _base_fault_reset_work(struct work_struc
+       int rc;
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-      if (ioc->ioc_reset_in_progress)
++      if (ioc->shost_recovery)
+               goto rearm_timer;
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+@@ -3501,20 +3501,13 @@ mpt2sas_base_hard_reset_handler(struct M
+           __func__));
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-      if (ioc->ioc_reset_in_progress) {
++      if (ioc->shost_recovery) {
+               spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+               printk(MPT2SAS_ERR_FMT "%s: busy\n",
+                   ioc->name, __func__);
+               return -EBUSY;
+       }
+-      ioc->ioc_reset_in_progress = 1;
+       ioc->shost_recovery = 1;
+-      if (ioc->shost->shost_state == SHOST_RUNNING) {
+-              /* set back to SHOST_RUNNING in mpt2sas_scsih.c */
+-              scsi_host_set_state(ioc->shost, SHOST_RECOVERY);
+-              printk(MPT2SAS_INFO_FMT "putting controller into "
+-                  "SHOST_RECOVERY\n", ioc->name);
+-      }
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       _base_reset_handler(ioc, MPT2_IOC_PRE_RESET);
+@@ -3534,7 +3527,7 @@ mpt2sas_base_hard_reset_handler(struct M
+           ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-      ioc->ioc_reset_in_progress = 0;
++      ioc->shost_recovery = 0;
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       if (!r)
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
+@@ -432,7 +432,7 @@ typedef void (*MPT_ADD_SGE)(void *paddr,
+  * @fw_event_list: list of fw events
+  * @aen_event_read_flag: event log was read
+  * @broadcast_aen_busy: broadcast aen waiting to be serviced
+- * @ioc_reset_in_progress: host reset in progress
++ * @shost_recovery: host reset in progress
+  * @ioc_reset_in_progress_lock:
+  * @ioc_link_reset_in_progress: phy/hard reset in progress
+  * @ignore_loginfos: ignore loginfos during task managment
+@@ -545,7 +545,6 @@ struct MPT2SAS_ADAPTER {
+        /* misc flags */
+       int             aen_event_read_flag;
+       u8              broadcast_aen_busy;
+-      u8              ioc_reset_in_progress;
+       u8              shost_recovery;
+       spinlock_t      ioc_reset_in_progress_lock;
+       u8              ioc_link_reset_in_progress;
+--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+@@ -1963,7 +1963,6 @@ _ctl_ioctl_main(struct file *file, unsig
+ {
+       enum block_state state;
+       long ret = -EINVAL;
+-      unsigned long flags;
+       state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING :
+           BLOCKING;
+@@ -1989,13 +1988,8 @@ _ctl_ioctl_main(struct file *file, unsig
+                   !ioc)
+                       return -ENODEV;
+-              spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-              if (ioc->shost_recovery) {
+-                      spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
+-                          flags);
++              if (ioc->shost_recovery)
+                       return -EAGAIN;
+-              }
+-              spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
+                       uarg = arg;
+@@ -2098,7 +2092,6 @@ _ctl_compat_mpt_command(struct file *fil
+       struct mpt2_ioctl_command karg;
+       struct MPT2SAS_ADAPTER *ioc;
+       enum block_state state;
+-      unsigned long flags;
+       if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
+               return -EINVAL;
+@@ -2113,13 +2106,8 @@ _ctl_compat_mpt_command(struct file *fil
+       if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
+               return -ENODEV;
+-      spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-      if (ioc->shost_recovery) {
+-              spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
+-                  flags);
++      if (ioc->shost_recovery)
+               return -EAGAIN;
+-      }
+-      spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
+       karg.hdr.ioc_number = karg32.hdr.ioc_number;
+--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+@@ -1785,17 +1785,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_AD
+       u32 ioc_state;
+       unsigned long timeleft;
+       u8 VF_ID = 0;
+-      unsigned long flags;
+-      spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-      if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED ||
+-          ioc->shost_recovery) {
+-              spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
++      if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
++              printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
++                  __func__, ioc->name);
++              return;
++      }
++
++      if (ioc->shost_recovery) {
+               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return;
+       }
+-      spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
+       if (ioc_state & MPI2_DOORBELL_USED) {
+@@ -2553,7 +2554,6 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void
+       Mpi2SCSIIORequest_t *mpi_request;
+       u32 mpi_control;
+       u16 smid;
+-      unsigned long flags;
+       scmd->scsi_done = done;
+       sas_device_priv_data = scmd->device->hostdata;
+@@ -2572,13 +2572,10 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void
+       }
+       /* see if we are busy with task managment stuff */
+-      spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-      if (sas_target_priv_data->tm_busy ||
+-          ioc->shost_recovery || ioc->ioc_link_reset_in_progress) {
+-              spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
++      if (sas_target_priv_data->tm_busy)
++              return SCSI_MLQUEUE_DEVICE_BUSY;
++      else if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
+               return SCSI_MLQUEUE_HOST_BUSY;
+-      }
+-      spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       if (scmd->sc_data_direction == DMA_FROM_DEVICE)
+               mpi_control = MPI2_SCSIIO_CONTROL_READ;
+@@ -3374,6 +3371,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPT
+       if (!handle)
+               return -1;
++      if (ioc->shost_recovery)
++              return -1;
++
+       if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
+           MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
+               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+@@ -3510,6 +3510,9 @@ _scsih_expander_remove(struct MPT2SAS_AD
+       struct _sas_node *sas_expander;
+       unsigned long flags;
++      if (ioc->shost_recovery)
++              return;
++
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle);
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+@@ -3681,6 +3684,8 @@ _scsih_remove_device(struct MPT2SAS_ADAP
+               mutex_unlock(&ioc->tm_cmds.mutex);
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset "
+                   "done: handle(0x%04x)\n", ioc->name, device_handle));
++              if (ioc->shost_recovery)
++                      goto out;
+       }
+       /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */
+@@ -3846,6 +3851,8 @@ _scsih_sas_topology_change_event(struct 
+                           "expander event\n", ioc->name));
+                       return;
+               }
++              if (ioc->shost_recovery)
++                      return;
+               if (event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT)
+                       continue;
+@@ -5217,13 +5224,10 @@ _firmware_event_work(struct work_struct 
+       }
+       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+-      spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+       if (ioc->shost_recovery) {
+-              spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+               _scsih_fw_event_requeue(ioc, fw_event, 1000);
+               return;
+       }
+-      spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       switch (fw_event->event) {
+       case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+@@ -5425,6 +5429,8 @@ _scsih_expander_node_remove(struct MPT2S
+                       if (!sas_device)
+                               continue;
+                       _scsih_remove_device(ioc, sas_device->handle);
++                      if (ioc->shost_recovery)
++                              return;
+                       goto retry_device_search;
+               }
+       }
+@@ -5446,6 +5452,8 @@ _scsih_expander_node_remove(struct MPT2S
+                       if (!expander_sibling)
+                               continue;
+                       _scsih_expander_remove(ioc, expander_sibling->handle);
++                      if (ioc->shost_recovery)
++                              return;
+                       goto retry_expander_search;
+               }
+       }
+--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
+@@ -140,11 +140,18 @@ _transport_set_identify(struct MPT2SAS_A
+       u32 device_info;
+       u32 ioc_status;
++      if (ioc->shost_recovery) {
++              printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
++                  __func__, ioc->name);
++              return -EFAULT;
++      }
++
+       if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
++
+                   ioc->name, __FILE__, __LINE__, __func__);
+-              return -1;
++              return -ENXIO;
+       }
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+@@ -153,7 +160,7 @@ _transport_set_identify(struct MPT2SAS_A
+               printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
+                   "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
+                    __FILE__, __LINE__, __func__);
+-              return -1;
++              return -EIO;
+       }
+       memset(identify, 0, sizeof(identify));
+@@ -288,21 +295,17 @@ _transport_expander_report_manufacture(s
+       void *psge;
+       u32 sgl_flags;
+       u8 issue_reset = 0;
+-      unsigned long flags;
+       void *data_out = NULL;
+       dma_addr_t data_out_dma;
+       u32 sz;
+       u64 *sas_address_le;
+       u16 wait_state_count;
+-      spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-      if (ioc->ioc_reset_in_progress) {
+-              spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
++      if (ioc->shost_recovery) {
+               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return -EFAULT;
+       }
+-      spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       mutex_lock(&ioc->transport_cmds.mutex);
+@@ -806,6 +809,12 @@ mpt2sas_transport_update_phy_link_change
+       struct _sas_node *sas_node;
+       struct _sas_phy *mpt2sas_phy;
++      if (ioc->shost_recovery) {
++              printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
++                      __func__, ioc->name);
++              return;
++      }
++
+       spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       sas_node = _transport_sas_node_find_by_handle(ioc, handle);
+       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+@@ -1025,7 +1034,6 @@ _transport_smp_handler(struct Scsi_Host 
+       void *psge;
+       u32 sgl_flags;
+       u8 issue_reset = 0;
+-      unsigned long flags;
+       dma_addr_t dma_addr_in = 0;
+       dma_addr_t dma_addr_out = 0;
+       u16 wait_state_count;
+@@ -1045,14 +1053,11 @@ _transport_smp_handler(struct Scsi_Host 
+               return -EINVAL;
+       }
+-      spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-      if (ioc->ioc_reset_in_progress) {
+-              spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
++      if (ioc->shost_recovery) {
+               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return -EFAULT;
+       }
+-      spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
+       if (rc)
diff --git a/queue-2.6.31/mpt2sas-raid-10-volume-is-showing-as-raid-1e-in-dmesg.patch b/queue-2.6.31/mpt2sas-raid-10-volume-is-showing-as-raid-1e-in-dmesg.patch
new file mode 100644 (file)
index 0000000..d9a65ac
--- /dev/null
@@ -0,0 +1,220 @@
+From ed79f1280d1bc54f168abcffc8c3e0bf8ffb1873 Mon Sep 17 00:00:00 2001
+From: Kashyap, Desai <kashyap.desai@lsi.com>
+Date: Thu, 20 Aug 2009 13:23:49 +0530
+Subject: [SCSI] mpt2sas: Raid 10 Volume is showing as Raid 1E in dmesg
+
+From: Kashyap, Desai <kashyap.desai@lsi.com>
+
+commit ed79f1280d1bc54f168abcffc8c3e0bf8ffb1873 upstream.
+
+This patch modifies the slave_configure callback so the messages that get sent
+to system log for RAID1E volumes contain the string "RAID10" instead of
+"RAID1E". These messages contain information regarding what kind of scsi device
+is being added. Certain OEMS can enable displaying the RAID10 string instead of
+RAID1E via manufacturing page 10.   The driver will read this config page at
+driver load time, then determine from the GenericFlags0 bits whether display
+the RAID10 or RAID1E string, also even drive count is taken into consideration.
+
+Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
+Reviewed-by: Eric Moore <Eric.moore@lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/mpt2sas/mpt2sas_base.c   |    7 ++-
+ drivers/scsi/mpt2sas/mpt2sas_base.h   |   37 ++++++++++++++++++++
+ drivers/scsi/mpt2sas/mpt2sas_config.c |   61 ++++++++++++++++++++++++++++++++++
+ drivers/scsi/mpt2sas/mpt2sas_scsih.c  |    8 +++-
+ 4 files changed, 109 insertions(+), 4 deletions(-)
+
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
+@@ -1542,6 +1542,8 @@ _base_display_ioc_capabilities(struct MP
+          (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8,
+           ioc->bios_pg3.BiosVersion & 0x000000FF);
++      _base_display_dell_branding(ioc);
++
+       printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
+       if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
+@@ -1554,8 +1556,6 @@ _base_display_ioc_capabilities(struct MP
+               i++;
+       }
+-      _base_display_dell_branding(ioc);
+-
+       i = 0;
+       printk("), ");
+       printk("Capabilities=(");
+@@ -1627,6 +1627,9 @@ _base_static_config_pages(struct MPT2SAS
+       u32 iounit_pg1_flags;
+       mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
++      if (ioc->ir_firmware)
++              mpt2sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
++                  &ioc->manu_pg10);
+       mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
+       mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
+       mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
+@@ -197,6 +197,38 @@ struct MPT2SAS_TARGET {
+  * @block: device is in SDEV_BLOCK state
+  * @tlr_snoop_check: flag used in determining whether to disable TLR
+  */
++
++/* OEM Identifiers */
++#define MFG10_OEM_ID_INVALID                   (0x00000000)
++#define MFG10_OEM_ID_DELL                      (0x00000001)
++#define MFG10_OEM_ID_FSC                       (0x00000002)
++#define MFG10_OEM_ID_SUN                       (0x00000003)
++#define MFG10_OEM_ID_IBM                       (0x00000004)
++
++/* GENERIC Flags 0*/
++#define MFG10_GF0_OCE_DISABLED                 (0x00000001)
++#define MFG10_GF0_R1E_DRIVE_COUNT              (0x00000002)
++#define MFG10_GF0_R10_DISPLAY                  (0x00000004)
++#define MFG10_GF0_SSD_DATA_SCRUB_DISABLE       (0x00000008)
++#define MFG10_GF0_SINGLE_DRIVE_R0              (0x00000010)
++
++/* OEM Specific Flags will come from OEM specific header files */
++typedef struct _MPI2_CONFIG_PAGE_MAN_10 {
++    MPI2_CONFIG_PAGE_HEADER Header;                                 /* 00h */
++    U8                      OEMIdentifier;                          /* 04h */
++    U8                      Reserved1;                              /* 05h */
++    U16                     Reserved2;                              /* 08h */
++    U32                     Reserved3;                              /* 0Ch */
++    U32                     GenericFlags0;                          /* 10h */
++    U32                     GenericFlags1;                          /* 14h */
++    U32                     Reserved4;                              /* 18h */
++    U32                     OEMSpecificFlags0;                      /* 1Ch */
++    U32                     OEMSpecificFlags1;                      /* 20h */
++    U32                     Reserved5[18];                          /* 24h-60h*/
++} MPI2_CONFIG_PAGE_MAN_10,
++  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_10,
++  Mpi2ManufacturingPage10_t, MPI2_POINTER pMpi2ManufacturingPage10_t;
++
+ struct MPT2SAS_DEVICE {
+       struct MPT2SAS_TARGET *sas_target;
+       unsigned int    lun;
+@@ -461,6 +493,7 @@ typedef void (*MPT_ADD_SGE)(void *paddr,
+  * @facts: static facts data
+  * @pfacts: static port facts data
+  * @manu_pg0: static manufacturing page 0
++ * @manu_pg10: static manufacturing page 10
+  * @bios_pg2: static bios page 2
+  * @bios_pg3: static bios page 3
+  * @ioc_pg8: static ioc page 8
+@@ -663,6 +696,7 @@ struct MPT2SAS_ADAPTER {
+       dma_addr_t      diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT];
+       u8              diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT];
+       u32             unique_id[MPI2_DIAG_BUF_TYPE_COUNT];
++      Mpi2ManufacturingPage10_t manu_pg10;
+       u32             product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23];
+       u32             diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
+ };
+@@ -734,6 +768,8 @@ void mpt2sas_config_done(struct MPT2SAS_
+ int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys);
+ int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
+     Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page);
++int mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc,
++    Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page);
+ int mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+     *mpi_reply, Mpi2BiosPage2_t *config_page);
+ int mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+@@ -776,7 +812,6 @@ int mpt2sas_config_get_volume_handle(str
+     u16 *volume_handle);
+ int mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
+     u64 *wwid);
+-
+ /* ctl shared API */
+ extern struct device_attribute *mpt2sas_host_attrs[];
+ extern struct device_attribute *mpt2sas_dev_attrs[];
+--- a/drivers/scsi/mpt2sas/mpt2sas_config.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
+@@ -426,6 +426,67 @@ mpt2sas_config_get_manufacturing_pg0(str
+ }
+ /**
++ * mpt2sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
++ * @ioc: per adapter object
++ * @mpi_reply: reply mf payload returned from firmware
++ * @config_page: contents of the config page
++ * Context: sleep.
++ *
++ * Returns 0 for success, non-zero for failure.
++ */
++int
++mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc,
++    Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page)
++{
++      Mpi2ConfigRequest_t mpi_request;
++      int r;
++      struct config_request mem;
++
++      memset(config_page, 0, sizeof(Mpi2ManufacturingPage10_t));
++      memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
++      mpi_request.Function = MPI2_FUNCTION_CONFIG;
++      mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
++      mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
++      mpi_request.Header.PageNumber = 10;
++      mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
++      mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
++      r = _config_request(ioc, &mpi_request, mpi_reply,
++          MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
++      if (r)
++              goto out;
++
++      mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
++      mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
++      mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
++      mpi_request.Header.PageType = mpi_reply->Header.PageType;
++      mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
++      mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
++      if (mem.config_page_sz > ioc->config_page_sz) {
++              r = _config_alloc_config_dma_memory(ioc, &mem);
++              if (r)
++                      goto out;
++      } else {
++              mem.config_page_dma = ioc->config_page_dma;
++              mem.config_page = ioc->config_page;
++      }
++      ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
++          MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
++          mem.config_page_dma);
++      r = _config_request(ioc, &mpi_request, mpi_reply,
++          MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
++      if (!r)
++              memcpy(config_page, mem.config_page,
++                  min_t(u16, mem.config_page_sz,
++                  sizeof(Mpi2ManufacturingPage10_t)));
++
++      if (mem.config_page_sz > ioc->config_page_sz)
++              _config_free_config_dma_memory(ioc, &mem);
++
++ out:
++      return r;
++}
++
++/**
+  * mpt2sas_config_get_bios_pg2 - obtain bios page 2
+  * @ioc: per adapter object
+  * @mpi_reply: reply mf payload returned from firmware
+--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+@@ -1501,7 +1501,13 @@ _scsih_slave_configure(struct scsi_devic
+                       break;
+               case MPI2_RAID_VOL_TYPE_RAID1E:
+                       qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
+-                      r_level = "RAID1E";
++                      if (ioc->manu_pg10.OEMIdentifier &&
++                          (ioc->manu_pg10.GenericFlags0 &
++                          MFG10_GF0_R10_DISPLAY) &&
++                          !(raid_device->num_pds % 2))
++                              r_level = "RAID10";
++                      else
++                              r_level = "RAID1E";
+                       break;
+               case MPI2_RAID_VOL_TYPE_RAID1:
+                       qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
diff --git a/queue-2.6.31/mpt2sas-rescan-topology-from-interrupt-context-instead-of-work-thread.patch b/queue-2.6.31/mpt2sas-rescan-topology-from-interrupt-context-instead-of-work-thread.patch
new file mode 100644 (file)
index 0000000..9d335b2
--- /dev/null
@@ -0,0 +1,241 @@
+From cd4e12e8ad246ec5bc23ab04d0da0e6985025620 Mon Sep 17 00:00:00 2001
+From: Kashyap, Desai <kashyap.desai@lsi.com>
+Date: Thu, 20 Aug 2009 13:20:54 +0530
+Subject: [SCSI] mpt2sas : Rescan topology from Interrupt context instead of work thread
+
+From: Kashyap, Desai <kashyap.desai@lsi.com>
+
+commit cd4e12e8ad246ec5bc23ab04d0da0e6985025620 upstream.
+
+Following host reset its possible that the controller firmware could
+assign new handles for devices, as well as adding or deleting devices. There is
+code in the driver that will rescan the topology folowing host reset; updating
+device handles, and remove devices that are no longer responding. This patch
+will improve the responsivness by moving this rescaning from the delayed hotplug
+worker thread to immediately following the host reset.
+
+Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
+Reviewed-by: Eric Moore <Eric.moore@lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/mpt2sas/mpt2sas_base.c  |    3 
+ drivers/scsi/mpt2sas/mpt2sas_base.h  |    1 
+ drivers/scsi/mpt2sas/mpt2sas_scsih.c |  142 +++++++++++++----------------------
+ 3 files changed, 57 insertions(+), 89 deletions(-)
+
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
+@@ -3536,5 +3536,8 @@ mpt2sas_base_hard_reset_handler(struct M
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+       ioc->ioc_reset_in_progress = 0;
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
++
++      if (!r)
++              _base_reset_handler(ioc, MPT2_IOC_RUNNING);
+       return r;
+ }
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
+@@ -119,6 +119,7 @@
+ #define MPT2_IOC_PRE_RESET            1 /* prior to host reset */
+ #define MPT2_IOC_AFTER_RESET          2 /* just after host reset */
+ #define MPT2_IOC_DONE_RESET           3 /* links re-initialized */
++#define MPT2_IOC_RUNNING              4 /* shost running */
+ /*
+  * logging format
+--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+@@ -103,7 +103,6 @@ struct sense_info {
+ };
+-#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
+ /**
+  * struct fw_event_work - firmware event struct
+  * @list: link list framework
+@@ -2405,27 +2404,6 @@ _scsih_check_topo_delete_events(struct M
+ }
+ /**
+- * _scsih_queue_rescan - queue a topology rescan from user context
+- * @ioc: per adapter object
+- *
+- * Return nothing.
+- */
+-static void
+-_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc)
+-{
+-      struct fw_event_work *fw_event;
+-
+-      if (ioc->wait_for_port_enable_to_complete)
+-              return;
+-      fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+-      if (!fw_event)
+-              return;
+-      fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET;
+-      fw_event->ioc = ioc;
+-      _scsih_fw_event_add(ioc, fw_event);
+-}
+-
+-/**
+  * _scsih_flush_running_cmds - completing outstanding commands.
+  * @ioc: per adapter object
+  *
+@@ -2456,46 +2434,6 @@ _scsih_flush_running_cmds(struct MPT2SAS
+ }
+ /**
+- * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
+- * @ioc: per adapter object
+- * @reset_phase: phase
+- *
+- * The handler for doing any required cleanup or initialization.
+- *
+- * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
+- * MPT2_IOC_DONE_RESET
+- *
+- * Return nothing.
+- */
+-void
+-mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
+-{
+-      switch (reset_phase) {
+-      case MPT2_IOC_PRE_RESET:
+-              dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+-                  "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
+-              _scsih_fw_event_off(ioc);
+-              break;
+-      case MPT2_IOC_AFTER_RESET:
+-              dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+-                  "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
+-              if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
+-                      ioc->tm_cmds.status |= MPT2_CMD_RESET;
+-                      mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
+-                      complete(&ioc->tm_cmds.done);
+-              }
+-              _scsih_fw_event_on(ioc);
+-              _scsih_flush_running_cmds(ioc);
+-              break;
+-      case MPT2_IOC_DONE_RESET:
+-              dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+-                  "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
+-              _scsih_queue_rescan(ioc);
+-              break;
+-      }
+-}
+-
+-/**
+  * _scsih_setup_eedp - setup MPI request for EEDP transfer
+  * @scmd: pointer to scsi command object
+  * @mpi_request: pointer to the SCSI_IO reqest message frame
+@@ -5156,22 +5094,9 @@ static void
+ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
+ {
+       struct _sas_device *sas_device, *sas_device_next;
+-      struct _sas_node *sas_expander, *sas_expander_next;
++      struct _sas_node *sas_expander;
+       struct _raid_device *raid_device, *raid_device_next;
+-      unsigned long flags;
+-      _scsih_search_responding_sas_devices(ioc);
+-      _scsih_search_responding_raid_devices(ioc);
+-      _scsih_search_responding_expanders(ioc);
+-
+-      spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+-      ioc->shost_recovery = 0;
+-      if (ioc->shost->shost_state == SHOST_RECOVERY) {
+-              printk(MPT2SAS_INFO_FMT "putting controller into "
+-                  "SHOST_RUNNING\n", ioc->name);
+-              scsi_host_set_state(ioc->shost, SHOST_RUNNING);
+-      }
+-      spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       list_for_each_entry_safe(sas_device, sas_device_next,
+           &ioc->sas_device_list, list) {
+@@ -5207,16 +5132,63 @@ _scsih_remove_unresponding_devices(struc
+               _scsih_raid_device_remove(ioc, raid_device);
+       }
+-      list_for_each_entry_safe(sas_expander, sas_expander_next,
+-          &ioc->sas_expander_list, list) {
++ retry_expander_search:
++      sas_expander = NULL;
++      list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
+               if (sas_expander->responding) {
+                       sas_expander->responding = 0;
+                       continue;
+               }
+-              printk("\tremoving expander: handle(0x%04x), "
+-                  " sas_addr(0x%016llx)\n", sas_expander->handle,
+-                  (unsigned long long)sas_expander->sas_address);
+               _scsih_expander_remove(ioc, sas_expander->handle);
++              goto retry_expander_search;
++      }
++}
++
++/**
++ * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
++ * @ioc: per adapter object
++ * @reset_phase: phase
++ *
++ * The handler for doing any required cleanup or initialization.
++ *
++ * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
++ * MPT2_IOC_DONE_RESET
++ *
++ * Return nothing.
++ */
++void
++mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
++{
++      switch (reset_phase) {
++      case MPT2_IOC_PRE_RESET:
++              dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
++                  "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
++              _scsih_fw_event_off(ioc);
++              break;
++      case MPT2_IOC_AFTER_RESET:
++              dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
++                  "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
++              if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
++                      ioc->tm_cmds.status |= MPT2_CMD_RESET;
++                      mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
++                      complete(&ioc->tm_cmds.done);
++              }
++              _scsih_fw_event_on(ioc);
++              _scsih_flush_running_cmds(ioc);
++              break;
++      case MPT2_IOC_DONE_RESET:
++              dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
++                  "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
++              _scsih_sas_host_refresh(ioc, 0);
++              _scsih_search_responding_sas_devices(ioc);
++              _scsih_search_responding_raid_devices(ioc);
++              _scsih_search_responding_expanders(ioc);
++              break;
++      case MPT2_IOC_RUNNING:
++              dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
++                  "MPT2_IOC_RUNNING\n", ioc->name, __func__));
++              _scsih_remove_unresponding_devices(ioc);
++              break;
+       }
+ }
+@@ -5236,14 +5208,6 @@ _firmware_event_work(struct work_struct 
+       unsigned long flags;
+       struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
+-      /* This is invoked by calling _scsih_queue_rescan(). */
+-      if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) {
+-              _scsih_fw_event_free(ioc, fw_event);
+-              _scsih_sas_host_refresh(ioc, 1);
+-              _scsih_remove_unresponding_devices(ioc);
+-              return;
+-      }
+-
+       /* the queue is being flushed so ignore this event */
+       spin_lock_irqsave(&ioc->fw_event_lock, flags);
+       if (ioc->fw_events_off || ioc->remove_host) {
diff --git a/queue-2.6.31/mpt2sas-setting-sdev-into-running-state-from-interrupt-context.patch b/queue-2.6.31/mpt2sas-setting-sdev-into-running-state-from-interrupt-context.patch
new file mode 100644 (file)
index 0000000..b9da5ac
--- /dev/null
@@ -0,0 +1,99 @@
+From 34a03bef2202d0c9983a8da0a8abaee37d285847 Mon Sep 17 00:00:00 2001
+From: Kashyap, Desai <kashyap.desai@lsi.com>
+Date: Thu, 20 Aug 2009 13:23:19 +0530
+Subject: [SCSI] mpt2sas: setting SDEV into RUNNING state from Interrupt context
+
+From: Kashyap, Desai <kashyap.desai@lsi.com>
+
+commit 34a03bef2202d0c9983a8da0a8abaee37d285847 upstream.
+
+Changing SDEV Running state from interrupt context. Previously It was
+handle in work queue thread. With this change It will not wait for work
+queue thread to execute scsih_ublock_io_device to put SDEV into Running
+state. This will reduce delay for Device becoming RUNNING.
+
+Modified this patch considering James comment "Not to change SDEV state
+using  scsi_device_set_state API, instead use scsi_internal_device_unblock
+scsi_internal_device_block API"
+
+Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
+Reviewed-by: Eric Moore <Eric.moore@lsi.com>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/mpt2sas/mpt2sas_base.h  |    2 ++
+ drivers/scsi/mpt2sas/mpt2sas_scsih.c |   17 +++++++++++------
+ 2 files changed, 13 insertions(+), 6 deletions(-)
+
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
+@@ -802,5 +802,7 @@ void mpt2sas_transport_update_phy_link_c
+    u16 attached_handle, u8 phy_number, u8 link_rate);
+ extern struct sas_function_template mpt2sas_transport_functions;
+ extern struct scsi_transport_template *mpt2sas_transport_template;
++extern int scsi_internal_device_block(struct scsi_device *sdev);
++extern int scsi_internal_device_unblock(struct scsi_device *sdev);
+ #endif /* MPT2SAS_BASE_H_INCLUDED */
+--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+@@ -2222,7 +2222,7 @@ _scsih_ublock_io_device(struct MPT2SAS_A
+                           MPT2SAS_INFO_FMT "SDEV_RUNNING: "
+                           "handle(0x%04x)\n", ioc->name, handle));
+                       sas_device_priv_data->block = 0;
+-                      scsi_device_set_state(sdev, SDEV_RUNNING);
++                      scsi_internal_device_unblock(sdev);
+               }
+       }
+ }
+@@ -2251,7 +2251,7 @@ _scsih_block_io_device(struct MPT2SAS_AD
+                           MPT2SAS_INFO_FMT "SDEV_BLOCK: "
+                           "handle(0x%04x)\n", ioc->name, handle));
+                       sas_device_priv_data->block = 1;
+-                      scsi_device_set_state(sdev, SDEV_BLOCK);
++                      scsi_internal_device_block(sdev);
+               }
+       }
+ }
+@@ -2327,6 +2327,7 @@ _scsih_block_io_to_children_attached_dir
+       u16 handle;
+       u16 reason_code;
+       u8 phy_number;
++      u8 link_rate;
+       for (i = 0; i < event_data->NumEntries; i++) {
+               handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
+@@ -2337,6 +2338,11 @@ _scsih_block_io_to_children_attached_dir
+                   MPI2_EVENT_SAS_TOPO_RC_MASK;
+               if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
+                       _scsih_block_io_device(ioc, handle);
++              if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) {
++                      link_rate = event_data->PHY[i].LinkRate >> 4;
++                      if (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)
++                              _scsih_ublock_io_device(ioc, handle);
++              }
+       }
+ }
+@@ -3708,6 +3714,9 @@ _scsih_remove_device(struct MPT2SAS_ADAP
+           le32_to_cpu(mpi_reply.IOCLogInfo)));
+  out:
++
++      _scsih_ublock_io_device(ioc, handle);
++
+       mpt2sas_transport_port_remove(ioc, sas_device->sas_address,
+           sas_device->parent_handle);
+@@ -3887,10 +3896,6 @@ _scsih_sas_topology_change_event(struct 
+                                                  link_rate_);
+                               }
+                       }
+-                      if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) {
+-                              if (link_rate_ >= MPI2_SAS_NEG_LINK_RATE_1_5)
+-                                      _scsih_ublock_io_device(ioc, handle);
+-                      }
+                       if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) {
+                               if (link_rate_ < MPI2_SAS_NEG_LINK_RATE_1_5)
+                                       break;
diff --git a/queue-2.6.31/scsi-fix-oops-during-scsi-scanning.patch b/queue-2.6.31/scsi-fix-oops-during-scsi-scanning.patch
new file mode 100644 (file)
index 0000000..cc8f0bd
--- /dev/null
@@ -0,0 +1,105 @@
+From ea038f63ac52439e7816295fa6064fe95e6c1f51 Mon Sep 17 00:00:00 2001
+From: James Bottomley <James.Bottomley@suse.de>
+Date: Fri, 21 Aug 2009 09:47:54 -0600
+Subject: SCSI: fix oops during scsi scanning
+
+From: James Bottomley <James.Bottomley@suse.de>
+
+commit ea038f63ac52439e7816295fa6064fe95e6c1f51 upstream.
+
+Chris Webb reported:
+  p0# uname -a
+  Linux f7ea8425-d45b-490f-a738-d181d0df6963.host.elastichosts.com 2.6.30.4-elastic-lon-p #2 SMP PREEMPT Thu Aug 20 14:30:50 BST 2009 x86_64 Intel(R) Xeon(R) CPU E5420 @ 2.50GHz GenuineIntel GNU/Linux
+  p0# zgrep SCAN_ASYNC /proc/config.gz
+  # CONFIG_SCSI_SCAN_ASYNC is not set
+
+  p0# cat /var/log/kern/2009-08-20
+  [...]
+  15:27:10.485 kernel: scsi9 : iSCSI Initiator over TCP/IP
+  15:27:11.493 kernel: scsi 9:0:0:0: RAID              IET      Controller       0001 PQ: 0 ANSI: 5
+  15:27:11.493 kernel: scsi 9:0:0:0: Attached scsi generic sg6 type 12
+  15:27:11.495 kernel: scsi 9:0:0:1: Direct-Access     IET      VIRTUAL-DISK     0001 PQ: 0 ANSI: 5
+  15:27:11.495 kernel: sd 9:0:0:1: Attached scsi generic sg7 type 0
+  15:27:11.495 kernel: sd 9:0:0:1: [sdg] 4194304 512-byte hardware sectors: (2.14 GB/2.00 GiB)
+  15:27:11.495 kernel: sd 9:0:0:1: [sdg] Write Protect is off
+  15:27:11.495 kernel: sd 9:0:0:1: [sdg] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
+  15:27:13.012 kernel: sdg:<6>scsi 9:0:0:1: [sdg] Unhandled error code
+  15:27:13.012 kernel: scsi 9:0:0:1: [sdg] Result: hostbyte=0x07 driverbyte=0x00
+  15:27:13.012 kernel: end_request: I/O error, dev sdg, sector 0
+  15:27:13.012 kernel: Buffer I/O error on device sdg, logical block 0
+  15:27:13.012 kernel: ldm_validate_partition_table(): Disk read failed.
+  15:27:13.012 kernel: unable to read partition table
+  15:27:13.014 kernel: BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
+  15:27:13.014 kernel: IP: [<ffffffff803f0d77>] disk_part_iter_next+0x74/0xfd
+  15:27:13.014 kernel: PGD 82ad0b067 PUD 82cd7e067 PMD 0
+  15:27:13.014 kernel: Oops: 0000 [#1] PREEMPT SMP
+  15:27:13.014 kernel: last sysfs file: /sys/devices/platform/host9/session4/iscsi_session/session4/ifacename
+  15:27:13.014 kernel: CPU 5
+  15:27:13.014 kernel: Modules linked in:
+  15:27:13.014 kernel: Pid: 13999, comm: async/0 Not tainted 2.6.30.4-elastic-lon-p #2 X7DBN
+  15:27:13.014 kernel: RIP: 0010:[<ffffffff803f0d77>]  [<ffffffff803f0d77>] disk_part_iter_next+0x74/0xfd
+  15:27:13.014 kernel: RSP: 0018:ffff88066afa3dd0  EFLAGS: 00010246
+  15:27:13.014 kernel: RAX: ffff88082b58a000 RBX: ffff88066afa3e00 RCX: 0000000000000000
+  15:27:13.014 kernel: RDX: 0000000000000000 RSI: ffff88082b58a000 RDI: 0000000000000000
+  15:27:13.014 kernel: RBP: ffff88066afa3df0 R08: ffff88066afa2000 R09: ffff8806a204f000
+  15:27:13.014 kernel: R10: 000000fb12c7d274 R11: ffff8806c2bf0628 R12: ffff88066afa3e00
+  15:27:13.014 kernel: R13: ffff88082c829a00 R14: 0000000000000000 R15: ffff8806bc50c920
+  15:27:13.014 kernel: FS:  0000000000000000(0000) GS:ffff88002818a000(0000) knlGS:0000000000000000
+  15:27:13.014 kernel: CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
+  15:27:13.014 kernel: CR2: 0000000000000010 CR3: 000000082ade3000 CR4: 00000000000426e0
+  15:27:13.014 kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+  15:27:13.014 kernel: DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+  15:27:13.014 kernel: Process async/0 (pid: 13999, threadinfo ffff88066afa2000, task ffff8806c2bf05e0)
+  15:27:13.014 kernel: Stack:
+  15:27:13.014 kernel: 0000000000000000 ffff88066afa3e00 ffff88066afa3e00 ffff88082c829a00
+  15:27:13.014 kernel: ffff88066afa3e40 ffffffff80306feb ffff88082b58a000 0000000000000000
+  15:27:13.014 kernel: 0000000000000001 ffff8806bc50c920 ffff88066afa3e40 ffff88082b58a000
+  15:27:13.014 kernel: Call Trace:
+  15:27:13.014 kernel: [<ffffffff80306feb>] register_disk+0x122/0x13a
+  15:27:13.014 kernel: [<ffffffff803f0b0f>] add_disk+0xaa/0x106
+  15:27:13.014 kernel: [<ffffffff80493609>] sd_probe_async+0x198/0x25b
+  15:27:13.014 kernel: [<ffffffff80270482>] async_thread+0x10c/0x20d
+  15:27:13.014 kernel: [<ffffffff802545ff>] ? default_wake_function+0x0/0xf
+  15:27:13.014 kernel: [<ffffffff80270376>] ? async_thread+0x0/0x20d
+  15:27:13.014 kernel: [<ffffffff8026ad89>] kthread+0x55/0x80
+  15:27:13.014 kernel: [<ffffffff8022be6a>] child_rip+0xa/0x20
+  15:27:13.014 kernel: [<ffffffff8026ad34>] ? kthread+0x0/0x80
+  15:27:13.014 kernel: [<ffffffff8022be60>] ? child_rip+0x0/0x20
+  15:27:13.014 kernel: Code: c8 ff 80 e1 0c b9 00 00 00 00 0f 44 c1 41 83 cd ff 48 8d 7a 20 48 be ff ff ff ff 08 00 00 00 48 b9 00 00 00 00 08 00 00 00 eb 50 <8b> 42 10 41 bd 01 00 00 00 eb db 4c 63 c2 4e 8d 04 c7 4d 8b 20
+  15:27:13.015 kernel: RIP  [<ffffffff803f0d77>] disk_part_iter_next+0x74/0xfd
+  15:27:13.015 kernel: RSP <ffff88066afa3dd0>
+  15:27:13.015 kernel: CR2: 0000000000000010
+  15:27:13.015 kernel: ---[ end trace 6104b56ef5590e25 ]---
+
+The problem is caused because the async scanning split in sd.c doesn't hold
+any reference to the device when it kicks off the async piece.  What's
+happening is that an iSCSI disconnect is destorying the device again *before*
+the async sd scanning thread even starts.  Fix this by taking a reference
+before starting the thread and dropping it again when the thread completes.
+
+Reported-by: Chris Webb <chris@arachsys.com>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/sd.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -2021,6 +2021,7 @@ static void sd_probe_async(void *data, a
+       sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
+                 sdp->removable ? "removable " : "");
++      put_device(&sdkp->dev);
+ }
+ /**
+@@ -2106,6 +2107,7 @@ static int sd_probe(struct device *dev)
+       get_device(&sdp->sdev_gendev);
++      get_device(&sdkp->dev); /* prevent release before async_schedule */
+       async_schedule(sd_probe_async, sdkp);
+       return 0;
diff --git a/queue-2.6.31/scsi-libsrp-fix-memory-leak-in-srp_ring_free.patch b/queue-2.6.31/scsi-libsrp-fix-memory-leak-in-srp_ring_free.patch
new file mode 100644 (file)
index 0000000..c35be76
--- /dev/null
@@ -0,0 +1,39 @@
+From afffd3dabe5209882c8cc59a373a4d33b5db304a Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@gmail.com>
+Date: Sun, 30 Aug 2009 12:36:48 +0200
+Subject: SCSI: libsrp: fix memory leak in srp_ring_free()
+
+From: Bart Van Assche <bart.vanassche@gmail.com>
+
+commit afffd3dabe5209882c8cc59a373a4d33b5db304a upstream.
+
+This patch fixes a memory leak in the libsrp function srp_ring_free().
+It is not documented whether or not this function should free the ring
+pointer itself. But the source code of the callers of this function
+(srp_target_alloc() and srp_target_free()) makes it clear that
+srp_ring_free() should deallocate the ring pointer itself. Furthermore,
+the patch below makes srp_ring_free() deallocate all memory allocated by
+srp_ring_alloc().
+
+This patch affects the ibmvstgt driver, which is the only in-tree driver
+that calls the srp_ring_free() function (indirectly).
+
+Signed-off-by: Bart Van Assche <bart.vanassche@gmail.com>
+Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/libsrp.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/scsi/libsrp.c
++++ b/drivers/scsi/libsrp.c
+@@ -124,6 +124,7 @@ static void srp_ring_free(struct device 
+               dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
+               kfree(ring[i]);
+       }
++      kfree(ring);
+ }
+ int srp_target_alloc(struct srp_target *target, struct device *dev,
diff --git a/queue-2.6.31/series b/queue-2.6.31/series
new file mode 100644 (file)
index 0000000..177798e
--- /dev/null
@@ -0,0 +1,9 @@
+sg-fix-oops-in-the-error-path-in-sg_build_indirect.patch
+mpt2sas-rescan-topology-from-interrupt-context-instead-of-work-thread.patch
+mpt2sas-prevent-sending-command-to-fw-while-host-reset.patch
+mpt2sas-setting-sdev-into-running-state-from-interrupt-context.patch
+mpt2sas-raid-10-volume-is-showing-as-raid-1e-in-dmesg.patch
+scsi-fix-oops-during-scsi-scanning.patch
+scsi-libsrp-fix-memory-leak-in-srp_ring_free.patch
+cfg80211-fix-looping-soft-lockup-in-find_ie.patch
+ath5k-write-pcu-registers-on-initial-reset.patch
diff --git a/queue-2.6.31/sg-fix-oops-in-the-error-path-in-sg_build_indirect.patch b/queue-2.6.31/sg-fix-oops-in-the-error-path-in-sg_build_indirect.patch
new file mode 100644 (file)
index 0000000..aaca77a
--- /dev/null
@@ -0,0 +1,33 @@
+From e71044ee2efa4792e21d243b03d49006db66aec9 Mon Sep 17 00:00:00 2001
+From: Michal Schmidt <mschmidt@redhat.com>
+Date: Thu, 3 Sep 2009 14:27:08 +0200
+Subject: [SCSI] sg: fix oops in the error path in sg_build_indirect()
+
+From: Michal Schmidt <mschmidt@redhat.com>
+
+commit e71044ee2efa4792e21d243b03d49006db66aec9 upstream.
+
+When the allocation fails in sg_build_indirect(), an oops happens in
+the error path. It's caused by an obvious typo.
+
+Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
+Reported-by: Bob Tracy <rct@gherkin.frus.com>
+Acked-by: Douglas Gilbert <dgilbert@interlog.com>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/sg.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -1811,7 +1811,7 @@ retry:
+       return 0;
+ out:
+       for (i = 0; i < k; i++)
+-              __free_pages(schp->pages[k], order);
++              __free_pages(schp->pages[i], order);
+       if (--order >= 0)
+               goto retry;