--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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)
--- /dev/null
+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;
--- /dev/null
+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) {
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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,
--- /dev/null
+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
--- /dev/null
+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;