aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptsas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
-rw-r--r--drivers/message/fusion/mptsas.c125
1 files changed, 124 insertions, 1 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index f705a235300e..235113ac08e5 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -57,6 +57,7 @@
57#include <scsi/scsi_device.h> 57#include <scsi/scsi_device.h>
58#include <scsi/scsi_host.h> 58#include <scsi/scsi_host.h>
59#include <scsi/scsi_transport_sas.h> 59#include <scsi/scsi_transport_sas.h>
60#include <scsi/scsi_transport.h>
60#include <scsi/scsi_dbg.h> 61#include <scsi/scsi_dbg.h>
61 62
62#include "mptbase.h" 63#include "mptbase.h"
@@ -1912,6 +1913,48 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1912 return mptscsih_qcmd(SCpnt,done); 1913 return mptscsih_qcmd(SCpnt,done);
1913} 1914}
1914 1915
1916/**
1917 * mptsas_mptsas_eh_timed_out - resets the scsi_cmnd timeout
1918 * if the device under question is currently in the
1919 * device removal delay.
1920 * @sc: scsi command that the midlayer is about to time out
1921 *
1922 **/
1923static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
1924{
1925 MPT_SCSI_HOST *hd;
1926 MPT_ADAPTER *ioc;
1927 VirtDevice *vdevice;
1928 enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
1929
1930 hd = shost_priv(sc->device->host);
1931 if (hd == NULL) {
1932 printk(KERN_ERR MYNAM ": %s: Can't locate host! (sc=%p)\n",
1933 __func__, sc);
1934 goto done;
1935 }
1936
1937 ioc = hd->ioc;
1938 if (ioc->bus_type != SAS) {
1939 printk(KERN_ERR MYNAM ": %s: Wrong bus type (sc=%p)\n",
1940 __func__, sc);
1941 goto done;
1942 }
1943
1944 vdevice = sc->device->hostdata;
1945 if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD
1946 || vdevice->vtarget->deleted)) {
1947 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: target removed "
1948 "or in device removal delay (sc=%p)\n",
1949 ioc->name, __func__, sc));
1950 rc = BLK_EH_RESET_TIMER;
1951 goto done;
1952 }
1953
1954done:
1955 return rc;
1956}
1957
1915 1958
1916static struct scsi_host_template mptsas_driver_template = { 1959static struct scsi_host_template mptsas_driver_template = {
1917 .module = THIS_MODULE, 1960 .module = THIS_MODULE,
@@ -2984,6 +3027,7 @@ static int mptsas_probe_one_phy(struct device *dev,
2984 struct sas_phy *phy; 3027 struct sas_phy *phy;
2985 struct sas_port *port; 3028 struct sas_port *port;
2986 int error = 0; 3029 int error = 0;
3030 VirtTarget *vtarget;
2987 3031
2988 if (!dev) { 3032 if (!dev) {
2989 error = -ENODEV; 3033 error = -ENODEV;
@@ -3206,6 +3250,16 @@ static int mptsas_probe_one_phy(struct device *dev,
3206 rphy_to_expander_device(rphy)); 3250 rphy_to_expander_device(rphy));
3207 } 3251 }
3208 3252
3253 /* If the device exists,verify it wasn't previously flagged
3254 as a missing device. If so, clear it */
3255 vtarget = mptsas_find_vtarget(ioc,
3256 phy_info->attached.channel,
3257 phy_info->attached.id);
3258 if (vtarget && vtarget->inDMD) {
3259 printk(KERN_INFO "Device returned, unsetting inDMD\n");
3260 vtarget->inDMD = 0;
3261 }
3262
3209 out: 3263 out:
3210 return error; 3264 return error;
3211} 3265}
@@ -3659,9 +3713,42 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event)
3659 MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION) 3713 MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
3660 phy_info->phy->negotiated_linkrate = 3714 phy_info->phy->negotiated_linkrate =
3661 SAS_LINK_RATE_FAILED; 3715 SAS_LINK_RATE_FAILED;
3662 else 3716 else {
3663 phy_info->phy->negotiated_linkrate = 3717 phy_info->phy->negotiated_linkrate =
3664 SAS_LINK_RATE_UNKNOWN; 3718 SAS_LINK_RATE_UNKNOWN;
3719 if (ioc->device_missing_delay &&
3720 mptsas_is_end_device(&phy_info->attached)) {
3721 struct scsi_device *sdev;
3722 VirtDevice *vdevice;
3723 u8 channel, id;
3724 id = phy_info->attached.id;
3725 channel = phy_info->attached.channel;
3726 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3727 "Link down for fw_id %d:fw_channel %d\n",
3728 ioc->name, phy_info->attached.id,
3729 phy_info->attached.channel));
3730
3731 shost_for_each_device(sdev, ioc->sh) {
3732 vdevice = sdev->hostdata;
3733 if ((vdevice == NULL) ||
3734 (vdevice->vtarget == NULL))
3735 continue;
3736 if ((vdevice->vtarget->tflags &
3737 MPT_TARGET_FLAGS_RAID_COMPONENT ||
3738 vdevice->vtarget->raidVolume))
3739 continue;
3740 if (vdevice->vtarget->id == id &&
3741 vdevice->vtarget->channel ==
3742 channel)
3743 devtprintk(ioc,
3744 printk(MYIOC_s_DEBUG_FMT
3745 "SDEV OUTSTANDING CMDS"
3746 "%d\n", ioc->name,
3747 sdev->device_busy));
3748 }
3749
3750 }
3751 }
3665 } 3752 }
3666 out: 3753 out:
3667 mptsas_free_fw_event(ioc, fw_event); 3754 mptsas_free_fw_event(ioc, fw_event);
@@ -4906,12 +4993,47 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
4906 { 4993 {
4907 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data = 4994 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
4908 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data; 4995 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
4996 u16 ioc_stat;
4997 ioc_stat = le16_to_cpu(reply->IOCStatus);
4909 4998
4910 if (sas_event_data->ReasonCode == 4999 if (sas_event_data->ReasonCode ==
4911 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) { 5000 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
4912 mptsas_target_reset_queue(ioc, sas_event_data); 5001 mptsas_target_reset_queue(ioc, sas_event_data);
4913 return 0; 5002 return 0;
4914 } 5003 }
5004 if (sas_event_data->ReasonCode ==
5005 MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
5006 ioc->device_missing_delay &&
5007 (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)) {
5008 VirtTarget *vtarget = NULL;
5009 u8 id, channel;
5010 u32 log_info = le32_to_cpu(reply->IOCLogInfo);
5011
5012 id = sas_event_data->TargetID;
5013 channel = sas_event_data->Bus;
5014
5015 vtarget = mptsas_find_vtarget(ioc, channel, id);
5016 if (vtarget) {
5017 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5018 "LogInfo (0x%x) available for "
5019 "INTERNAL_DEVICE_RESET"
5020 "fw_id %d fw_channel %d\n", ioc->name,
5021 log_info, id, channel));
5022 if (vtarget->raidVolume) {
5023 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5024 "Skipping Raid Volume for inDMD\n",
5025 ioc->name));
5026 } else {
5027 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5028 "Setting device flag inDMD\n",
5029 ioc->name));
5030 vtarget->inDMD = 1;
5031 }
5032
5033 }
5034
5035 }
5036
4915 break; 5037 break;
4916 } 5038 }
4917 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE: 5039 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
@@ -5244,6 +5366,7 @@ mptsas_init(void)
5244 sas_attach_transport(&mptsas_transport_functions); 5366 sas_attach_transport(&mptsas_transport_functions);
5245 if (!mptsas_transport_template) 5367 if (!mptsas_transport_template)
5246 return -ENODEV; 5368 return -ENODEV;
5369 mptsas_transport_template->eh_timed_out = mptsas_eh_timed_out;
5247 5370
5248 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); 5371 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
5249 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); 5372 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);