diff options
Diffstat (limited to 'drivers/message')
-rw-r--r-- | drivers/message/fusion/mptbase.h | 2 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 125 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 40 |
3 files changed, 157 insertions, 10 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 0d149c82e764..7f31973b3f7c 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
@@ -396,6 +396,8 @@ typedef struct _VirtTarget { | |||
396 | u8 raidVolume; /* set, if RAID Volume */ | 396 | u8 raidVolume; /* set, if RAID Volume */ |
397 | u8 type; /* byte 0 of Inquiry data */ | 397 | u8 type; /* byte 0 of Inquiry data */ |
398 | u8 deleted; /* target in process of being removed */ | 398 | u8 deleted; /* target in process of being removed */ |
399 | u8 inDMD; /* currently in the device | ||
400 | removal delay timer */ | ||
399 | u32 num_luns; | 401 | u32 num_luns; |
400 | } VirtTarget; | 402 | } VirtTarget; |
401 | 403 | ||
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 | **/ | ||
1923 | static 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 | |||
1954 | done: | ||
1955 | return rc; | ||
1956 | } | ||
1957 | |||
1915 | 1958 | ||
1916 | static struct scsi_host_template mptsas_driver_template = { | 1959 | static 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); |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index dceb67a21825..59b8f53d1ece 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -664,6 +664,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
664 | u32 log_info; | 664 | u32 log_info; |
665 | 665 | ||
666 | status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; | 666 | status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; |
667 | |||
667 | scsi_state = pScsiReply->SCSIState; | 668 | scsi_state = pScsiReply->SCSIState; |
668 | scsi_status = pScsiReply->SCSIStatus; | 669 | scsi_status = pScsiReply->SCSIStatus; |
669 | xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); | 670 | xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); |
@@ -738,15 +739,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
738 | 739 | ||
739 | case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ | 740 | case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ |
740 | if ( ioc->bus_type == SAS ) { | 741 | if ( ioc->bus_type == SAS ) { |
741 | u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus); | 742 | u16 ioc_status = |
742 | if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { | 743 | le16_to_cpu(pScsiReply->IOCStatus); |
743 | if ((log_info & SAS_LOGINFO_MASK) | 744 | if ((ioc_status & |
744 | == SAS_LOGINFO_NEXUS_LOSS) { | 745 | MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) |
745 | sc->result = | 746 | && |
746 | (DID_TRANSPORT_DISRUPTED | 747 | ((log_info & SAS_LOGINFO_MASK) == |
747 | << 16); | 748 | SAS_LOGINFO_NEXUS_LOSS)) { |
748 | break; | 749 | VirtDevice *vdevice = |
749 | } | 750 | sc->device->hostdata; |
751 | |||
752 | /* flag the device as being in | ||
753 | * device removal delay so we can | ||
754 | * notify the midlayer to hold off | ||
755 | * on timeout eh */ | ||
756 | if (vdevice && vdevice-> | ||
757 | vtarget && | ||
758 | vdevice->vtarget-> | ||
759 | raidVolume) | ||
760 | printk(KERN_INFO | ||
761 | "Skipping Raid Volume" | ||
762 | "for inDMD\n"); | ||
763 | else if (vdevice && | ||
764 | vdevice->vtarget) | ||
765 | vdevice->vtarget-> | ||
766 | inDMD = 1; | ||
767 | |||
768 | sc->result = | ||
769 | (DID_TRANSPORT_DISRUPTED | ||
770 | << 16); | ||
771 | break; | ||
750 | } | 772 | } |
751 | } else if (ioc->bus_type == FC) { | 773 | } else if (ioc->bus_type == FC) { |
752 | /* | 774 | /* |