From: Greg Kroah-Hartman Date: Tue, 15 Sep 2009 23:17:08 +0000 (-0700) Subject: start .31 queue X-Git-Tag: v2.6.30.8~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cb9f7961eb31fff773e466b90275cace37099fd2;p=thirdparty%2Fkernel%2Fstable-queue.git start .31 queue --- 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 index 00000000000..ebf7410cbb8 --- /dev/null +++ b/queue-2.6.31/ath5k-write-pcu-registers-on-initial-reset.patch @@ -0,0 +1,35 @@ +From 3355443ad7601991affa5992b0d53870335af765 Mon Sep 17 00:00:00 2001 +From: Bob Copeland +Date: Sat, 4 Jul 2009 21:03:13 -0400 +Subject: ath5k: write PCU registers on initial reset + +From: Bob Copeland + +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 +Signed-off-by: Bob Copeland +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..c9689bacff5 --- /dev/null +++ b/queue-2.6.31/cfg80211-fix-looping-soft-lockup-in-find_ie.patch @@ -0,0 +1,83 @@ +From fcc6cb0c13555e78c2d47257b6d1b5e59b0c419a Mon Sep 17 00:00:00 2001 +From: Bob Copeland +Date: Tue, 1 Sep 2009 18:12:11 -0400 +Subject: cfg80211: fix looping soft lockup in find_ie() + +From: Bob Copeland + +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): [] restore_all_notrace+0x0/0x18 +[38573.102007] hardirqs last disabled at (2547724535): [] apic_timer_interrupt+0x28/0x34 +[38573.102007] softirqs last enabled at (92950144): [] __do_softirq+0x108/0x210 +[38573.102007] softirqs last disabled at (92950274): [] _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:[] 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] [] cmp_bss+0xed/0x100 [cfg80211] +[38573.102007] [] cfg80211_bss_update+0x84/0x410 [cfg80211] +[38573.102007] [] cfg80211_inform_bss_frame+0x114/0x180 [cfg80211] +[38573.102007] [] ieee80211_bss_info_update+0x4f/0x180 [mac80211] +[38573.102007] [] ieee80211_rx_bss_info+0x88/0xf0 [mac80211] +[38573.102007] [] ? ieee802_11_parse_elems+0x27/0x30 [mac80211] +[38573.102007] [] ieee80211_rx_mgmt_probe_resp+0xa4/0x1c0 [mac80211] +[38573.102007] [] ieee80211_sta_rx_queued_mgmt+0x919/0xc50 [mac80211] +[38573.102007] [] ? sched_clock+0x27/0xa0 +[38573.102007] [] ? sched_clock+0x27/0xa0 +[38573.102007] [] ? mark_held_locks+0x60/0x80 +[38573.102007] [] ? _spin_unlock_irqrestore+0x55/0x70 +[38573.102007] [] ? sub_preempt_count+0x85/0xc0 +[38573.102007] [] ? _spin_unlock_irqrestore+0x3e/0x70 +[38573.102007] [] ? skb_dequeue+0x4f/0x70 +[38573.102007] [] ieee80211_sta_work+0x91/0xb80 [mac80211] +[38573.102007] [] ? sched_clock+0x27/0xa0 +[38573.102007] [] ? sub_preempt_count+0x85/0xc0 +[38573.102007] [] worker_thread+0x18f/0x320 +[38573.102007] [] ? worker_thread+0x12e/0x320 +[38573.102007] [] ? _spin_unlock_irqrestore+0x55/0x70 +[38573.102007] [] ? ieee80211_sta_work+0x0/0xb80 [mac80211] +[38573.102007] [] ? autoremove_wake_function+0x0/0x50 +[38573.102007] [] ? worker_thread+0x0/0x320 +[38573.102007] [] kthread+0x84/0x90 +[38573.102007] [] ? kthread+0x0/0x90 +[38573.102007] [] kernel_thread_helper+0x7/0x10 + +Signed-off-by: Bob Copeland +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..7f4a4349e64 --- /dev/null +++ b/queue-2.6.31/mpt2sas-prevent-sending-command-to-fw-while-host-reset.patch @@ -0,0 +1,352 @@ +From 155dd4c763694222c125e65438d823f58ea653bc Mon Sep 17 00:00:00 2001 +From: Kashyap, Desai +Date: Thu, 20 Aug 2009 13:22:00 +0530 +Subject: [SCSI] mpt2sas: Prevent sending command to FW while Host Reset + +From: Kashyap, Desai + +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 +Reviewed-by: Eric Moore +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d9a65acbbff --- /dev/null +++ b/queue-2.6.31/mpt2sas-raid-10-volume-is-showing-as-raid-1e-in-dmesg.patch @@ -0,0 +1,220 @@ +From ed79f1280d1bc54f168abcffc8c3e0bf8ffb1873 Mon Sep 17 00:00:00 2001 +From: Kashyap, Desai +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 + +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 +Reviewed-by: Eric Moore +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..9d335b26a73 --- /dev/null +++ b/queue-2.6.31/mpt2sas-rescan-topology-from-interrupt-context-instead-of-work-thread.patch @@ -0,0 +1,241 @@ +From cd4e12e8ad246ec5bc23ab04d0da0e6985025620 Mon Sep 17 00:00:00 2001 +From: Kashyap, Desai +Date: Thu, 20 Aug 2009 13:20:54 +0530 +Subject: [SCSI] mpt2sas : Rescan topology from Interrupt context instead of work thread + +From: Kashyap, Desai + +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 +Reviewed-by: Eric Moore +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..b9da5ac31d1 --- /dev/null +++ b/queue-2.6.31/mpt2sas-setting-sdev-into-running-state-from-interrupt-context.patch @@ -0,0 +1,99 @@ +From 34a03bef2202d0c9983a8da0a8abaee37d285847 Mon Sep 17 00:00:00 2001 +From: Kashyap, Desai +Date: Thu, 20 Aug 2009 13:23:19 +0530 +Subject: [SCSI] mpt2sas: setting SDEV into RUNNING state from Interrupt context + +From: Kashyap, Desai + +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 +Reviewed-by: Eric Moore +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..cc8f0bd4bb3 --- /dev/null +++ b/queue-2.6.31/scsi-fix-oops-during-scsi-scanning.patch @@ -0,0 +1,105 @@ +From ea038f63ac52439e7816295fa6064fe95e6c1f51 Mon Sep 17 00:00:00 2001 +From: James Bottomley +Date: Fri, 21 Aug 2009 09:47:54 -0600 +Subject: SCSI: fix oops during scsi scanning + +From: James Bottomley + +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: [] 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:[] [] 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: [] register_disk+0x122/0x13a + 15:27:13.014 kernel: [] add_disk+0xaa/0x106 + 15:27:13.014 kernel: [] sd_probe_async+0x198/0x25b + 15:27:13.014 kernel: [] async_thread+0x10c/0x20d + 15:27:13.014 kernel: [] ? default_wake_function+0x0/0xf + 15:27:13.014 kernel: [] ? async_thread+0x0/0x20d + 15:27:13.014 kernel: [] kthread+0x55/0x80 + 15:27:13.014 kernel: [] child_rip+0xa/0x20 + 15:27:13.014 kernel: [] ? kthread+0x0/0x80 + 15:27:13.014 kernel: [] ? 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 [] disk_part_iter_next+0x74/0xfd + 15:27:13.015 kernel: RSP + 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 +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..c35be76d1df --- /dev/null +++ b/queue-2.6.31/scsi-libsrp-fix-memory-leak-in-srp_ring_free.patch @@ -0,0 +1,39 @@ +From afffd3dabe5209882c8cc59a373a4d33b5db304a Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Sun, 30 Aug 2009 12:36:48 +0200 +Subject: SCSI: libsrp: fix memory leak in srp_ring_free() + +From: Bart Van Assche + +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 +Acked-by: FUJITA Tomonori +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..177798e6c8d --- /dev/null +++ b/queue-2.6.31/series @@ -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 index 00000000000..aaca77a3b04 --- /dev/null +++ b/queue-2.6.31/sg-fix-oops-in-the-error-path-in-sg_build_indirect.patch @@ -0,0 +1,33 @@ +From e71044ee2efa4792e21d243b03d49006db66aec9 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +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 + +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 +Reported-by: Bob Tracy +Acked-by: Douglas Gilbert +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + 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;