diff options
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r-- | drivers/message/fusion/Kconfig | 1 | ||||
-rw-r--r-- | drivers/message/fusion/Makefile | 1 | ||||
-rw-r--r-- | drivers/message/fusion/lsi/mpi_log_sas.h | 105 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.c | 205 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 36 | ||||
-rw-r--r-- | drivers/message/fusion/mptctl.c | 8 | ||||
-rw-r--r-- | drivers/message/fusion/mptfc.c | 39 | ||||
-rw-r--r-- | drivers/message/fusion/mptlan.c | 5 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 818 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 2486 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.h | 12 | ||||
-rw-r--r-- | drivers/message/fusion/mptspi.c | 735 |
12 files changed, 1648 insertions, 2803 deletions
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index e67cf15e9c39..bbc229852881 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig | |||
@@ -9,6 +9,7 @@ config FUSION_SPI | |||
9 | tristate "Fusion MPT ScsiHost drivers for SPI" | 9 | tristate "Fusion MPT ScsiHost drivers for SPI" |
10 | depends on PCI && SCSI | 10 | depends on PCI && SCSI |
11 | select FUSION | 11 | select FUSION |
12 | select SCSI_SPI_ATTRS | ||
12 | ---help--- | 13 | ---help--- |
13 | SCSI HOST support for a parallel SCSI host adapters. | 14 | SCSI HOST support for a parallel SCSI host adapters. |
14 | 15 | ||
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 33ace373241c..51740b346224 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME | 4 | #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME |
5 | #EXTRA_CFLAGS += -DMPT_DEBUG_SG | 5 | #EXTRA_CFLAGS += -DMPT_DEBUG_SG |
6 | #EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS | 6 | #EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS |
7 | #EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE_EVENTS | ||
7 | #EXTRA_CFLAGS += -DMPT_DEBUG_INIT | 8 | #EXTRA_CFLAGS += -DMPT_DEBUG_INIT |
8 | #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT | 9 | #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT |
9 | #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL | 10 | #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL |
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h index 9259d1ad6e6e..a9c14ad132ce 100644 --- a/drivers/message/fusion/lsi/mpi_log_sas.h +++ b/drivers/message/fusion/lsi/mpi_log_sas.h | |||
@@ -3,38 +3,11 @@ | |||
3 | * * | 3 | * * |
4 | * Copyright 2003 LSI Logic Corporation. All rights reserved. * | 4 | * Copyright 2003 LSI Logic Corporation. All rights reserved. * |
5 | * * | 5 | * * |
6 | * This file is confidential and a trade secret of LSI Logic. The * | 6 | * Description * |
7 | * receipt of or possession of this file does not convey any rights to * | 7 | * ------------ * |
8 | * reproduce or disclose its contents or to manufacture, use, or sell * | 8 | * This include file contains SAS firmware interface IOC Log Info codes * |
9 | * anything it may describe, in whole, or in part, without the specific * | ||
10 | * written consent of LSI Logic Corporation. * | ||
11 | * * | 9 | * * |
12 | *************************************************************************** | 10 | *-------------------------------------------------------------------------* |
13 | * | ||
14 | * Name: iopiIocLogInfo.h | ||
15 | * Title: SAS Firmware IOP Interface IOC Log Info Definitions | ||
16 | * Programmer: Guy Kendall | ||
17 | * Creation Date: September 24, 2003 | ||
18 | * | ||
19 | * Version History | ||
20 | * --------------- | ||
21 | * | ||
22 | * Last Updated | ||
23 | * ------------- | ||
24 | * Version %version: 22 % | ||
25 | * Date Updated %date_modified: % | ||
26 | * Programmer %created_by: nperucca % | ||
27 | * | ||
28 | * Date Who Description | ||
29 | * -------- --- ------------------------------------------------------- | ||
30 | * 09/24/03 GWK Initial version | ||
31 | * | ||
32 | * | ||
33 | * Description | ||
34 | * ------------ | ||
35 | * This include file contains SAS firmware interface IOC Log Info codes | ||
36 | * | ||
37 | *------------------------------------------------------------------------- | ||
38 | */ | 11 | */ |
39 | 12 | ||
40 | #ifndef IOPI_IOCLOGINFO_H_INCLUDED | 13 | #ifndef IOPI_IOCLOGINFO_H_INCLUDED |
@@ -57,6 +30,8 @@ | |||
57 | #define IOC_LOGINFO_ORIGINATOR_PL (0x01000000) | 30 | #define IOC_LOGINFO_ORIGINATOR_PL (0x01000000) |
58 | #define IOC_LOGINFO_ORIGINATOR_IR (0x02000000) | 31 | #define IOC_LOGINFO_ORIGINATOR_IR (0x02000000) |
59 | 32 | ||
33 | #define IOC_LOGINFO_ORIGINATOR_MASK (0x0F000000) | ||
34 | |||
60 | /****************************************************************************/ | 35 | /****************************************************************************/ |
61 | /* LOGINFO_CODE defines */ | 36 | /* LOGINFO_CODE defines */ |
62 | /****************************************************************************/ | 37 | /****************************************************************************/ |
@@ -78,11 +53,27 @@ | |||
78 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ | 53 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ |
79 | #define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) | 54 | #define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) |
80 | 55 | ||
56 | #define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R (0x00060001) /* Read Action not supported for SEP msg */ | ||
57 | #define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */ | ||
58 | |||
59 | #define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED (0x00070001) | ||
60 | #define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED (0x00070002) | ||
61 | #define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO (0x00070003) | ||
62 | #define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004) | ||
63 | #define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005) | ||
81 | 64 | ||
82 | /****************************************************************************/ | 65 | /****************************************************************************/ |
83 | /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */ | 66 | /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */ |
84 | /****************************************************************************/ | 67 | /****************************************************************************/ |
85 | #define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) | 68 | #define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) |
69 | #define PL_LOG_INFO_CODE_OPEN_FAILURE_NO_DEST_TIME_OUT (0x00010001) | ||
70 | #define PL_LOGINFO_CODE_OPEN_FAILURE_BAD_DESTINATION (0x00010011) | ||
71 | #define PL_LOGINFO_CODE_OPEN_FAILURE_PROTOCOL_NOT_SUPPORTED (0x00010013) | ||
72 | #define PL_LOGINFO_CODE_OPEN_FAILURE_STP_RESOURCES_BSY (0x00010018) | ||
73 | #define PL_LOGINFO_CODE_OPEN_FAILURE_WRONG_DESTINATION (0x00010019) | ||
74 | #define PL_LOGINFO_CODE_OPEN_FAILURE_ORR_TIMEOUT (0X0001001A) | ||
75 | #define PL_LOGINFO_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0001001B) | ||
76 | #define PL_LOGINFO_CODE_OPEN_FAILURE_AWT_MAXED (0x0001001C) | ||
86 | #define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) | 77 | #define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) |
87 | #define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) | 78 | #define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) |
88 | #define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) | 79 | #define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) |
@@ -97,6 +88,7 @@ | |||
97 | #define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) | 88 | #define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) |
98 | #define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) | 89 | #define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) |
99 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) | 90 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) |
91 | #define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED (0x000F0001) /* PL not yet initialized, can't do config page req. */ | ||
100 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ | 92 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ |
101 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ | 93 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ |
102 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ | 94 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ |
@@ -105,11 +97,23 @@ | |||
105 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ | 97 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ |
106 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ | 98 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ |
107 | #define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) | 99 | #define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) |
108 | #define PL_LOGINFO_CODE_RESET (0x00110000) | 100 | #define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below */ |
109 | #define PL_LOGINFO_CODE_ABORT (0x00120000) | 101 | #define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below */ |
110 | #define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) | 102 | #define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) |
111 | #define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) | 103 | #define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) |
104 | #define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER (0x00150000) | ||
105 | #define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT (0x00160000) | ||
112 | #define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100) | 106 | #define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100) |
107 | #define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT (0x00000101) | ||
108 | #define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT (0x0000011A) /* Open Reject (Retry) Timeout */ | ||
109 | #define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0000011B) | ||
110 | #define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED (0x0000011C) /* Arbitration Wait Timer Maxed */ | ||
111 | |||
112 | #define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET (0x00000120) | ||
113 | #define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER (0x00000130) /* Leave lower nibble (1-f) reserved. */ | ||
114 | #define PL_LOGINFO_SUB_CODE_PORT_LAYER (0x00000140) /* Leave lower nibble (1-f) reserved. */ | ||
115 | |||
116 | |||
113 | #define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) | 117 | #define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) |
114 | #define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) | 118 | #define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) |
115 | #define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) | 119 | #define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) |
@@ -123,26 +127,39 @@ | |||
123 | #define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) | 127 | #define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) |
124 | #define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) | 128 | #define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) |
125 | #define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) | 129 | #define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) |
130 | #define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01) | ||
131 | #define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00) | ||
126 | #define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) | 132 | #define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) |
127 | 133 | ||
128 | 134 | ||
129 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ | 135 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ |
130 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200001) /* Error occured on SMP Read */ | 136 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */ |
131 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */ | 137 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */ |
132 | #define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */ | 138 | #define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */ |
133 | #define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */ | 139 | #define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */ |
134 | #define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */ | 140 | #define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */ |
135 | #define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */ | 141 | #define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200070) /* SGPIO not present/enabled */ |
142 | #define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED (0x00200080) /* GPIO not configured */ | ||
143 | #define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR (0x00200090) /* GPIO can't allocate a frame */ | ||
144 | #define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR (0x002000A0) /* GPIO failed config page request */ | ||
145 | #define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR (0x002000B0) /* Can't get frame for SES command */ | ||
146 | #define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR (0x002000C0) /* I/O execution error */ | ||
147 | #define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED (0x002000D0) /* SEP I/O retries exhausted */ | ||
148 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR (0x002000E0) /* Can't get frame for SMP command */ | ||
136 | 149 | ||
137 | #define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ | 150 | #define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ |
138 | #define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ | 151 | #define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ |
139 | #define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ | 152 | #define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ |
140 | #define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ | 153 | #define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ |
141 | #define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */ | 154 | #define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */ |
142 | #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */ | 155 | #define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */ |
143 | #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */ | 156 | #define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */ |
144 | #define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */ | 157 | #define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */ |
145 | #define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/ | 158 | #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */ |
159 | #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */ | ||
160 | #define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */ | ||
161 | #define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/ | ||
162 | #define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND (0x0020010C) /* SEP doesn't support CDB opcode */ | ||
146 | 163 | ||
147 | 164 | ||
148 | /****************************************************************************/ | 165 | /****************************************************************************/ |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 642a61b6d0a4..266414ca2814 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -180,6 +180,7 @@ static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) | |||
180 | static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); | 180 | static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); |
181 | static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); | 181 | static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); |
182 | static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); | 182 | static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); |
183 | static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); | ||
183 | 184 | ||
184 | /* module entry point */ | 185 | /* module entry point */ |
185 | static int __init fusion_init (void); | 186 | static int __init fusion_init (void); |
@@ -428,7 +429,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) | |||
428 | results = ProcessEventNotification(ioc, pEvReply, &evHandlers); | 429 | results = ProcessEventNotification(ioc, pEvReply, &evHandlers); |
429 | if (results != evHandlers) { | 430 | if (results != evHandlers) { |
430 | /* CHECKME! Any special handling needed here? */ | 431 | /* CHECKME! Any special handling needed here? */ |
431 | devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", | 432 | devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", |
432 | ioc->name, evHandlers, results)); | 433 | ioc->name, evHandlers, results)); |
433 | } | 434 | } |
434 | 435 | ||
@@ -438,10 +439,10 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) | |||
438 | */ | 439 | */ |
439 | if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { | 440 | if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { |
440 | freereq = 0; | 441 | freereq = 0; |
441 | devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n", | 442 | devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n", |
442 | ioc->name, pEvReply)); | 443 | ioc->name, pEvReply)); |
443 | } else { | 444 | } else { |
444 | devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", | 445 | devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", |
445 | ioc->name, pEvReply)); | 446 | ioc->name, pEvReply)); |
446 | } | 447 | } |
447 | 448 | ||
@@ -1120,65 +1121,6 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) | |||
1120 | return -1; | 1121 | return -1; |
1121 | } | 1122 | } |
1122 | 1123 | ||
1123 | int | ||
1124 | mpt_alt_ioc_wait(MPT_ADAPTER *ioc) | ||
1125 | { | ||
1126 | int loop_count = 30 * 4; /* Wait 30 seconds */ | ||
1127 | int status = -1; /* -1 means failed to get board READY */ | ||
1128 | |||
1129 | do { | ||
1130 | spin_lock(&ioc->initializing_hba_lock); | ||
1131 | if (ioc->initializing_hba_lock_flag == 0) { | ||
1132 | ioc->initializing_hba_lock_flag=1; | ||
1133 | spin_unlock(&ioc->initializing_hba_lock); | ||
1134 | status = 0; | ||
1135 | break; | ||
1136 | } | ||
1137 | spin_unlock(&ioc->initializing_hba_lock); | ||
1138 | set_current_state(TASK_INTERRUPTIBLE); | ||
1139 | schedule_timeout(HZ/4); | ||
1140 | } while (--loop_count); | ||
1141 | |||
1142 | return status; | ||
1143 | } | ||
1144 | |||
1145 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1146 | /* | ||
1147 | * mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery | ||
1148 | * @ioc: Pointer to MPT adapter structure | ||
1149 | * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. | ||
1150 | * | ||
1151 | * This routine performs all the steps necessary to bring the IOC | ||
1152 | * to a OPERATIONAL state. | ||
1153 | * | ||
1154 | * Special Note: This function was added with spin lock's so as to allow | ||
1155 | * the dv(domain validation) work thread to succeed on the other channel | ||
1156 | * that maybe occuring at the same time when this function is called. | ||
1157 | * Without this lock, the dv would fail when message frames were | ||
1158 | * requested during hba bringup on the alternate ioc. | ||
1159 | */ | ||
1160 | static int | ||
1161 | mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag) | ||
1162 | { | ||
1163 | int r; | ||
1164 | |||
1165 | if(ioc->alt_ioc) { | ||
1166 | if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0)) | ||
1167 | return r; | ||
1168 | } | ||
1169 | |||
1170 | r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, | ||
1171 | CAN_SLEEP); | ||
1172 | |||
1173 | if(ioc->alt_ioc) { | ||
1174 | spin_lock(&ioc->alt_ioc->initializing_hba_lock); | ||
1175 | ioc->alt_ioc->initializing_hba_lock_flag=0; | ||
1176 | spin_unlock(&ioc->alt_ioc->initializing_hba_lock); | ||
1177 | } | ||
1178 | |||
1179 | return r; | ||
1180 | } | ||
1181 | |||
1182 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1124 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
1183 | /* | 1125 | /* |
1184 | * mpt_attach - Install a PCI intelligent MPT adapter. | 1126 | * mpt_attach - Install a PCI intelligent MPT adapter. |
@@ -1482,7 +1424,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1482 | */ | 1424 | */ |
1483 | mpt_detect_bound_ports(ioc, pdev); | 1425 | mpt_detect_bound_ports(ioc, pdev); |
1484 | 1426 | ||
1485 | if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){ | 1427 | if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, |
1428 | CAN_SLEEP)) != 0){ | ||
1486 | printk(KERN_WARNING MYNAM | 1429 | printk(KERN_WARNING MYNAM |
1487 | ": WARNING - %s did not initialize properly! (%d)\n", | 1430 | ": WARNING - %s did not initialize properly! (%d)\n", |
1488 | ioc->name, r); | 1431 | ioc->name, r); |
@@ -1629,7 +1572,6 @@ mpt_resume(struct pci_dev *pdev) | |||
1629 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 1572 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); |
1630 | u32 device_state = pdev->current_state; | 1573 | u32 device_state = pdev->current_state; |
1631 | int recovery_state; | 1574 | int recovery_state; |
1632 | int ii; | ||
1633 | 1575 | ||
1634 | printk(MYIOC_s_INFO_FMT | 1576 | printk(MYIOC_s_INFO_FMT |
1635 | "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", | 1577 | "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n", |
@@ -1643,14 +1585,6 @@ mpt_resume(struct pci_dev *pdev) | |||
1643 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); | 1585 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); |
1644 | ioc->active = 1; | 1586 | ioc->active = 1; |
1645 | 1587 | ||
1646 | /* F/W not running */ | ||
1647 | if(!CHIPREG_READ32(&ioc->chip->Doorbell)) { | ||
1648 | /* enable domain validation flags */ | ||
1649 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | ||
1650 | ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV; | ||
1651 | } | ||
1652 | } | ||
1653 | |||
1654 | printk(MYIOC_s_INFO_FMT | 1588 | printk(MYIOC_s_INFO_FMT |
1655 | "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", | 1589 | "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", |
1656 | ioc->name, | 1590 | ioc->name, |
@@ -4938,7 +4872,7 @@ done_and_free: | |||
4938 | return rc; | 4872 | return rc; |
4939 | } | 4873 | } |
4940 | 4874 | ||
4941 | int | 4875 | static int |
4942 | mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) | 4876 | mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) |
4943 | { | 4877 | { |
4944 | IOCPage3_t *pIoc3; | 4878 | IOCPage3_t *pIoc3; |
@@ -5146,13 +5080,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) | |||
5146 | 5080 | ||
5147 | evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); | 5081 | evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); |
5148 | if (evnp == NULL) { | 5082 | if (evnp == NULL) { |
5149 | devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", | 5083 | devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", |
5150 | ioc->name)); | 5084 | ioc->name)); |
5151 | return 0; | 5085 | return 0; |
5152 | } | 5086 | } |
5153 | memset(evnp, 0, sizeof(*evnp)); | 5087 | memset(evnp, 0, sizeof(*evnp)); |
5154 | 5088 | ||
5155 | devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); | 5089 | devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); |
5156 | 5090 | ||
5157 | evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; | 5091 | evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; |
5158 | evnp->ChainOffset = 0; | 5092 | evnp->ChainOffset = 0; |
@@ -5907,24 +5841,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
5907 | break; | 5841 | break; |
5908 | case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: | 5842 | case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: |
5909 | { | 5843 | { |
5844 | char buf[50]; | ||
5845 | u8 id = (u8)(evData0); | ||
5910 | u8 ReasonCode = (u8)(evData0 >> 16); | 5846 | u8 ReasonCode = (u8)(evData0 >> 16); |
5911 | switch (ReasonCode) { | 5847 | switch (ReasonCode) { |
5912 | case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: | 5848 | case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: |
5913 | ds = "SAS Device Status Change: Added"; | 5849 | sprintf(buf,"SAS Device Status Change: Added: id=%d", id); |
5914 | break; | 5850 | break; |
5915 | case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: | 5851 | case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: |
5916 | ds = "SAS Device Status Change: Deleted"; | 5852 | sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id); |
5917 | break; | 5853 | break; |
5918 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: | 5854 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: |
5919 | ds = "SAS Device Status Change: SMART Data"; | 5855 | sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id); |
5920 | break; | 5856 | break; |
5921 | case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: | 5857 | case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: |
5922 | ds = "SAS Device Status Change: No Persistancy Added"; | 5858 | sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id); |
5923 | break; | 5859 | break; |
5924 | default: | 5860 | default: |
5925 | ds = "SAS Device Status Change: Unknown"; | 5861 | sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id); |
5926 | break; | 5862 | break; |
5927 | } | 5863 | } |
5864 | ds = buf; | ||
5928 | break; | 5865 | break; |
5929 | } | 5866 | } |
5930 | case MPI_EVENT_ON_BUS_TIMER_EXPIRED: | 5867 | case MPI_EVENT_ON_BUS_TIMER_EXPIRED: |
@@ -5940,11 +5877,97 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) | |||
5940 | ds = "Persistent Table Full"; | 5877 | ds = "Persistent Table Full"; |
5941 | break; | 5878 | break; |
5942 | case MPI_EVENT_SAS_PHY_LINK_STATUS: | 5879 | case MPI_EVENT_SAS_PHY_LINK_STATUS: |
5943 | ds = "SAS PHY Link Status"; | 5880 | { |
5881 | char buf[50]; | ||
5882 | u8 LinkRates = (u8)(evData0 >> 8); | ||
5883 | u8 PhyNumber = (u8)(evData0); | ||
5884 | LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >> | ||
5885 | MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT; | ||
5886 | switch (LinkRates) { | ||
5887 | case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN: | ||
5888 | sprintf(buf,"SAS PHY Link Status: Phy=%d:" | ||
5889 | " Rate Unknown",PhyNumber); | ||
5890 | break; | ||
5891 | case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED: | ||
5892 | sprintf(buf,"SAS PHY Link Status: Phy=%d:" | ||
5893 | " Phy Disabled",PhyNumber); | ||
5894 | break; | ||
5895 | case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION: | ||
5896 | sprintf(buf,"SAS PHY Link Status: Phy=%d:" | ||
5897 | " Failed Speed Nego",PhyNumber); | ||
5898 | break; | ||
5899 | case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE: | ||
5900 | sprintf(buf,"SAS PHY Link Status: Phy=%d:" | ||
5901 | " Sata OOB Completed",PhyNumber); | ||
5902 | break; | ||
5903 | case MPI_EVENT_SAS_PLS_LR_RATE_1_5: | ||
5904 | sprintf(buf,"SAS PHY Link Status: Phy=%d:" | ||
5905 | " Rate 1.5 Gbps",PhyNumber); | ||
5906 | break; | ||
5907 | case MPI_EVENT_SAS_PLS_LR_RATE_3_0: | ||
5908 | sprintf(buf,"SAS PHY Link Status: Phy=%d:" | ||
5909 | " Rate 3.0 Gpbs",PhyNumber); | ||
5910 | break; | ||
5911 | default: | ||
5912 | sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber); | ||
5913 | break; | ||
5914 | } | ||
5915 | ds = buf; | ||
5944 | break; | 5916 | break; |
5917 | } | ||
5945 | case MPI_EVENT_SAS_DISCOVERY_ERROR: | 5918 | case MPI_EVENT_SAS_DISCOVERY_ERROR: |
5946 | ds = "SAS Discovery Error"; | 5919 | ds = "SAS Discovery Error"; |
5947 | break; | 5920 | break; |
5921 | case MPI_EVENT_IR_RESYNC_UPDATE: | ||
5922 | { | ||
5923 | u8 resync_complete = (u8)(evData0 >> 16); | ||
5924 | char buf[40]; | ||
5925 | sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete); | ||
5926 | ds = buf; | ||
5927 | break; | ||
5928 | } | ||
5929 | case MPI_EVENT_IR2: | ||
5930 | { | ||
5931 | u8 ReasonCode = (u8)(evData0 >> 16); | ||
5932 | switch (ReasonCode) { | ||
5933 | case MPI_EVENT_IR2_RC_LD_STATE_CHANGED: | ||
5934 | ds = "IR2: LD State Changed"; | ||
5935 | break; | ||
5936 | case MPI_EVENT_IR2_RC_PD_STATE_CHANGED: | ||
5937 | ds = "IR2: PD State Changed"; | ||
5938 | break; | ||
5939 | case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL: | ||
5940 | ds = "IR2: Bad Block Table Full"; | ||
5941 | break; | ||
5942 | case MPI_EVENT_IR2_RC_PD_INSERTED: | ||
5943 | ds = "IR2: PD Inserted"; | ||
5944 | break; | ||
5945 | case MPI_EVENT_IR2_RC_PD_REMOVED: | ||
5946 | ds = "IR2: PD Removed"; | ||
5947 | break; | ||
5948 | case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: | ||
5949 | ds = "IR2: Foreign CFG Detected"; | ||
5950 | break; | ||
5951 | case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: | ||
5952 | ds = "IR2: Rebuild Medium Error"; | ||
5953 | break; | ||
5954 | default: | ||
5955 | ds = "IR2"; | ||
5956 | break; | ||
5957 | } | ||
5958 | break; | ||
5959 | } | ||
5960 | case MPI_EVENT_SAS_DISCOVERY: | ||
5961 | { | ||
5962 | if (evData0) | ||
5963 | ds = "SAS Discovery: Start"; | ||
5964 | else | ||
5965 | ds = "SAS Discovery: Stop"; | ||
5966 | break; | ||
5967 | } | ||
5968 | case MPI_EVENT_LOG_ENTRY_ADDED: | ||
5969 | ds = "SAS Log Entry Added"; | ||
5970 | break; | ||
5948 | 5971 | ||
5949 | /* | 5972 | /* |
5950 | * MPT base "custom" events may be added here... | 5973 | * MPT base "custom" events may be added here... |
@@ -5989,12 +6012,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
5989 | } | 6012 | } |
5990 | 6013 | ||
5991 | EventDescriptionStr(event, evData0, evStr); | 6014 | EventDescriptionStr(event, evData0, evStr); |
5992 | devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", | 6015 | devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n", |
5993 | ioc->name, | 6016 | ioc->name, |
5994 | evStr, | 6017 | event, |
5995 | event)); | 6018 | evStr)); |
5996 | 6019 | ||
5997 | #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS) | 6020 | #if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS) |
5998 | printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO); | 6021 | printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO); |
5999 | for (ii = 0; ii < evDataLen; ii++) | 6022 | for (ii = 0; ii < evDataLen; ii++) |
6000 | printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); | 6023 | printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); |
@@ -6053,7 +6076,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
6053 | */ | 6076 | */ |
6054 | for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { | 6077 | for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { |
6055 | if (MptEvHandlers[ii]) { | 6078 | if (MptEvHandlers[ii]) { |
6056 | devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", | 6079 | devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", |
6057 | ioc->name, ii)); | 6080 | ioc->name, ii)); |
6058 | r += (*(MptEvHandlers[ii]))(ioc, pEventReply); | 6081 | r += (*(MptEvHandlers[ii]))(ioc, pEventReply); |
6059 | handlers++; | 6082 | handlers++; |
@@ -6065,10 +6088,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
6065 | * If needed, send (a single) EventAck. | 6088 | * If needed, send (a single) EventAck. |
6066 | */ | 6089 | */ |
6067 | if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { | 6090 | if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { |
6068 | devtprintk((MYIOC_s_WARN_FMT | 6091 | devtverboseprintk((MYIOC_s_WARN_FMT |
6069 | "EventAck required\n",ioc->name)); | 6092 | "EventAck required\n",ioc->name)); |
6070 | if ((ii = SendEventAck(ioc, pEventReply)) != 0) { | 6093 | if ((ii = SendEventAck(ioc, pEventReply)) != 0) { |
6071 | devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", | 6094 | devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", |
6072 | ioc->name, ii)); | 6095 | ioc->name, ii)); |
6073 | } | 6096 | } |
6074 | } | 6097 | } |
@@ -6205,8 +6228,8 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) | |||
6205 | "Abort", /* 12h */ | 6228 | "Abort", /* 12h */ |
6206 | "IO Not Yet Executed", /* 13h */ | 6229 | "IO Not Yet Executed", /* 13h */ |
6207 | "IO Executed", /* 14h */ | 6230 | "IO Executed", /* 14h */ |
6208 | NULL, /* 15h */ | 6231 | "Persistant Reservation Out Not Affiliation Owner", /* 15h */ |
6209 | NULL, /* 16h */ | 6232 | "Open Transmit DMA Abort", /* 16h */ |
6210 | NULL, /* 17h */ | 6233 | NULL, /* 17h */ |
6211 | NULL, /* 18h */ | 6234 | NULL, /* 18h */ |
6212 | NULL, /* 19h */ | 6235 | NULL, /* 19h */ |
@@ -6431,11 +6454,9 @@ EXPORT_SYMBOL(mpt_stm_index); | |||
6431 | EXPORT_SYMBOL(mpt_HardResetHandler); | 6454 | EXPORT_SYMBOL(mpt_HardResetHandler); |
6432 | EXPORT_SYMBOL(mpt_config); | 6455 | EXPORT_SYMBOL(mpt_config); |
6433 | EXPORT_SYMBOL(mpt_findImVolumes); | 6456 | EXPORT_SYMBOL(mpt_findImVolumes); |
6434 | EXPORT_SYMBOL(mpt_read_ioc_pg_3); | ||
6435 | EXPORT_SYMBOL(mpt_alloc_fw_memory); | 6457 | EXPORT_SYMBOL(mpt_alloc_fw_memory); |
6436 | EXPORT_SYMBOL(mpt_free_fw_memory); | 6458 | EXPORT_SYMBOL(mpt_free_fw_memory); |
6437 | EXPORT_SYMBOL(mptbase_sas_persist_operation); | 6459 | EXPORT_SYMBOL(mptbase_sas_persist_operation); |
6438 | EXPORT_SYMBOL(mpt_alt_ioc_wait); | ||
6439 | EXPORT_SYMBOL(mptbase_GetFcPortPage0); | 6460 | EXPORT_SYMBOL(mptbase_GetFcPortPage0); |
6440 | 6461 | ||
6441 | 6462 | ||
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 723d54300953..be7e8501b53c 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
@@ -76,8 +76,8 @@ | |||
76 | #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR | 76 | #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR |
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | #define MPT_LINUX_VERSION_COMMON "3.03.07" | 79 | #define MPT_LINUX_VERSION_COMMON "3.03.08" |
80 | #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.07" | 80 | #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.08" |
81 | #define WHAT_MAGIC_STRING "@" "(" "#" ")" | 81 | #define WHAT_MAGIC_STRING "@" "(" "#" ")" |
82 | 82 | ||
83 | #define show_mptmod_ver(s,ver) \ | 83 | #define show_mptmod_ver(s,ver) \ |
@@ -331,6 +331,7 @@ typedef struct _SYSIF_REGS | |||
331 | * VirtDevice - FC LUN device or SCSI target device | 331 | * VirtDevice - FC LUN device or SCSI target device |
332 | */ | 332 | */ |
333 | typedef struct _VirtTarget { | 333 | typedef struct _VirtTarget { |
334 | struct scsi_target *starget; | ||
334 | u8 tflags; | 335 | u8 tflags; |
335 | u8 ioc_id; | 336 | u8 ioc_id; |
336 | u8 target_id; | 337 | u8 target_id; |
@@ -343,14 +344,10 @@ typedef struct _VirtTarget { | |||
343 | u8 type; /* byte 0 of Inquiry data */ | 344 | u8 type; /* byte 0 of Inquiry data */ |
344 | u32 num_luns; | 345 | u32 num_luns; |
345 | u32 luns[8]; /* Max LUNs is 256 */ | 346 | u32 luns[8]; /* Max LUNs is 256 */ |
346 | u8 inq_data[8]; | ||
347 | } VirtTarget; | 347 | } VirtTarget; |
348 | 348 | ||
349 | typedef struct _VirtDevice { | 349 | typedef struct _VirtDevice { |
350 | VirtTarget *vtarget; | 350 | VirtTarget *vtarget; |
351 | u8 ioc_id; | ||
352 | u8 bus_id; | ||
353 | u8 target_id; | ||
354 | u8 configured_lun; | 351 | u8 configured_lun; |
355 | u32 lun; | 352 | u32 lun; |
356 | } VirtDevice; | 353 | } VirtDevice; |
@@ -364,6 +361,7 @@ typedef struct _VirtDevice { | |||
364 | #define MPT_TARGET_FLAGS_Q_YES 0x08 | 361 | #define MPT_TARGET_FLAGS_Q_YES 0x08 |
365 | #define MPT_TARGET_FLAGS_VALID_56 0x10 | 362 | #define MPT_TARGET_FLAGS_VALID_56 0x10 |
366 | #define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20 | 363 | #define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20 |
364 | #define MPT_TARGET_FLAGS_RAID_COMPONENT 0x40 | ||
367 | 365 | ||
368 | /* | 366 | /* |
369 | * /proc/mpt interface | 367 | * /proc/mpt interface |
@@ -447,13 +445,6 @@ typedef struct _mpt_ioctl_events { | |||
447 | * Substructure to store SCSI specific configuration page data | 445 | * Substructure to store SCSI specific configuration page data |
448 | */ | 446 | */ |
449 | /* dvStatus defines: */ | 447 | /* dvStatus defines: */ |
450 | #define MPT_SCSICFG_NEGOTIATE 0x01 /* Negotiate on next IO */ | ||
451 | #define MPT_SCSICFG_NEED_DV 0x02 /* Schedule DV */ | ||
452 | #define MPT_SCSICFG_DV_PENDING 0x04 /* DV on this physical id pending */ | ||
453 | #define MPT_SCSICFG_DV_NOT_DONE 0x08 /* DV has not been performed */ | ||
454 | #define MPT_SCSICFG_BLK_NEGO 0x10 /* WriteSDP1 with WDTR and SDTR disabled */ | ||
455 | #define MPT_SCSICFG_RELOAD_IOC_PG3 0x20 /* IOC Pg 3 data is obsolete */ | ||
456 | /* Args passed to writeSDP1: */ | ||
457 | #define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */ | 448 | #define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */ |
458 | #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ | 449 | #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ |
459 | /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ | 450 | /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ |
@@ -464,7 +455,6 @@ typedef struct _SpiCfgData { | |||
464 | IOCPage4_t *pIocPg4; /* SEP devices addressing */ | 455 | IOCPage4_t *pIocPg4; /* SEP devices addressing */ |
465 | dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ | 456 | dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ |
466 | int IocPg4Sz; /* IOCPage4 size */ | 457 | int IocPg4Sz; /* IOCPage4 size */ |
467 | u8 dvStatus[MPT_MAX_SCSI_DEVICES]; | ||
468 | u8 minSyncFactor; /* 0xFF if async */ | 458 | u8 minSyncFactor; /* 0xFF if async */ |
469 | u8 maxSyncOffset; /* 0 if async */ | 459 | u8 maxSyncOffset; /* 0 if async */ |
470 | u8 maxBusWidth; /* 0 if narrow, 1 if wide */ | 460 | u8 maxBusWidth; /* 0 if narrow, 1 if wide */ |
@@ -474,13 +464,11 @@ typedef struct _SpiCfgData { | |||
474 | u8 sdp0version; /* SDP0 version */ | 464 | u8 sdp0version; /* SDP0 version */ |
475 | u8 sdp0length; /* SDP0 length */ | 465 | u8 sdp0length; /* SDP0 length */ |
476 | u8 dvScheduled; /* 1 if scheduled */ | 466 | u8 dvScheduled; /* 1 if scheduled */ |
477 | u8 forceDv; /* 1 to force DV scheduling */ | ||
478 | u8 noQas; /* Disable QAS for this adapter */ | 467 | u8 noQas; /* Disable QAS for this adapter */ |
479 | u8 Saf_Te; /* 1 to force all Processors as | 468 | u8 Saf_Te; /* 1 to force all Processors as |
480 | * SAF-TE if Inquiry data length | 469 | * SAF-TE if Inquiry data length |
481 | * is too short to check for SAF-TE | 470 | * is too short to check for SAF-TE |
482 | */ | 471 | */ |
483 | u8 mpt_dv; /* command line option: enhanced=1, basic=0 */ | ||
484 | u8 bus_reset; /* 1 to allow bus reset */ | 472 | u8 bus_reset; /* 1 to allow bus reset */ |
485 | u8 rsvd[1]; | 473 | u8 rsvd[1]; |
486 | }SpiCfgData; | 474 | }SpiCfgData; |
@@ -631,6 +619,10 @@ typedef struct _MPT_ADAPTER | |||
631 | struct net_device *netdev; | 619 | struct net_device *netdev; |
632 | struct list_head sas_topology; | 620 | struct list_head sas_topology; |
633 | struct mutex sas_topology_mutex; | 621 | struct mutex sas_topology_mutex; |
622 | struct mutex sas_discovery_mutex; | ||
623 | u8 sas_discovery_runtime; | ||
624 | u8 sas_discovery_ignore_events; | ||
625 | int sas_index; /* index refrencing */ | ||
634 | MPT_SAS_MGMT sas_mgmt; | 626 | MPT_SAS_MGMT sas_mgmt; |
635 | int num_ports; | 627 | int num_ports; |
636 | struct work_struct mptscsih_persistTask; | 628 | struct work_struct mptscsih_persistTask; |
@@ -728,12 +720,18 @@ typedef struct _mpt_sge { | |||
728 | #define dhsprintk(x) | 720 | #define dhsprintk(x) |
729 | #endif | 721 | #endif |
730 | 722 | ||
731 | #ifdef MPT_DEBUG_EVENTS | 723 | #if defined(MPT_DEBUG_EVENTS) || defined(MPT_DEBUG_VERBOSE_EVENTS) |
732 | #define devtprintk(x) printk x | 724 | #define devtprintk(x) printk x |
733 | #else | 725 | #else |
734 | #define devtprintk(x) | 726 | #define devtprintk(x) |
735 | #endif | 727 | #endif |
736 | 728 | ||
729 | #ifdef MPT_DEBUG_VERBOSE_EVENTS | ||
730 | #define devtverboseprintk(x) printk x | ||
731 | #else | ||
732 | #define devtverboseprintk(x) | ||
733 | #endif | ||
734 | |||
737 | #ifdef MPT_DEBUG_RESET | 735 | #ifdef MPT_DEBUG_RESET |
738 | #define drsprintk(x) printk x | 736 | #define drsprintk(x) printk x |
739 | #else | 737 | #else |
@@ -1030,10 +1028,8 @@ extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); | |||
1030 | extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); | 1028 | extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); |
1031 | extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); | 1029 | extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); |
1032 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); | 1030 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); |
1033 | extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); | ||
1034 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | 1031 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); |
1035 | extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); | 1032 | extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); |
1036 | extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc); | ||
1037 | 1033 | ||
1038 | /* | 1034 | /* |
1039 | * Public data decl's... | 1035 | * Public data decl's... |
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 9b64e07400da..b4967bb8a7d6 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c | |||
@@ -140,7 +140,7 @@ static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase); | |||
140 | * Event Handler function | 140 | * Event Handler function |
141 | */ | 141 | */ |
142 | static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); | 142 | static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); |
143 | struct fasync_struct *async_queue=NULL; | 143 | static struct fasync_struct *async_queue=NULL; |
144 | 144 | ||
145 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 145 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
146 | /* | 146 | /* |
@@ -497,7 +497,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
497 | if (event == 0x21 ) { | 497 | if (event == 0x21 ) { |
498 | ioc->aen_event_read_flag=1; | 498 | ioc->aen_event_read_flag=1; |
499 | dctlprintk(("Raised SIGIO to application\n")); | 499 | dctlprintk(("Raised SIGIO to application\n")); |
500 | devtprintk(("Raised SIGIO to application\n")); | 500 | devtverboseprintk(("Raised SIGIO to application\n")); |
501 | kill_fasync(&async_queue, SIGIO, POLL_IN); | 501 | kill_fasync(&async_queue, SIGIO, POLL_IN); |
502 | return 1; | 502 | return 1; |
503 | } | 503 | } |
@@ -515,7 +515,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
515 | if (ioc->events && (ioc->eventTypes & ( 1 << event))) { | 515 | if (ioc->events && (ioc->eventTypes & ( 1 << event))) { |
516 | ioc->aen_event_read_flag=1; | 516 | ioc->aen_event_read_flag=1; |
517 | dctlprintk(("Raised SIGIO to application\n")); | 517 | dctlprintk(("Raised SIGIO to application\n")); |
518 | devtprintk(("Raised SIGIO to application\n")); | 518 | devtverboseprintk(("Raised SIGIO to application\n")); |
519 | kill_fasync(&async_queue, SIGIO, POLL_IN); | 519 | kill_fasync(&async_queue, SIGIO, POLL_IN); |
520 | } | 520 | } |
521 | return 1; | 521 | return 1; |
@@ -2968,7 +2968,7 @@ static int __init mptctl_init(void) | |||
2968 | } | 2968 | } |
2969 | 2969 | ||
2970 | if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) { | 2970 | if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) { |
2971 | devtprintk((KERN_INFO MYNAM | 2971 | devtverboseprintk((KERN_INFO MYNAM |
2972 | ": Registered for IOC event notifications\n")); | 2972 | ": Registered for IOC event notifications\n")); |
2973 | } | 2973 | } |
2974 | 2974 | ||
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index c3a3499bce2a..b343f2a68b1c 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
@@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(pci, mptfc_pci_table); | |||
154 | 154 | ||
155 | static struct scsi_transport_template *mptfc_transport_template = NULL; | 155 | static struct scsi_transport_template *mptfc_transport_template = NULL; |
156 | 156 | ||
157 | struct fc_function_template mptfc_transport_functions = { | 157 | static struct fc_function_template mptfc_transport_functions = { |
158 | .dd_fcrport_size = 8, | 158 | .dd_fcrport_size = 8, |
159 | .show_host_node_name = 1, | 159 | .show_host_node_name = 1, |
160 | .show_host_port_name = 1, | 160 | .show_host_port_name = 1, |
@@ -349,24 +349,6 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid) | |||
349 | } | 349 | } |
350 | 350 | ||
351 | static void | 351 | static void |
352 | mptfc_remap_sdev(struct scsi_device *sdev, void *arg) | ||
353 | { | ||
354 | VirtDevice *vdev; | ||
355 | VirtTarget *vtarget; | ||
356 | struct scsi_target *starget; | ||
357 | |||
358 | starget = scsi_target(sdev); | ||
359 | if (starget->hostdata == arg) { | ||
360 | vtarget = arg; | ||
361 | vdev = sdev->hostdata; | ||
362 | if (vdev) { | ||
363 | vdev->bus_id = vtarget->bus_id; | ||
364 | vdev->target_id = vtarget->target_id; | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | |||
369 | static void | ||
370 | mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | 352 | mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) |
371 | { | 353 | { |
372 | struct fc_rport_identifiers rport_ids; | 354 | struct fc_rport_identifiers rport_ids; |
@@ -423,8 +405,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | |||
423 | if (vtarget) { | 405 | if (vtarget) { |
424 | vtarget->target_id = pg0->CurrentTargetID; | 406 | vtarget->target_id = pg0->CurrentTargetID; |
425 | vtarget->bus_id = pg0->CurrentBus; | 407 | vtarget->bus_id = pg0->CurrentBus; |
426 | starget_for_each_device(ri->starget, | ||
427 | vtarget,mptfc_remap_sdev); | ||
428 | } | 408 | } |
429 | ri->remap_needed = 0; | 409 | ri->remap_needed = 0; |
430 | } | 410 | } |
@@ -432,7 +412,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | |||
432 | "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " | 412 | "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " |
433 | "rport tid %d, tmo %d\n", | 413 | "rport tid %d, tmo %d\n", |
434 | ioc->name, | 414 | ioc->name, |
435 | oc->sh->host_no, | 415 | ioc->sh->host_no, |
436 | pg0->PortIdentifier, | 416 | pg0->PortIdentifier, |
437 | pg0->WWNN, | 417 | pg0->WWNN, |
438 | pg0->WWPN, | 418 | pg0->WWPN, |
@@ -514,7 +494,7 @@ mptfc_target_alloc(struct scsi_target *starget) | |||
514 | * Return non-zero if allocation fails. | 494 | * Return non-zero if allocation fails. |
515 | * Init memory once per LUN. | 495 | * Init memory once per LUN. |
516 | */ | 496 | */ |
517 | int | 497 | static int |
518 | mptfc_slave_alloc(struct scsi_device *sdev) | 498 | mptfc_slave_alloc(struct scsi_device *sdev) |
519 | { | 499 | { |
520 | MPT_SCSI_HOST *hd; | 500 | MPT_SCSI_HOST *hd; |
@@ -553,23 +533,26 @@ mptfc_slave_alloc(struct scsi_device *sdev) | |||
553 | } | 533 | } |
554 | 534 | ||
555 | vdev->vtarget = vtarget; | 535 | vdev->vtarget = vtarget; |
556 | vdev->ioc_id = hd->ioc->id; | ||
557 | vdev->lun = sdev->lun; | 536 | vdev->lun = sdev->lun; |
558 | vdev->target_id = vtarget->target_id; | ||
559 | vdev->bus_id = vtarget->bus_id; | ||
560 | 537 | ||
561 | spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); | 538 | spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); |
562 | 539 | ||
563 | vtarget->num_luns++; | 540 | vtarget->num_luns++; |
564 | 541 | ||
542 | #ifdef DMPT_DEBUG_FC | ||
543 | { | ||
544 | struct mptfc_rport_info *ri; | ||
545 | ri = *((struct mptfc_rport_info **)rport->dd_data); | ||
565 | dfcprintk ((MYIOC_s_INFO_FMT | 546 | dfcprintk ((MYIOC_s_INFO_FMT |
566 | "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " | 547 | "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " |
567 | "CurrentTargetID %d, %x %llx %llx\n", | 548 | "CurrentTargetID %d, %x %llx %llx\n", |
568 | ioc->name, | 549 | hd->ioc->name, |
569 | sdev->host->host_no, | 550 | sdev->host->host_no, |
570 | vtarget->num_luns, | 551 | vtarget->num_luns, |
571 | sdev->id, ri->pg0.CurrentTargetID, | 552 | sdev->id, ri->pg0.CurrentTargetID, |
572 | ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN)); | 553 | ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN)); |
554 | } | ||
555 | #endif | ||
573 | 556 | ||
574 | return 0; | 557 | return 0; |
575 | } | 558 | } |
@@ -941,7 +924,7 @@ mptfc_init(void) | |||
941 | mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); | 924 | mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); |
942 | 925 | ||
943 | if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { | 926 | if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { |
944 | devtprintk((KERN_INFO MYNAM | 927 | devtverboseprintk((KERN_INFO MYNAM |
945 | ": Registered for IOC event notifications\n")); | 928 | ": Registered for IOC event notifications\n")); |
946 | } | 929 | } |
947 | 930 | ||
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 73f59528212a..314c3a27585d 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c | |||
@@ -1152,10 +1152,7 @@ mpt_lan_receive_post_reply(struct net_device *dev, | |||
1152 | priv->mpt_rxfidx_tail, | 1152 | priv->mpt_rxfidx_tail, |
1153 | MPT_LAN_MAX_BUCKETS_OUT); | 1153 | MPT_LAN_MAX_BUCKETS_OUT); |
1154 | 1154 | ||
1155 | panic("Damn it Jim! I'm a doctor, not a programmer! " | 1155 | return -1; |
1156 | "Oh, wait a sec, I am a programmer. " | ||
1157 | "And, who's Jim?!?!\n" | ||
1158 | "Arrgghh! We've done it again!\n"); | ||
1159 | } | 1156 | } |
1160 | 1157 | ||
1161 | if (remaining == 0) | 1158 | if (remaining == 0) |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 2512d0e6155e..010d4a39269b 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
@@ -104,6 +104,13 @@ struct mptsas_hotplug_event { | |||
104 | u16 handle; | 104 | u16 handle; |
105 | u16 parent_handle; | 105 | u16 parent_handle; |
106 | u8 phy_id; | 106 | u8 phy_id; |
107 | u8 phys_disk_num; | ||
108 | u8 phys_disk_num_valid; | ||
109 | }; | ||
110 | |||
111 | struct mptsas_discovery_event { | ||
112 | struct work_struct work; | ||
113 | MPT_ADAPTER *ioc; | ||
107 | }; | 114 | }; |
108 | 115 | ||
109 | /* | 116 | /* |
@@ -117,6 +124,8 @@ struct mptsas_hotplug_event { | |||
117 | struct mptsas_devinfo { | 124 | struct mptsas_devinfo { |
118 | u16 handle; /* unique id to address this device */ | 125 | u16 handle; /* unique id to address this device */ |
119 | u16 handle_parent; /* unique id to address parent device */ | 126 | u16 handle_parent; /* unique id to address parent device */ |
127 | u16 handle_enclosure; /* enclosure identifier of the enclosure */ | ||
128 | u16 slot; /* physical slot in enclosure */ | ||
120 | u8 phy_id; /* phy number of parent device */ | 129 | u8 phy_id; /* phy number of parent device */ |
121 | u8 port_id; /* sas physical port this device | 130 | u8 port_id; /* sas physical port this device |
122 | is assoc'd with */ | 131 | is assoc'd with */ |
@@ -137,6 +146,7 @@ struct mptsas_phyinfo { | |||
137 | struct mptsas_devinfo attached; /* point to attached device info */ | 146 | struct mptsas_devinfo attached; /* point to attached device info */ |
138 | struct sas_phy *phy; | 147 | struct sas_phy *phy; |
139 | struct sas_rphy *rphy; | 148 | struct sas_rphy *rphy; |
149 | struct scsi_target *starget; | ||
140 | }; | 150 | }; |
141 | 151 | ||
142 | struct mptsas_portinfo { | 152 | struct mptsas_portinfo { |
@@ -146,6 +156,17 @@ struct mptsas_portinfo { | |||
146 | struct mptsas_phyinfo *phy_info; | 156 | struct mptsas_phyinfo *phy_info; |
147 | }; | 157 | }; |
148 | 158 | ||
159 | struct mptsas_enclosure { | ||
160 | u64 enclosure_logical_id; /* The WWN for the enclosure */ | ||
161 | u16 enclosure_handle; /* unique id to address this */ | ||
162 | u16 flags; /* details enclosure management */ | ||
163 | u16 num_slot; /* num slots */ | ||
164 | u16 start_slot; /* first slot */ | ||
165 | u8 start_id; /* starting logical target id */ | ||
166 | u8 start_channel; /* starting logical channel id */ | ||
167 | u8 sep_id; /* SEP device logical target id */ | ||
168 | u8 sep_channel; /* SEP channel logical channel id */ | ||
169 | }; | ||
149 | 170 | ||
150 | #ifdef SASDEBUG | 171 | #ifdef SASDEBUG |
151 | static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) | 172 | static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) |
@@ -205,6 +226,7 @@ static void mptsas_print_device_pg0(SasDevicePage0_t *pg0) | |||
205 | 226 | ||
206 | printk("---- SAS DEVICE PAGE 0 ---------\n"); | 227 | printk("---- SAS DEVICE PAGE 0 ---------\n"); |
207 | printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)); | 228 | printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)); |
229 | printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle)); | ||
208 | printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)); | 230 | printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)); |
209 | printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot)); | 231 | printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot)); |
210 | printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address)); | 232 | printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address)); |
@@ -243,6 +265,111 @@ static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1) | |||
243 | #define mptsas_print_expander_pg1(pg1) do { } while (0) | 265 | #define mptsas_print_expander_pg1(pg1) do { } while (0) |
244 | #endif | 266 | #endif |
245 | 267 | ||
268 | static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) | ||
269 | { | ||
270 | struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); | ||
271 | return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; | ||
272 | } | ||
273 | |||
274 | static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy) | ||
275 | { | ||
276 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); | ||
277 | return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * mptsas_find_portinfo_by_handle | ||
282 | * | ||
283 | * This function should be called with the sas_topology_mutex already held | ||
284 | */ | ||
285 | static struct mptsas_portinfo * | ||
286 | mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) | ||
287 | { | ||
288 | struct mptsas_portinfo *port_info, *rc=NULL; | ||
289 | int i; | ||
290 | |||
291 | list_for_each_entry(port_info, &ioc->sas_topology, list) | ||
292 | for (i = 0; i < port_info->num_phys; i++) | ||
293 | if (port_info->phy_info[i].identify.handle == handle) { | ||
294 | rc = port_info; | ||
295 | goto out; | ||
296 | } | ||
297 | out: | ||
298 | return rc; | ||
299 | } | ||
300 | |||
301 | static int | ||
302 | mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, | ||
303 | u32 form, u32 form_specific) | ||
304 | { | ||
305 | ConfigExtendedPageHeader_t hdr; | ||
306 | CONFIGPARMS cfg; | ||
307 | SasEnclosurePage0_t *buffer; | ||
308 | dma_addr_t dma_handle; | ||
309 | int error; | ||
310 | __le64 le_identifier; | ||
311 | |||
312 | memset(&hdr, 0, sizeof(hdr)); | ||
313 | hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION; | ||
314 | hdr.PageNumber = 0; | ||
315 | hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | ||
316 | hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE; | ||
317 | |||
318 | cfg.cfghdr.ehdr = &hdr; | ||
319 | cfg.physAddr = -1; | ||
320 | cfg.pageAddr = form + form_specific; | ||
321 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
322 | cfg.dir = 0; /* read */ | ||
323 | cfg.timeout = 10; | ||
324 | |||
325 | error = mpt_config(ioc, &cfg); | ||
326 | if (error) | ||
327 | goto out; | ||
328 | if (!hdr.ExtPageLength) { | ||
329 | error = -ENXIO; | ||
330 | goto out; | ||
331 | } | ||
332 | |||
333 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
334 | &dma_handle); | ||
335 | if (!buffer) { | ||
336 | error = -ENOMEM; | ||
337 | goto out; | ||
338 | } | ||
339 | |||
340 | cfg.physAddr = dma_handle; | ||
341 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
342 | |||
343 | error = mpt_config(ioc, &cfg); | ||
344 | if (error) | ||
345 | goto out_free_consistent; | ||
346 | |||
347 | /* save config data */ | ||
348 | memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64)); | ||
349 | enclosure->enclosure_logical_id = le64_to_cpu(le_identifier); | ||
350 | enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle); | ||
351 | enclosure->flags = le16_to_cpu(buffer->Flags); | ||
352 | enclosure->num_slot = le16_to_cpu(buffer->NumSlots); | ||
353 | enclosure->start_slot = le16_to_cpu(buffer->StartSlot); | ||
354 | enclosure->start_id = buffer->StartTargetID; | ||
355 | enclosure->start_channel = buffer->StartBus; | ||
356 | enclosure->sep_id = buffer->SEPTargetID; | ||
357 | enclosure->sep_channel = buffer->SEPBus; | ||
358 | |||
359 | out_free_consistent: | ||
360 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
361 | buffer, dma_handle); | ||
362 | out: | ||
363 | return error; | ||
364 | } | ||
365 | |||
366 | static int | ||
367 | mptsas_slave_configure(struct scsi_device *sdev) | ||
368 | { | ||
369 | sas_read_port_mode_page(sdev); | ||
370 | |||
371 | return mptscsih_slave_configure(sdev); | ||
372 | } | ||
246 | 373 | ||
247 | /* | 374 | /* |
248 | * This is pretty ugly. We will be able to seriously clean it up | 375 | * This is pretty ugly. We will be able to seriously clean it up |
@@ -259,6 +386,7 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
259 | VirtTarget *vtarget; | 386 | VirtTarget *vtarget; |
260 | VirtDevice *vdev; | 387 | VirtDevice *vdev; |
261 | struct scsi_target *starget; | 388 | struct scsi_target *starget; |
389 | u32 target_id; | ||
262 | int i; | 390 | int i; |
263 | 391 | ||
264 | vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); | 392 | vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); |
@@ -267,10 +395,10 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
267 | hd->ioc->name, sizeof(VirtDevice)); | 395 | hd->ioc->name, sizeof(VirtDevice)); |
268 | return -ENOMEM; | 396 | return -ENOMEM; |
269 | } | 397 | } |
270 | vdev->ioc_id = hd->ioc->id; | ||
271 | sdev->hostdata = vdev; | 398 | sdev->hostdata = vdev; |
272 | starget = scsi_target(sdev); | 399 | starget = scsi_target(sdev); |
273 | vtarget = starget->hostdata; | 400 | vtarget = starget->hostdata; |
401 | vtarget->ioc_id = hd->ioc->id; | ||
274 | vdev->vtarget = vtarget; | 402 | vdev->vtarget = vtarget; |
275 | if (vtarget->num_luns == 0) { | 403 | if (vtarget->num_luns == 0) { |
276 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; | 404 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; |
@@ -281,8 +409,8 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
281 | RAID volumes placed beyond the last expected port. | 409 | RAID volumes placed beyond the last expected port. |
282 | */ | 410 | */ |
283 | if (sdev->channel == hd->ioc->num_ports) { | 411 | if (sdev->channel == hd->ioc->num_ports) { |
284 | vdev->target_id = sdev->id; | 412 | target_id = sdev->id; |
285 | vdev->bus_id = 0; | 413 | vtarget->bus_id = 0; |
286 | vdev->lun = 0; | 414 | vdev->lun = 0; |
287 | goto out; | 415 | goto out; |
288 | } | 416 | } |
@@ -293,11 +421,21 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
293 | for (i = 0; i < p->num_phys; i++) { | 421 | for (i = 0; i < p->num_phys; i++) { |
294 | if (p->phy_info[i].attached.sas_address == | 422 | if (p->phy_info[i].attached.sas_address == |
295 | rphy->identify.sas_address) { | 423 | rphy->identify.sas_address) { |
296 | vdev->target_id = | 424 | target_id = p->phy_info[i].attached.id; |
297 | p->phy_info[i].attached.id; | 425 | vtarget->bus_id = p->phy_info[i].attached.channel; |
298 | vdev->bus_id = p->phy_info[i].attached.channel; | ||
299 | vdev->lun = sdev->lun; | 426 | vdev->lun = sdev->lun; |
300 | mutex_unlock(&hd->ioc->sas_topology_mutex); | 427 | p->phy_info[i].starget = sdev->sdev_target; |
428 | /* | ||
429 | * Exposing hidden disk (RAID) | ||
430 | */ | ||
431 | if (mptscsih_is_phys_disk(hd->ioc, target_id)) { | ||
432 | target_id = mptscsih_raid_id_to_num(hd, | ||
433 | target_id); | ||
434 | vdev->vtarget->tflags |= | ||
435 | MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
436 | sdev->no_uld_attach = 1; | ||
437 | } | ||
438 | mutex_unlock(&hd->ioc->sas_topology_mutex); | ||
301 | goto out; | 439 | goto out; |
302 | } | 440 | } |
303 | } | 441 | } |
@@ -308,9 +446,7 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
308 | return -ENXIO; | 446 | return -ENXIO; |
309 | 447 | ||
310 | out: | 448 | out: |
311 | vtarget->ioc_id = vdev->ioc_id; | 449 | vtarget->target_id = target_id; |
312 | vtarget->target_id = vdev->target_id; | ||
313 | vtarget->bus_id = vdev->bus_id; | ||
314 | vtarget->num_luns++; | 450 | vtarget->num_luns++; |
315 | return 0; | 451 | return 0; |
316 | } | 452 | } |
@@ -320,41 +456,17 @@ mptsas_slave_destroy(struct scsi_device *sdev) | |||
320 | { | 456 | { |
321 | struct Scsi_Host *host = sdev->host; | 457 | struct Scsi_Host *host = sdev->host; |
322 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | 458 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; |
323 | struct sas_rphy *rphy; | ||
324 | struct mptsas_portinfo *p; | ||
325 | int i; | ||
326 | VirtDevice *vdev; | 459 | VirtDevice *vdev; |
327 | 460 | ||
328 | /* | 461 | /* |
329 | * Handle hotplug removal case. | ||
330 | * We need to clear out attached data structure. | ||
331 | */ | ||
332 | rphy = dev_to_rphy(sdev->sdev_target->dev.parent); | ||
333 | |||
334 | mutex_lock(&hd->ioc->sas_topology_mutex); | ||
335 | list_for_each_entry(p, &hd->ioc->sas_topology, list) { | ||
336 | for (i = 0; i < p->num_phys; i++) { | ||
337 | if (p->phy_info[i].attached.sas_address == | ||
338 | rphy->identify.sas_address) { | ||
339 | memset(&p->phy_info[i].attached, 0, | ||
340 | sizeof(struct mptsas_devinfo)); | ||
341 | p->phy_info[i].rphy = NULL; | ||
342 | goto out; | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | |||
347 | out: | ||
348 | mutex_unlock(&hd->ioc->sas_topology_mutex); | ||
349 | /* | ||
350 | * Issue target reset to flush firmware outstanding commands. | 462 | * Issue target reset to flush firmware outstanding commands. |
351 | */ | 463 | */ |
352 | vdev = sdev->hostdata; | 464 | vdev = sdev->hostdata; |
353 | if (vdev->configured_lun){ | 465 | if (vdev->configured_lun){ |
354 | if (mptscsih_TMHandler(hd, | 466 | if (mptscsih_TMHandler(hd, |
355 | MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, | 467 | MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, |
356 | vdev->bus_id, | 468 | vdev->vtarget->bus_id, |
357 | vdev->target_id, | 469 | vdev->vtarget->target_id, |
358 | 0, 0, 5 /* 5 second timeout */) | 470 | 0, 0, 5 /* 5 second timeout */) |
359 | < 0){ | 471 | < 0){ |
360 | 472 | ||
@@ -364,7 +476,7 @@ mptsas_slave_destroy(struct scsi_device *sdev) | |||
364 | printk(MYIOC_s_WARN_FMT | 476 | printk(MYIOC_s_WARN_FMT |
365 | "Error processing TaskMgmt id=%d TARGET_RESET\n", | 477 | "Error processing TaskMgmt id=%d TARGET_RESET\n", |
366 | hd->ioc->name, | 478 | hd->ioc->name, |
367 | vdev->target_id); | 479 | vdev->vtarget->target_id); |
368 | 480 | ||
369 | hd->tmPending = 0; | 481 | hd->tmPending = 0; |
370 | hd->tmState = TM_STATE_NONE; | 482 | hd->tmState = TM_STATE_NONE; |
@@ -382,7 +494,7 @@ static struct scsi_host_template mptsas_driver_template = { | |||
382 | .queuecommand = mptscsih_qcmd, | 494 | .queuecommand = mptscsih_qcmd, |
383 | .target_alloc = mptscsih_target_alloc, | 495 | .target_alloc = mptscsih_target_alloc, |
384 | .slave_alloc = mptsas_slave_alloc, | 496 | .slave_alloc = mptsas_slave_alloc, |
385 | .slave_configure = mptscsih_slave_configure, | 497 | .slave_configure = mptsas_slave_configure, |
386 | .target_destroy = mptscsih_target_destroy, | 498 | .target_destroy = mptscsih_target_destroy, |
387 | .slave_destroy = mptsas_slave_destroy, | 499 | .slave_destroy = mptsas_slave_destroy, |
388 | .change_queue_depth = mptscsih_change_queue_depth, | 500 | .change_queue_depth = mptscsih_change_queue_depth, |
@@ -399,12 +511,6 @@ static struct scsi_host_template mptsas_driver_template = { | |||
399 | .use_clustering = ENABLE_CLUSTERING, | 511 | .use_clustering = ENABLE_CLUSTERING, |
400 | }; | 512 | }; |
401 | 513 | ||
402 | static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) | ||
403 | { | ||
404 | struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); | ||
405 | return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; | ||
406 | } | ||
407 | |||
408 | static int mptsas_get_linkerrors(struct sas_phy *phy) | 514 | static int mptsas_get_linkerrors(struct sas_phy *phy) |
409 | { | 515 | { |
410 | MPT_ADAPTER *ioc = phy_to_ioc(phy); | 516 | MPT_ADAPTER *ioc = phy_to_ioc(phy); |
@@ -546,8 +652,67 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) | |||
546 | return error; | 652 | return error; |
547 | } | 653 | } |
548 | 654 | ||
655 | static int | ||
656 | mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) | ||
657 | { | ||
658 | MPT_ADAPTER *ioc = rphy_to_ioc(rphy); | ||
659 | int i, error; | ||
660 | struct mptsas_portinfo *p; | ||
661 | struct mptsas_enclosure enclosure_info; | ||
662 | u64 enclosure_handle; | ||
663 | |||
664 | mutex_lock(&ioc->sas_topology_mutex); | ||
665 | list_for_each_entry(p, &ioc->sas_topology, list) { | ||
666 | for (i = 0; i < p->num_phys; i++) { | ||
667 | if (p->phy_info[i].attached.sas_address == | ||
668 | rphy->identify.sas_address) { | ||
669 | enclosure_handle = p->phy_info[i]. | ||
670 | attached.handle_enclosure; | ||
671 | goto found_info; | ||
672 | } | ||
673 | } | ||
674 | } | ||
675 | mutex_unlock(&ioc->sas_topology_mutex); | ||
676 | return -ENXIO; | ||
677 | |||
678 | found_info: | ||
679 | mutex_unlock(&ioc->sas_topology_mutex); | ||
680 | memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure)); | ||
681 | error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info, | ||
682 | (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << | ||
683 | MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle); | ||
684 | if (!error) | ||
685 | *identifier = enclosure_info.enclosure_logical_id; | ||
686 | return error; | ||
687 | } | ||
688 | |||
689 | static int | ||
690 | mptsas_get_bay_identifier(struct sas_rphy *rphy) | ||
691 | { | ||
692 | MPT_ADAPTER *ioc = rphy_to_ioc(rphy); | ||
693 | struct mptsas_portinfo *p; | ||
694 | int i, rc; | ||
695 | |||
696 | mutex_lock(&ioc->sas_topology_mutex); | ||
697 | list_for_each_entry(p, &ioc->sas_topology, list) { | ||
698 | for (i = 0; i < p->num_phys; i++) { | ||
699 | if (p->phy_info[i].attached.sas_address == | ||
700 | rphy->identify.sas_address) { | ||
701 | rc = p->phy_info[i].attached.slot; | ||
702 | goto out; | ||
703 | } | ||
704 | } | ||
705 | } | ||
706 | rc = -ENXIO; | ||
707 | out: | ||
708 | mutex_unlock(&ioc->sas_topology_mutex); | ||
709 | return rc; | ||
710 | } | ||
711 | |||
549 | static struct sas_function_template mptsas_transport_functions = { | 712 | static struct sas_function_template mptsas_transport_functions = { |
550 | .get_linkerrors = mptsas_get_linkerrors, | 713 | .get_linkerrors = mptsas_get_linkerrors, |
714 | .get_enclosure_identifier = mptsas_get_enclosure_identifier, | ||
715 | .get_bay_identifier = mptsas_get_bay_identifier, | ||
551 | .phy_reset = mptsas_phy_reset, | 716 | .phy_reset = mptsas_phy_reset, |
552 | }; | 717 | }; |
553 | 718 | ||
@@ -607,6 +772,9 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) | |||
607 | goto out_free_consistent; | 772 | goto out_free_consistent; |
608 | } | 773 | } |
609 | 774 | ||
775 | if (port_info->num_phys) | ||
776 | port_info->handle = | ||
777 | le16_to_cpu(buffer->PhyData[0].ControllerDevHandle); | ||
610 | for (i = 0; i < port_info->num_phys; i++) { | 778 | for (i = 0; i < port_info->num_phys; i++) { |
611 | mptsas_print_phy_data(&buffer->PhyData[i]); | 779 | mptsas_print_phy_data(&buffer->PhyData[i]); |
612 | port_info->phy_info[i].phy_id = i; | 780 | port_info->phy_info[i].phy_id = i; |
@@ -713,6 +881,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, | |||
713 | cfg.dir = 0; /* read */ | 881 | cfg.dir = 0; /* read */ |
714 | cfg.timeout = 10; | 882 | cfg.timeout = 10; |
715 | 883 | ||
884 | memset(device_info, 0, sizeof(struct mptsas_devinfo)); | ||
716 | error = mpt_config(ioc, &cfg); | 885 | error = mpt_config(ioc, &cfg); |
717 | if (error) | 886 | if (error) |
718 | goto out; | 887 | goto out; |
@@ -739,6 +908,9 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, | |||
739 | 908 | ||
740 | device_info->handle = le16_to_cpu(buffer->DevHandle); | 909 | device_info->handle = le16_to_cpu(buffer->DevHandle); |
741 | device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); | 910 | device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); |
911 | device_info->handle_enclosure = | ||
912 | le16_to_cpu(buffer->EnclosureHandle); | ||
913 | device_info->slot = le16_to_cpu(buffer->Slot); | ||
742 | device_info->phy_id = buffer->PhyNum; | 914 | device_info->phy_id = buffer->PhyNum; |
743 | device_info->port_id = buffer->PhysicalPort; | 915 | device_info->port_id = buffer->PhysicalPort; |
744 | device_info->id = buffer->TargetID; | 916 | device_info->id = buffer->TargetID; |
@@ -780,6 +952,7 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, | |||
780 | cfg.dir = 0; /* read */ | 952 | cfg.dir = 0; /* read */ |
781 | cfg.timeout = 10; | 953 | cfg.timeout = 10; |
782 | 954 | ||
955 | memset(port_info, 0, sizeof(struct mptsas_portinfo)); | ||
783 | error = mpt_config(ioc, &cfg); | 956 | error = mpt_config(ioc, &cfg); |
784 | if (error) | 957 | if (error) |
785 | goto out; | 958 | goto out; |
@@ -880,7 +1053,6 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, | |||
880 | phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); | 1053 | phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); |
881 | phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); | 1054 | phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); |
882 | 1055 | ||
883 | |||
884 | out_free_consistent: | 1056 | out_free_consistent: |
885 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | 1057 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, |
886 | buffer, dma_handle); | 1058 | buffer, dma_handle); |
@@ -970,12 +1142,19 @@ mptsas_parse_device_info(struct sas_identify *identify, | |||
970 | static int mptsas_probe_one_phy(struct device *dev, | 1142 | static int mptsas_probe_one_phy(struct device *dev, |
971 | struct mptsas_phyinfo *phy_info, int index, int local) | 1143 | struct mptsas_phyinfo *phy_info, int index, int local) |
972 | { | 1144 | { |
1145 | MPT_ADAPTER *ioc; | ||
973 | struct sas_phy *phy; | 1146 | struct sas_phy *phy; |
974 | int error; | 1147 | int error; |
975 | 1148 | ||
976 | phy = sas_phy_alloc(dev, index); | 1149 | if (!dev) |
977 | if (!phy) | 1150 | return -ENODEV; |
978 | return -ENOMEM; | 1151 | |
1152 | if (!phy_info->phy) { | ||
1153 | phy = sas_phy_alloc(dev, index); | ||
1154 | if (!phy) | ||
1155 | return -ENOMEM; | ||
1156 | } else | ||
1157 | phy = phy_info->phy; | ||
979 | 1158 | ||
980 | phy->port_identifier = phy_info->port_id; | 1159 | phy->port_identifier = phy_info->port_id; |
981 | mptsas_parse_device_info(&phy->identify, &phy_info->identify); | 1160 | mptsas_parse_device_info(&phy->identify, &phy_info->identify); |
@@ -1061,24 +1240,54 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
1061 | break; | 1240 | break; |
1062 | } | 1241 | } |
1063 | 1242 | ||
1064 | if (local) | 1243 | if (!phy_info->phy) { |
1065 | phy->local_attached = 1; | ||
1066 | 1244 | ||
1067 | error = sas_phy_add(phy); | 1245 | if (local) |
1068 | if (error) { | 1246 | phy->local_attached = 1; |
1069 | sas_phy_free(phy); | 1247 | |
1070 | return error; | 1248 | error = sas_phy_add(phy); |
1249 | if (error) { | ||
1250 | sas_phy_free(phy); | ||
1251 | return error; | ||
1252 | } | ||
1253 | phy_info->phy = phy; | ||
1071 | } | 1254 | } |
1072 | phy_info->phy = phy; | ||
1073 | 1255 | ||
1074 | if (phy_info->attached.handle) { | 1256 | if ((phy_info->attached.handle) && |
1257 | (!phy_info->rphy)) { | ||
1258 | |||
1075 | struct sas_rphy *rphy; | 1259 | struct sas_rphy *rphy; |
1260 | struct sas_identify identify; | ||
1261 | |||
1262 | ioc = phy_to_ioc(phy_info->phy); | ||
1076 | 1263 | ||
1077 | rphy = sas_rphy_alloc(phy); | 1264 | /* |
1265 | * Let the hotplug_work thread handle processing | ||
1266 | * the adding/removing of devices that occur | ||
1267 | * after start of day. | ||
1268 | */ | ||
1269 | if (ioc->sas_discovery_runtime && | ||
1270 | mptsas_is_end_device(&phy_info->attached)) | ||
1271 | return 0; | ||
1272 | |||
1273 | mptsas_parse_device_info(&identify, &phy_info->attached); | ||
1274 | switch (identify.device_type) { | ||
1275 | case SAS_END_DEVICE: | ||
1276 | rphy = sas_end_device_alloc(phy); | ||
1277 | break; | ||
1278 | case SAS_EDGE_EXPANDER_DEVICE: | ||
1279 | case SAS_FANOUT_EXPANDER_DEVICE: | ||
1280 | rphy = sas_expander_alloc(phy, identify.device_type); | ||
1281 | break; | ||
1282 | default: | ||
1283 | rphy = NULL; | ||
1284 | break; | ||
1285 | } | ||
1078 | if (!rphy) | 1286 | if (!rphy) |
1079 | return 0; /* non-fatal: an rphy can be added later */ | 1287 | return 0; /* non-fatal: an rphy can be added later */ |
1080 | 1288 | ||
1081 | mptsas_parse_device_info(&rphy->identify, &phy_info->attached); | 1289 | rphy->identify = identify; |
1290 | |||
1082 | error = sas_rphy_add(rphy); | 1291 | error = sas_rphy_add(rphy); |
1083 | if (error) { | 1292 | if (error) { |
1084 | sas_rphy_free(rphy); | 1293 | sas_rphy_free(rphy); |
@@ -1092,24 +1301,37 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
1092 | } | 1301 | } |
1093 | 1302 | ||
1094 | static int | 1303 | static int |
1095 | mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) | 1304 | mptsas_probe_hba_phys(MPT_ADAPTER *ioc) |
1096 | { | 1305 | { |
1097 | struct mptsas_portinfo *port_info; | 1306 | struct mptsas_portinfo *port_info, *hba; |
1098 | u32 handle = 0xFFFF; | 1307 | u32 handle = 0xFFFF; |
1099 | int error = -ENOMEM, i; | 1308 | int error = -ENOMEM, i; |
1100 | 1309 | ||
1101 | port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); | 1310 | hba = kzalloc(sizeof(*port_info), GFP_KERNEL); |
1102 | if (!port_info) | 1311 | if (! hba) |
1103 | goto out; | 1312 | goto out; |
1104 | 1313 | ||
1105 | error = mptsas_sas_io_unit_pg0(ioc, port_info); | 1314 | error = mptsas_sas_io_unit_pg0(ioc, hba); |
1106 | if (error) | 1315 | if (error) |
1107 | goto out_free_port_info; | 1316 | goto out_free_port_info; |
1108 | 1317 | ||
1109 | ioc->num_ports = port_info->num_phys; | ||
1110 | mutex_lock(&ioc->sas_topology_mutex); | 1318 | mutex_lock(&ioc->sas_topology_mutex); |
1111 | list_add_tail(&port_info->list, &ioc->sas_topology); | 1319 | port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle); |
1320 | if (!port_info) { | ||
1321 | port_info = hba; | ||
1322 | list_add_tail(&port_info->list, &ioc->sas_topology); | ||
1323 | } else { | ||
1324 | port_info->handle = hba->handle; | ||
1325 | for (i = 0; i < hba->num_phys; i++) | ||
1326 | port_info->phy_info[i].negotiated_link_rate = | ||
1327 | hba->phy_info[i].negotiated_link_rate; | ||
1328 | if (hba->phy_info) | ||
1329 | kfree(hba->phy_info); | ||
1330 | kfree(hba); | ||
1331 | hba = NULL; | ||
1332 | } | ||
1112 | mutex_unlock(&ioc->sas_topology_mutex); | 1333 | mutex_unlock(&ioc->sas_topology_mutex); |
1334 | ioc->num_ports = port_info->num_phys; | ||
1113 | 1335 | ||
1114 | for (i = 0; i < port_info->num_phys; i++) { | 1336 | for (i = 0; i < port_info->num_phys; i++) { |
1115 | mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], | 1337 | mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], |
@@ -1132,38 +1354,49 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) | |||
1132 | } | 1354 | } |
1133 | 1355 | ||
1134 | mptsas_probe_one_phy(&ioc->sh->shost_gendev, | 1356 | mptsas_probe_one_phy(&ioc->sh->shost_gendev, |
1135 | &port_info->phy_info[i], *index, 1); | 1357 | &port_info->phy_info[i], ioc->sas_index, 1); |
1136 | (*index)++; | 1358 | ioc->sas_index++; |
1137 | } | 1359 | } |
1138 | 1360 | ||
1139 | return 0; | 1361 | return 0; |
1140 | 1362 | ||
1141 | out_free_port_info: | 1363 | out_free_port_info: |
1142 | kfree(port_info); | 1364 | if (hba) |
1365 | kfree(hba); | ||
1143 | out: | 1366 | out: |
1144 | return error; | 1367 | return error; |
1145 | } | 1368 | } |
1146 | 1369 | ||
1147 | static int | 1370 | static int |
1148 | mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) | 1371 | mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) |
1149 | { | 1372 | { |
1150 | struct mptsas_portinfo *port_info, *p; | 1373 | struct mptsas_portinfo *port_info, *p, *ex; |
1151 | int error = -ENOMEM, i, j; | 1374 | int error = -ENOMEM, i, j; |
1152 | 1375 | ||
1153 | port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); | 1376 | ex = kzalloc(sizeof(*port_info), GFP_KERNEL); |
1154 | if (!port_info) | 1377 | if (!ex) |
1155 | goto out; | 1378 | goto out; |
1156 | 1379 | ||
1157 | error = mptsas_sas_expander_pg0(ioc, port_info, | 1380 | error = mptsas_sas_expander_pg0(ioc, ex, |
1158 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << | 1381 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << |
1159 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); | 1382 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); |
1160 | if (error) | 1383 | if (error) |
1161 | goto out_free_port_info; | 1384 | goto out_free_port_info; |
1162 | 1385 | ||
1163 | *handle = port_info->handle; | 1386 | *handle = ex->handle; |
1164 | 1387 | ||
1165 | mutex_lock(&ioc->sas_topology_mutex); | 1388 | mutex_lock(&ioc->sas_topology_mutex); |
1166 | list_add_tail(&port_info->list, &ioc->sas_topology); | 1389 | port_info = mptsas_find_portinfo_by_handle(ioc, *handle); |
1390 | if (!port_info) { | ||
1391 | port_info = ex; | ||
1392 | list_add_tail(&port_info->list, &ioc->sas_topology); | ||
1393 | } else { | ||
1394 | port_info->handle = ex->handle; | ||
1395 | if (ex->phy_info) | ||
1396 | kfree(ex->phy_info); | ||
1397 | kfree(ex); | ||
1398 | ex = NULL; | ||
1399 | } | ||
1167 | mutex_unlock(&ioc->sas_topology_mutex); | 1400 | mutex_unlock(&ioc->sas_topology_mutex); |
1168 | 1401 | ||
1169 | for (i = 0; i < port_info->num_phys; i++) { | 1402 | for (i = 0; i < port_info->num_phys; i++) { |
@@ -1189,6 +1422,8 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) | |||
1189 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << | 1422 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << |
1190 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | 1423 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
1191 | port_info->phy_info[i].attached.handle); | 1424 | port_info->phy_info[i].attached.handle); |
1425 | port_info->phy_info[i].attached.phy_id = | ||
1426 | port_info->phy_info[i].phy_id; | ||
1192 | } | 1427 | } |
1193 | 1428 | ||
1194 | /* | 1429 | /* |
@@ -1208,27 +1443,137 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) | |||
1208 | mutex_unlock(&ioc->sas_topology_mutex); | 1443 | mutex_unlock(&ioc->sas_topology_mutex); |
1209 | 1444 | ||
1210 | mptsas_probe_one_phy(parent, &port_info->phy_info[i], | 1445 | mptsas_probe_one_phy(parent, &port_info->phy_info[i], |
1211 | *index, 0); | 1446 | ioc->sas_index, 0); |
1212 | (*index)++; | 1447 | ioc->sas_index++; |
1213 | } | 1448 | } |
1214 | 1449 | ||
1215 | return 0; | 1450 | return 0; |
1216 | 1451 | ||
1217 | out_free_port_info: | 1452 | out_free_port_info: |
1218 | kfree(port_info); | 1453 | if (ex) { |
1454 | if (ex->phy_info) | ||
1455 | kfree(ex->phy_info); | ||
1456 | kfree(ex); | ||
1457 | } | ||
1219 | out: | 1458 | out: |
1220 | return error; | 1459 | return error; |
1221 | } | 1460 | } |
1222 | 1461 | ||
1462 | /* | ||
1463 | * mptsas_delete_expander_phys | ||
1464 | * | ||
1465 | * | ||
1466 | * This will traverse topology, and remove expanders | ||
1467 | * that are no longer present | ||
1468 | */ | ||
1469 | static void | ||
1470 | mptsas_delete_expander_phys(MPT_ADAPTER *ioc) | ||
1471 | { | ||
1472 | struct mptsas_portinfo buffer; | ||
1473 | struct mptsas_portinfo *port_info, *n, *parent; | ||
1474 | int i; | ||
1475 | |||
1476 | mutex_lock(&ioc->sas_topology_mutex); | ||
1477 | list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) { | ||
1478 | |||
1479 | if (port_info->phy_info && | ||
1480 | (!(port_info->phy_info[0].identify.device_info & | ||
1481 | MPI_SAS_DEVICE_INFO_SMP_TARGET))) | ||
1482 | continue; | ||
1483 | |||
1484 | if (mptsas_sas_expander_pg0(ioc, &buffer, | ||
1485 | (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << | ||
1486 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) { | ||
1487 | |||
1488 | /* | ||
1489 | * Obtain the port_info instance to the parent port | ||
1490 | */ | ||
1491 | parent = mptsas_find_portinfo_by_handle(ioc, | ||
1492 | port_info->phy_info[0].identify.handle_parent); | ||
1493 | |||
1494 | if (!parent) | ||
1495 | goto next_port; | ||
1496 | |||
1497 | /* | ||
1498 | * Delete rphys in the parent that point | ||
1499 | * to this expander. The transport layer will | ||
1500 | * cleanup all the children. | ||
1501 | */ | ||
1502 | for (i = 0; i < parent->num_phys; i++) { | ||
1503 | if ((!parent->phy_info[i].rphy) || | ||
1504 | (parent->phy_info[i].attached.sas_address != | ||
1505 | port_info->phy_info[i].identify.sas_address)) | ||
1506 | continue; | ||
1507 | sas_rphy_delete(parent->phy_info[i].rphy); | ||
1508 | memset(&parent->phy_info[i].attached, 0, | ||
1509 | sizeof(struct mptsas_devinfo)); | ||
1510 | parent->phy_info[i].rphy = NULL; | ||
1511 | parent->phy_info[i].starget = NULL; | ||
1512 | } | ||
1513 | next_port: | ||
1514 | list_del(&port_info->list); | ||
1515 | if (port_info->phy_info) | ||
1516 | kfree(port_info->phy_info); | ||
1517 | kfree(port_info); | ||
1518 | } | ||
1519 | /* | ||
1520 | * Free this memory allocated from inside | ||
1521 | * mptsas_sas_expander_pg0 | ||
1522 | */ | ||
1523 | if (buffer.phy_info) | ||
1524 | kfree(buffer.phy_info); | ||
1525 | } | ||
1526 | mutex_unlock(&ioc->sas_topology_mutex); | ||
1527 | } | ||
1528 | |||
1529 | /* | ||
1530 | * Start of day discovery | ||
1531 | */ | ||
1223 | static void | 1532 | static void |
1224 | mptsas_scan_sas_topology(MPT_ADAPTER *ioc) | 1533 | mptsas_scan_sas_topology(MPT_ADAPTER *ioc) |
1225 | { | 1534 | { |
1226 | u32 handle = 0xFFFF; | 1535 | u32 handle = 0xFFFF; |
1227 | int index = 0; | 1536 | int i; |
1537 | |||
1538 | mutex_lock(&ioc->sas_discovery_mutex); | ||
1539 | mptsas_probe_hba_phys(ioc); | ||
1540 | while (!mptsas_probe_expander_phys(ioc, &handle)) | ||
1541 | ; | ||
1542 | /* | ||
1543 | Reporting RAID volumes. | ||
1544 | */ | ||
1545 | if (!ioc->raid_data.pIocPg2) | ||
1546 | goto out; | ||
1547 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | ||
1548 | goto out; | ||
1549 | for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { | ||
1550 | scsi_add_device(ioc->sh, ioc->num_ports, | ||
1551 | ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); | ||
1552 | } | ||
1553 | out: | ||
1554 | mutex_unlock(&ioc->sas_discovery_mutex); | ||
1555 | } | ||
1556 | |||
1557 | /* | ||
1558 | * Work queue thread to handle Runtime discovery | ||
1559 | * Mere purpose is the hot add/delete of expanders | ||
1560 | */ | ||
1561 | static void | ||
1562 | mptscsih_discovery_work(void * arg) | ||
1563 | { | ||
1564 | struct mptsas_discovery_event *ev = arg; | ||
1565 | MPT_ADAPTER *ioc = ev->ioc; | ||
1566 | u32 handle = 0xFFFF; | ||
1228 | 1567 | ||
1229 | mptsas_probe_hba_phys(ioc, &index); | 1568 | mutex_lock(&ioc->sas_discovery_mutex); |
1230 | while (!mptsas_probe_expander_phys(ioc, &handle, &index)) | 1569 | ioc->sas_discovery_runtime=1; |
1570 | mptsas_delete_expander_phys(ioc); | ||
1571 | mptsas_probe_hba_phys(ioc); | ||
1572 | while (!mptsas_probe_expander_phys(ioc, &handle)) | ||
1231 | ; | 1573 | ; |
1574 | kfree(ev); | ||
1575 | ioc->sas_discovery_runtime=0; | ||
1576 | mutex_unlock(&ioc->sas_discovery_mutex); | ||
1232 | } | 1577 | } |
1233 | 1578 | ||
1234 | static struct mptsas_phyinfo * | 1579 | static struct mptsas_phyinfo * |
@@ -1246,10 +1591,8 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id) | |||
1246 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << | 1591 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << |
1247 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | 1592 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), |
1248 | parent_handle); | 1593 | parent_handle); |
1249 | if (error) { | 1594 | if (error) |
1250 | printk("mptsas: failed to retrieve device page\n"); | ||
1251 | return NULL; | 1595 | return NULL; |
1252 | } | ||
1253 | 1596 | ||
1254 | /* | 1597 | /* |
1255 | * The phy_info structures are never deallocated during lifetime of | 1598 | * The phy_info structures are never deallocated during lifetime of |
@@ -1296,6 +1639,35 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) | |||
1296 | return phy_info; | 1639 | return phy_info; |
1297 | } | 1640 | } |
1298 | 1641 | ||
1642 | /* | ||
1643 | * Work queue thread to clear the persitency table | ||
1644 | */ | ||
1645 | static void | ||
1646 | mptscsih_sas_persist_clear_table(void * arg) | ||
1647 | { | ||
1648 | MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; | ||
1649 | |||
1650 | mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); | ||
1651 | } | ||
1652 | |||
1653 | static void | ||
1654 | mptsas_reprobe_lun(struct scsi_device *sdev, void *data) | ||
1655 | { | ||
1656 | sdev->no_uld_attach = data ? 1 : 0; | ||
1657 | scsi_device_reprobe(sdev); | ||
1658 | } | ||
1659 | |||
1660 | static void | ||
1661 | mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) | ||
1662 | { | ||
1663 | starget_for_each_device(starget, uld_attach ? (void *)1 : NULL, | ||
1664 | mptsas_reprobe_lun); | ||
1665 | } | ||
1666 | |||
1667 | |||
1668 | /* | ||
1669 | * Work queue thread to handle SAS hotplug events | ||
1670 | */ | ||
1299 | static void | 1671 | static void |
1300 | mptsas_hotplug_work(void *arg) | 1672 | mptsas_hotplug_work(void *arg) |
1301 | { | 1673 | { |
@@ -1304,16 +1676,39 @@ mptsas_hotplug_work(void *arg) | |||
1304 | struct mptsas_phyinfo *phy_info; | 1676 | struct mptsas_phyinfo *phy_info; |
1305 | struct sas_rphy *rphy; | 1677 | struct sas_rphy *rphy; |
1306 | struct scsi_device *sdev; | 1678 | struct scsi_device *sdev; |
1679 | struct sas_identify identify; | ||
1307 | char *ds = NULL; | 1680 | char *ds = NULL; |
1308 | struct mptsas_devinfo sas_device; | 1681 | struct mptsas_devinfo sas_device; |
1682 | VirtTarget *vtarget; | ||
1683 | |||
1684 | mutex_lock(&ioc->sas_discovery_mutex); | ||
1309 | 1685 | ||
1310 | switch (ev->event_type) { | 1686 | switch (ev->event_type) { |
1311 | case MPTSAS_DEL_DEVICE: | 1687 | case MPTSAS_DEL_DEVICE: |
1312 | 1688 | ||
1313 | phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); | 1689 | phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); |
1314 | if (!phy_info) { | 1690 | |
1315 | printk("mptsas: remove event for non-existant PHY.\n"); | 1691 | /* |
1692 | * Sanity checks, for non-existing phys and remote rphys. | ||
1693 | */ | ||
1694 | if (!phy_info) | ||
1316 | break; | 1695 | break; |
1696 | if (!phy_info->rphy) | ||
1697 | break; | ||
1698 | if (phy_info->starget) { | ||
1699 | vtarget = phy_info->starget->hostdata; | ||
1700 | |||
1701 | if (!vtarget) | ||
1702 | break; | ||
1703 | /* | ||
1704 | * Handling RAID components | ||
1705 | */ | ||
1706 | if (ev->phys_disk_num_valid) { | ||
1707 | vtarget->target_id = ev->phys_disk_num; | ||
1708 | vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
1709 | mptsas_reprobe_target(vtarget->starget, 1); | ||
1710 | break; | ||
1711 | } | ||
1317 | } | 1712 | } |
1318 | 1713 | ||
1319 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | 1714 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) |
@@ -1327,55 +1722,74 @@ mptsas_hotplug_work(void *arg) | |||
1327 | "removing %s device, channel %d, id %d, phy %d\n", | 1722 | "removing %s device, channel %d, id %d, phy %d\n", |
1328 | ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); | 1723 | ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); |
1329 | 1724 | ||
1330 | if (phy_info->rphy) { | 1725 | sas_rphy_delete(phy_info->rphy); |
1331 | sas_rphy_delete(phy_info->rphy); | 1726 | memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); |
1332 | phy_info->rphy = NULL; | 1727 | phy_info->rphy = NULL; |
1333 | } | 1728 | phy_info->starget = NULL; |
1334 | break; | 1729 | break; |
1335 | case MPTSAS_ADD_DEVICE: | 1730 | case MPTSAS_ADD_DEVICE: |
1336 | 1731 | ||
1337 | /* | 1732 | /* |
1338 | * When there is no sas address, | 1733 | * Refresh sas device pg0 data |
1339 | * RAID volumes are being deleted, | ||
1340 | * and hidden phy disk are being added. | ||
1341 | * We don't know the SAS data yet, | ||
1342 | * so lookup sas device page to get | ||
1343 | * pertaining info | ||
1344 | */ | 1734 | */ |
1345 | if (!ev->sas_address) { | 1735 | if (mptsas_sas_device_pg0(ioc, &sas_device, |
1346 | if (mptsas_sas_device_pg0(ioc, | 1736 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << |
1347 | &sas_device, ev->id, | 1737 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) |
1348 | (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | 1738 | break; |
1349 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT))) | ||
1350 | break; | ||
1351 | ev->handle = sas_device.handle; | ||
1352 | ev->parent_handle = sas_device.handle_parent; | ||
1353 | ev->channel = sas_device.channel; | ||
1354 | ev->phy_id = sas_device.phy_id; | ||
1355 | ev->sas_address = sas_device.sas_address; | ||
1356 | ev->device_info = sas_device.device_info; | ||
1357 | } | ||
1358 | 1739 | ||
1359 | phy_info = mptsas_find_phyinfo_by_parent(ioc, | 1740 | phy_info = mptsas_find_phyinfo_by_parent(ioc, |
1360 | ev->parent_handle, ev->phy_id); | 1741 | sas_device.handle_parent, sas_device.phy_id); |
1742 | |||
1361 | if (!phy_info) { | 1743 | if (!phy_info) { |
1362 | printk("mptsas: add event for non-existant PHY.\n"); | 1744 | u32 handle = 0xFFFF; |
1363 | break; | 1745 | |
1746 | /* | ||
1747 | * Its possible when an expander has been hot added | ||
1748 | * containing attached devices, the sas firmware | ||
1749 | * may send a RC_ADDED event prior to the | ||
1750 | * DISCOVERY STOP event. If that occurs, our | ||
1751 | * view of the topology in the driver in respect to this | ||
1752 | * expander might of not been setup, and we hit this | ||
1753 | * condition. | ||
1754 | * Therefore, this code kicks off discovery to | ||
1755 | * refresh the data. | ||
1756 | * Then again, we check whether the parent phy has | ||
1757 | * been created. | ||
1758 | */ | ||
1759 | ioc->sas_discovery_runtime=1; | ||
1760 | mptsas_delete_expander_phys(ioc); | ||
1761 | mptsas_probe_hba_phys(ioc); | ||
1762 | while (!mptsas_probe_expander_phys(ioc, &handle)) | ||
1763 | ; | ||
1764 | ioc->sas_discovery_runtime=0; | ||
1765 | |||
1766 | phy_info = mptsas_find_phyinfo_by_parent(ioc, | ||
1767 | sas_device.handle_parent, sas_device.phy_id); | ||
1768 | if (!phy_info) | ||
1769 | break; | ||
1364 | } | 1770 | } |
1365 | 1771 | ||
1366 | if (phy_info->rphy) { | 1772 | if (phy_info->starget) { |
1367 | printk("mptsas: trying to add existing device.\n"); | 1773 | vtarget = phy_info->starget->hostdata; |
1774 | |||
1775 | if (!vtarget) | ||
1776 | break; | ||
1777 | /* | ||
1778 | * Handling RAID components | ||
1779 | */ | ||
1780 | if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { | ||
1781 | vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
1782 | vtarget->target_id = ev->id; | ||
1783 | mptsas_reprobe_target(phy_info->starget, 0); | ||
1784 | } | ||
1368 | break; | 1785 | break; |
1369 | } | 1786 | } |
1370 | 1787 | ||
1371 | /* fill attached info */ | 1788 | if (phy_info->rphy) |
1372 | phy_info->attached.handle = ev->handle; | 1789 | break; |
1373 | phy_info->attached.phy_id = ev->phy_id; | 1790 | |
1374 | phy_info->attached.port_id = phy_info->identify.port_id; | 1791 | memcpy(&phy_info->attached, &sas_device, |
1375 | phy_info->attached.id = ev->id; | 1792 | sizeof(struct mptsas_devinfo)); |
1376 | phy_info->attached.channel = ev->channel; | ||
1377 | phy_info->attached.sas_address = ev->sas_address; | ||
1378 | phy_info->attached.device_info = ev->device_info; | ||
1379 | 1793 | ||
1380 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | 1794 | if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) |
1381 | ds = "ssp"; | 1795 | ds = "ssp"; |
@@ -1388,13 +1802,23 @@ mptsas_hotplug_work(void *arg) | |||
1388 | "attaching %s device, channel %d, id %d, phy %d\n", | 1802 | "attaching %s device, channel %d, id %d, phy %d\n", |
1389 | ioc->name, ds, ev->channel, ev->id, ev->phy_id); | 1803 | ioc->name, ds, ev->channel, ev->id, ev->phy_id); |
1390 | 1804 | ||
1391 | 1805 | mptsas_parse_device_info(&identify, &phy_info->attached); | |
1392 | rphy = sas_rphy_alloc(phy_info->phy); | 1806 | switch (identify.device_type) { |
1807 | case SAS_END_DEVICE: | ||
1808 | rphy = sas_end_device_alloc(phy_info->phy); | ||
1809 | break; | ||
1810 | case SAS_EDGE_EXPANDER_DEVICE: | ||
1811 | case SAS_FANOUT_EXPANDER_DEVICE: | ||
1812 | rphy = sas_expander_alloc(phy_info->phy, identify.device_type); | ||
1813 | break; | ||
1814 | default: | ||
1815 | rphy = NULL; | ||
1816 | break; | ||
1817 | } | ||
1393 | if (!rphy) | 1818 | if (!rphy) |
1394 | break; /* non-fatal: an rphy can be added later */ | 1819 | break; /* non-fatal: an rphy can be added later */ |
1395 | 1820 | ||
1396 | rphy->scsi_target_id = phy_info->attached.id; | 1821 | rphy->identify = identify; |
1397 | mptsas_parse_device_info(&rphy->identify, &phy_info->attached); | ||
1398 | if (sas_rphy_add(rphy)) { | 1822 | if (sas_rphy_add(rphy)) { |
1399 | sas_rphy_free(rphy); | 1823 | sas_rphy_free(rphy); |
1400 | break; | 1824 | break; |
@@ -1413,7 +1837,7 @@ mptsas_hotplug_work(void *arg) | |||
1413 | break; | 1837 | break; |
1414 | } | 1838 | } |
1415 | printk(MYIOC_s_INFO_FMT | 1839 | printk(MYIOC_s_INFO_FMT |
1416 | "attaching device, channel %d, id %d\n", | 1840 | "attaching raid volume, channel %d, id %d\n", |
1417 | ioc->name, ioc->num_ports, ev->id); | 1841 | ioc->name, ioc->num_ports, ev->id); |
1418 | scsi_add_device(ioc->sh, | 1842 | scsi_add_device(ioc->sh, |
1419 | ioc->num_ports, | 1843 | ioc->num_ports, |
@@ -1430,7 +1854,7 @@ mptsas_hotplug_work(void *arg) | |||
1430 | if (!sdev) | 1854 | if (!sdev) |
1431 | break; | 1855 | break; |
1432 | printk(MYIOC_s_INFO_FMT | 1856 | printk(MYIOC_s_INFO_FMT |
1433 | "removing device, channel %d, id %d\n", | 1857 | "removing raid volume, channel %d, id %d\n", |
1434 | ioc->name, ioc->num_ports, ev->id); | 1858 | ioc->name, ioc->num_ports, ev->id); |
1435 | scsi_remove_device(sdev); | 1859 | scsi_remove_device(sdev); |
1436 | scsi_device_put(sdev); | 1860 | scsi_device_put(sdev); |
@@ -1439,6 +1863,7 @@ mptsas_hotplug_work(void *arg) | |||
1439 | } | 1863 | } |
1440 | 1864 | ||
1441 | kfree(ev); | 1865 | kfree(ev); |
1866 | mutex_unlock(&ioc->sas_discovery_mutex); | ||
1442 | } | 1867 | } |
1443 | 1868 | ||
1444 | static void | 1869 | static void |
@@ -1455,35 +1880,51 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc, | |||
1455 | MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) | 1880 | MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) |
1456 | return; | 1881 | return; |
1457 | 1882 | ||
1458 | if ((sas_event_data->ReasonCode & | 1883 | switch (sas_event_data->ReasonCode) { |
1459 | (MPI_EVENT_SAS_DEV_STAT_RC_ADDED | | 1884 | case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: |
1460 | MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0) | 1885 | case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: |
1461 | return; | 1886 | ev = kmalloc(sizeof(*ev), GFP_ATOMIC); |
1887 | if (!ev) { | ||
1888 | printk(KERN_WARNING "mptsas: lost hotplug event\n"); | ||
1889 | break; | ||
1890 | } | ||
1462 | 1891 | ||
1463 | ev = kmalloc(sizeof(*ev), GFP_ATOMIC); | 1892 | INIT_WORK(&ev->work, mptsas_hotplug_work, ev); |
1464 | if (!ev) { | 1893 | ev->ioc = ioc; |
1465 | printk(KERN_WARNING "mptsas: lost hotplug event\n"); | 1894 | ev->handle = le16_to_cpu(sas_event_data->DevHandle); |
1466 | return; | 1895 | ev->parent_handle = |
1896 | le16_to_cpu(sas_event_data->ParentDevHandle); | ||
1897 | ev->channel = sas_event_data->Bus; | ||
1898 | ev->id = sas_event_data->TargetID; | ||
1899 | ev->phy_id = sas_event_data->PhyNum; | ||
1900 | memcpy(&sas_address, &sas_event_data->SASAddress, | ||
1901 | sizeof(__le64)); | ||
1902 | ev->sas_address = le64_to_cpu(sas_address); | ||
1903 | ev->device_info = device_info; | ||
1904 | |||
1905 | if (sas_event_data->ReasonCode & | ||
1906 | MPI_EVENT_SAS_DEV_STAT_RC_ADDED) | ||
1907 | ev->event_type = MPTSAS_ADD_DEVICE; | ||
1908 | else | ||
1909 | ev->event_type = MPTSAS_DEL_DEVICE; | ||
1910 | schedule_work(&ev->work); | ||
1911 | break; | ||
1912 | case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: | ||
1913 | /* | ||
1914 | * Persistent table is full. | ||
1915 | */ | ||
1916 | INIT_WORK(&ioc->mptscsih_persistTask, | ||
1917 | mptscsih_sas_persist_clear_table, | ||
1918 | (void *)ioc); | ||
1919 | schedule_work(&ioc->mptscsih_persistTask); | ||
1920 | break; | ||
1921 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: | ||
1922 | /* TODO */ | ||
1923 | case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: | ||
1924 | /* TODO */ | ||
1925 | default: | ||
1926 | break; | ||
1467 | } | 1927 | } |
1468 | |||
1469 | |||
1470 | INIT_WORK(&ev->work, mptsas_hotplug_work, ev); | ||
1471 | ev->ioc = ioc; | ||
1472 | ev->handle = le16_to_cpu(sas_event_data->DevHandle); | ||
1473 | ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle); | ||
1474 | ev->channel = sas_event_data->Bus; | ||
1475 | ev->id = sas_event_data->TargetID; | ||
1476 | ev->phy_id = sas_event_data->PhyNum; | ||
1477 | memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64)); | ||
1478 | ev->sas_address = le64_to_cpu(sas_address); | ||
1479 | ev->device_info = device_info; | ||
1480 | |||
1481 | if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED) | ||
1482 | ev->event_type = MPTSAS_ADD_DEVICE; | ||
1483 | else | ||
1484 | ev->event_type = MPTSAS_DEL_DEVICE; | ||
1485 | |||
1486 | schedule_work(&ev->work); | ||
1487 | } | 1928 | } |
1488 | 1929 | ||
1489 | static void | 1930 | static void |
@@ -1512,6 +1953,9 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc, | |||
1512 | ev->event_type = MPTSAS_ADD_DEVICE; | 1953 | ev->event_type = MPTSAS_ADD_DEVICE; |
1513 | break; | 1954 | break; |
1514 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: | 1955 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: |
1956 | ioc->raid_data.isRaid = 1; | ||
1957 | ev->phys_disk_num_valid = 1; | ||
1958 | ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||
1515 | ev->event_type = MPTSAS_DEL_DEVICE; | 1959 | ev->event_type = MPTSAS_DEL_DEVICE; |
1516 | break; | 1960 | break; |
1517 | case MPI_EVENT_RAID_RC_VOLUME_DELETED: | 1961 | case MPI_EVENT_RAID_RC_VOLUME_DELETED: |
@@ -1533,15 +1977,31 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc, | |||
1533 | schedule_work(&ev->work); | 1977 | schedule_work(&ev->work); |
1534 | } | 1978 | } |
1535 | 1979 | ||
1536 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1537 | /* work queue thread to clear the persitency table */ | ||
1538 | static void | 1980 | static void |
1539 | mptscsih_sas_persist_clear_table(void * arg) | 1981 | mptscsih_send_discovery(MPT_ADAPTER *ioc, |
1982 | EVENT_DATA_SAS_DISCOVERY *discovery_data) | ||
1540 | { | 1983 | { |
1541 | MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; | 1984 | struct mptsas_discovery_event *ev; |
1985 | |||
1986 | /* | ||
1987 | * DiscoveryStatus | ||
1988 | * | ||
1989 | * This flag will be non-zero when firmware | ||
1990 | * kicks off discovery, and return to zero | ||
1991 | * once its completed. | ||
1992 | */ | ||
1993 | if (discovery_data->DiscoveryStatus) | ||
1994 | return; | ||
1995 | |||
1996 | ev = kmalloc(sizeof(*ev), GFP_ATOMIC); | ||
1997 | if (!ev) | ||
1998 | return; | ||
1999 | memset(ev,0,sizeof(struct mptsas_discovery_event)); | ||
2000 | INIT_WORK(&ev->work, mptscsih_discovery_work, ev); | ||
2001 | ev->ioc = ioc; | ||
2002 | schedule_work(&ev->work); | ||
2003 | }; | ||
1542 | 2004 | ||
1543 | mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); | ||
1544 | } | ||
1545 | 2005 | ||
1546 | static int | 2006 | static int |
1547 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | 2007 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) |
@@ -1552,6 +2012,17 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | |||
1552 | if (!ioc->sh) | 2012 | if (!ioc->sh) |
1553 | goto out; | 2013 | goto out; |
1554 | 2014 | ||
2015 | /* | ||
2016 | * sas_discovery_ignore_events | ||
2017 | * | ||
2018 | * This flag is to prevent anymore processing of | ||
2019 | * sas events once mptsas_remove function is called. | ||
2020 | */ | ||
2021 | if (ioc->sas_discovery_ignore_events) { | ||
2022 | rc = mptscsih_event_process(ioc, reply); | ||
2023 | goto out; | ||
2024 | } | ||
2025 | |||
1555 | switch (event) { | 2026 | switch (event) { |
1556 | case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: | 2027 | case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: |
1557 | mptscsih_send_sas_event(ioc, | 2028 | mptscsih_send_sas_event(ioc, |
@@ -1567,6 +2038,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | |||
1567 | (void *)ioc); | 2038 | (void *)ioc); |
1568 | schedule_work(&ioc->mptscsih_persistTask); | 2039 | schedule_work(&ioc->mptscsih_persistTask); |
1569 | break; | 2040 | break; |
2041 | case MPI_EVENT_SAS_DISCOVERY: | ||
2042 | mptscsih_send_discovery(ioc, | ||
2043 | (EVENT_DATA_SAS_DISCOVERY *)reply->Data); | ||
2044 | break; | ||
1570 | default: | 2045 | default: |
1571 | rc = mptscsih_event_process(ioc, reply); | 2046 | rc = mptscsih_event_process(ioc, reply); |
1572 | break; | 2047 | break; |
@@ -1668,7 +2143,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1668 | 2143 | ||
1669 | INIT_LIST_HEAD(&ioc->sas_topology); | 2144 | INIT_LIST_HEAD(&ioc->sas_topology); |
1670 | mutex_init(&ioc->sas_topology_mutex); | 2145 | mutex_init(&ioc->sas_topology_mutex); |
1671 | 2146 | mutex_init(&ioc->sas_discovery_mutex); | |
1672 | mutex_init(&ioc->sas_mgmt.mutex); | 2147 | mutex_init(&ioc->sas_mgmt.mutex); |
1673 | init_completion(&ioc->sas_mgmt.done); | 2148 | init_completion(&ioc->sas_mgmt.done); |
1674 | 2149 | ||
@@ -1781,20 +2256,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1781 | 2256 | ||
1782 | mptsas_scan_sas_topology(ioc); | 2257 | mptsas_scan_sas_topology(ioc); |
1783 | 2258 | ||
1784 | /* | ||
1785 | Reporting RAID volumes. | ||
1786 | */ | ||
1787 | if (!ioc->raid_data.pIocPg2) | ||
1788 | return 0; | ||
1789 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | ||
1790 | return 0; | ||
1791 | for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) { | ||
1792 | scsi_add_device(sh, | ||
1793 | ioc->num_ports, | ||
1794 | ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID, | ||
1795 | 0); | ||
1796 | } | ||
1797 | |||
1798 | return 0; | 2259 | return 0; |
1799 | 2260 | ||
1800 | out_mptsas_probe: | 2261 | out_mptsas_probe: |
@@ -1808,11 +2269,14 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) | |||
1808 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 2269 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); |
1809 | struct mptsas_portinfo *p, *n; | 2270 | struct mptsas_portinfo *p, *n; |
1810 | 2271 | ||
2272 | ioc->sas_discovery_ignore_events=1; | ||
1811 | sas_remove_host(ioc->sh); | 2273 | sas_remove_host(ioc->sh); |
1812 | 2274 | ||
1813 | mutex_lock(&ioc->sas_topology_mutex); | 2275 | mutex_lock(&ioc->sas_topology_mutex); |
1814 | list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { | 2276 | list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { |
1815 | list_del(&p->list); | 2277 | list_del(&p->list); |
2278 | if (p->phy_info) | ||
2279 | kfree(p->phy_info); | ||
1816 | kfree(p); | 2280 | kfree(p); |
1817 | } | 2281 | } |
1818 | mutex_unlock(&ioc->sas_topology_mutex); | 2282 | mutex_unlock(&ioc->sas_topology_mutex); |
@@ -1867,7 +2331,7 @@ mptsas_init(void) | |||
1867 | mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); | 2331 | mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); |
1868 | 2332 | ||
1869 | if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) { | 2333 | if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) { |
1870 | devtprintk((KERN_INFO MYNAM | 2334 | devtverboseprintk((KERN_INFO MYNAM |
1871 | ": Registered for IOC event notifications\n")); | 2335 | ": Registered for IOC event notifications\n")); |
1872 | } | 2336 | } |
1873 | 2337 | ||
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 4fee6befc93d..3729062db317 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -114,21 +114,6 @@ typedef struct _internal_cmd { | |||
114 | u8 rsvd; | 114 | u8 rsvd; |
115 | } INTERNAL_CMD; | 115 | } INTERNAL_CMD; |
116 | 116 | ||
117 | typedef struct _negoparms { | ||
118 | u8 width; | ||
119 | u8 offset; | ||
120 | u8 factor; | ||
121 | u8 flags; | ||
122 | } NEGOPARMS; | ||
123 | |||
124 | typedef struct _dv_parameters { | ||
125 | NEGOPARMS max; | ||
126 | NEGOPARMS now; | ||
127 | u8 cmd; | ||
128 | u8 id; | ||
129 | u16 pad1; | ||
130 | } DVPARAMETERS; | ||
131 | |||
132 | /* | 117 | /* |
133 | * Other private/forward protos... | 118 | * Other private/forward protos... |
134 | */ | 119 | */ |
@@ -149,28 +134,12 @@ static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 tar | |||
149 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | 134 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); |
150 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); | 135 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); |
151 | 136 | ||
152 | static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen); | 137 | static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); |
153 | static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, char byte56); | 138 | static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); |
154 | static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags); | ||
155 | static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc); | ||
156 | static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags); | ||
157 | static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); | 139 | static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); |
158 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); | 140 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); |
159 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); | 141 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); |
160 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); | 142 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); |
161 | static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice); | ||
162 | static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); | ||
163 | |||
164 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
165 | static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); | ||
166 | static void mptscsih_domainValidation(void *hd); | ||
167 | static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); | ||
168 | static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); | ||
169 | static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); | ||
170 | static void mptscsih_fillbuf(char *buffer, int size, int index, int width); | ||
171 | static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id); | ||
172 | static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc); | ||
173 | #endif | ||
174 | 143 | ||
175 | void mptscsih_remove(struct pci_dev *); | 144 | void mptscsih_remove(struct pci_dev *); |
176 | void mptscsih_shutdown(struct pci_dev *); | 145 | void mptscsih_shutdown(struct pci_dev *); |
@@ -181,16 +150,6 @@ int mptscsih_resume(struct pci_dev *pdev); | |||
181 | 150 | ||
182 | #define SNS_LEN(scp) sizeof((scp)->sense_buffer) | 151 | #define SNS_LEN(scp) sizeof((scp)->sense_buffer) |
183 | 152 | ||
184 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
185 | /* | ||
186 | * Domain Validation task structure | ||
187 | */ | ||
188 | static DEFINE_SPINLOCK(dvtaskQ_lock); | ||
189 | static int dvtaskQ_active = 0; | ||
190 | static int dvtaskQ_release = 0; | ||
191 | static struct work_struct dvTaskQ_task; | ||
192 | #endif | ||
193 | |||
194 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 153 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
195 | /** | 154 | /** |
196 | * mptscsih_add_sge - Place a simple SGE at address pAddr. | 155 | * mptscsih_add_sge - Place a simple SGE at address pAddr. |
@@ -687,9 +646,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
687 | */ | 646 | */ |
688 | sc->result = DID_RESET << 16; | 647 | sc->result = DID_RESET << 16; |
689 | 648 | ||
690 | /* GEM Workaround. */ | ||
691 | if (ioc->bus_type == SPI) | ||
692 | mptscsih_no_negotiate(hd, sc); | ||
693 | break; | 649 | break; |
694 | 650 | ||
695 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ | 651 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ |
@@ -931,7 +887,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | |||
931 | dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", | 887 | dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", |
932 | hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); | 888 | hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); |
933 | 889 | ||
934 | if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) | 890 | if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) |
935 | continue; | 891 | continue; |
936 | 892 | ||
937 | /* Cleanup | 893 | /* Cleanup |
@@ -1005,10 +961,6 @@ mptscsih_remove(struct pci_dev *pdev) | |||
1005 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 961 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); |
1006 | struct Scsi_Host *host = ioc->sh; | 962 | struct Scsi_Host *host = ioc->sh; |
1007 | MPT_SCSI_HOST *hd; | 963 | MPT_SCSI_HOST *hd; |
1008 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
1009 | int count; | ||
1010 | unsigned long flags; | ||
1011 | #endif | ||
1012 | int sz1; | 964 | int sz1; |
1013 | 965 | ||
1014 | if(!host) { | 966 | if(!host) { |
@@ -1021,25 +973,6 @@ mptscsih_remove(struct pci_dev *pdev) | |||
1021 | if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL) | 973 | if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL) |
1022 | return; | 974 | return; |
1023 | 975 | ||
1024 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
1025 | /* Check DV thread active */ | ||
1026 | count = 10 * HZ; | ||
1027 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
1028 | if (dvtaskQ_active) { | ||
1029 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
1030 | while(dvtaskQ_active && --count) | ||
1031 | schedule_timeout_interruptible(1); | ||
1032 | } else { | ||
1033 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
1034 | } | ||
1035 | if (!count) | ||
1036 | printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n"); | ||
1037 | #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) | ||
1038 | else | ||
1039 | printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count); | ||
1040 | #endif | ||
1041 | #endif | ||
1042 | |||
1043 | mptscsih_shutdown(pdev); | 976 | mptscsih_shutdown(pdev); |
1044 | 977 | ||
1045 | sz1=0; | 978 | sz1=0; |
@@ -1127,21 +1060,6 @@ mptscsih_resume(struct pci_dev *pdev) | |||
1127 | if(!hd) | 1060 | if(!hd) |
1128 | return 0; | 1061 | return 0; |
1129 | 1062 | ||
1130 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
1131 | { | ||
1132 | unsigned long lflags; | ||
1133 | spin_lock_irqsave(&dvtaskQ_lock, lflags); | ||
1134 | if (!dvtaskQ_active) { | ||
1135 | dvtaskQ_active = 1; | ||
1136 | spin_unlock_irqrestore(&dvtaskQ_lock, lflags); | ||
1137 | INIT_WORK(&dvTaskQ_task, | ||
1138 | mptscsih_domainValidation, (void *) hd); | ||
1139 | schedule_work(&dvTaskQ_task); | ||
1140 | } else { | ||
1141 | spin_unlock_irqrestore(&dvtaskQ_lock, lflags); | ||
1142 | } | ||
1143 | } | ||
1144 | #endif | ||
1145 | return 0; | 1063 | return 0; |
1146 | } | 1064 | } |
1147 | 1065 | ||
@@ -1317,6 +1235,14 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1317 | return SCSI_MLQUEUE_HOST_BUSY; | 1235 | return SCSI_MLQUEUE_HOST_BUSY; |
1318 | } | 1236 | } |
1319 | 1237 | ||
1238 | if ((hd->ioc->bus_type == SPI) && | ||
1239 | vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && | ||
1240 | mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { | ||
1241 | SCpnt->result = DID_NO_CONNECT << 16; | ||
1242 | done(SCpnt); | ||
1243 | return 0; | ||
1244 | } | ||
1245 | |||
1320 | /* | 1246 | /* |
1321 | * Put together a MPT SCSI request... | 1247 | * Put together a MPT SCSI request... |
1322 | */ | 1248 | */ |
@@ -1360,10 +1286,13 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1360 | 1286 | ||
1361 | /* Use the above information to set up the message frame | 1287 | /* Use the above information to set up the message frame |
1362 | */ | 1288 | */ |
1363 | pScsiReq->TargetID = (u8) vdev->target_id; | 1289 | pScsiReq->TargetID = (u8) vdev->vtarget->target_id; |
1364 | pScsiReq->Bus = vdev->bus_id; | 1290 | pScsiReq->Bus = vdev->vtarget->bus_id; |
1365 | pScsiReq->ChainOffset = 0; | 1291 | pScsiReq->ChainOffset = 0; |
1366 | pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; | 1292 | if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) |
1293 | pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; | ||
1294 | else | ||
1295 | pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; | ||
1367 | pScsiReq->CDBLength = SCpnt->cmd_len; | 1296 | pScsiReq->CDBLength = SCpnt->cmd_len; |
1368 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; | 1297 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; |
1369 | pScsiReq->Reserved = 0; | 1298 | pScsiReq->Reserved = 0; |
@@ -1411,49 +1340,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1411 | hd->ScsiLookup[my_idx] = SCpnt; | 1340 | hd->ScsiLookup[my_idx] = SCpnt; |
1412 | SCpnt->host_scribble = NULL; | 1341 | SCpnt->host_scribble = NULL; |
1413 | 1342 | ||
1414 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
1415 | if (hd->ioc->bus_type == SPI) { | ||
1416 | int dvStatus = hd->ioc->spi_data.dvStatus[vdev->target_id]; | ||
1417 | int issueCmd = 1; | ||
1418 | |||
1419 | if (dvStatus || hd->ioc->spi_data.forceDv) { | ||
1420 | |||
1421 | if ((dvStatus & MPT_SCSICFG_NEED_DV) || | ||
1422 | (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { | ||
1423 | unsigned long lflags; | ||
1424 | /* Schedule DV if necessary */ | ||
1425 | spin_lock_irqsave(&dvtaskQ_lock, lflags); | ||
1426 | if (!dvtaskQ_active) { | ||
1427 | dvtaskQ_active = 1; | ||
1428 | spin_unlock_irqrestore(&dvtaskQ_lock, lflags); | ||
1429 | INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd); | ||
1430 | |||
1431 | schedule_work(&dvTaskQ_task); | ||
1432 | } else { | ||
1433 | spin_unlock_irqrestore(&dvtaskQ_lock, lflags); | ||
1434 | } | ||
1435 | hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV; | ||
1436 | } | ||
1437 | |||
1438 | /* Trying to do DV to this target, extend timeout. | ||
1439 | * Wait to issue until flag is clear | ||
1440 | */ | ||
1441 | if (dvStatus & MPT_SCSICFG_DV_PENDING) { | ||
1442 | mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); | ||
1443 | issueCmd = 0; | ||
1444 | } | ||
1445 | |||
1446 | /* Set the DV flags. | ||
1447 | */ | ||
1448 | if (dvStatus & MPT_SCSICFG_DV_NOT_DONE) | ||
1449 | mptscsih_set_dvflags(hd, SCpnt); | ||
1450 | |||
1451 | if (!issueCmd) | ||
1452 | goto fail; | ||
1453 | } | ||
1454 | } | ||
1455 | #endif | ||
1456 | |||
1457 | mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); | 1343 | mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); |
1458 | dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", | 1344 | dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", |
1459 | hd->ioc->name, SCpnt, mf, my_idx)); | 1345 | hd->ioc->name, SCpnt, mf, my_idx)); |
@@ -1816,7 +1702,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1816 | 1702 | ||
1817 | vdev = SCpnt->device->hostdata; | 1703 | vdev = SCpnt->device->hostdata; |
1818 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, | 1704 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, |
1819 | vdev->bus_id, vdev->target_id, vdev->lun, | 1705 | vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, |
1820 | ctx2abort, mptscsih_get_tm_timeout(ioc)); | 1706 | ctx2abort, mptscsih_get_tm_timeout(ioc)); |
1821 | 1707 | ||
1822 | printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", | 1708 | printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", |
@@ -1867,7 +1753,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
1867 | 1753 | ||
1868 | vdev = SCpnt->device->hostdata; | 1754 | vdev = SCpnt->device->hostdata; |
1869 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, | 1755 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, |
1870 | vdev->bus_id, vdev->target_id, | 1756 | vdev->vtarget->bus_id, vdev->vtarget->target_id, |
1871 | 0, 0, mptscsih_get_tm_timeout(hd->ioc)); | 1757 | 0, 0, mptscsih_get_tm_timeout(hd->ioc)); |
1872 | 1758 | ||
1873 | printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", | 1759 | printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", |
@@ -1918,7 +1804,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) | |||
1918 | 1804 | ||
1919 | vdev = SCpnt->device->hostdata; | 1805 | vdev = SCpnt->device->hostdata; |
1920 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | 1806 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, |
1921 | vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); | 1807 | vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); |
1922 | 1808 | ||
1923 | printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", | 1809 | printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", |
1924 | hd->ioc->name, | 1810 | hd->ioc->name, |
@@ -2218,6 +2104,42 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, | |||
2218 | return 0; | 2104 | return 0; |
2219 | } | 2105 | } |
2220 | 2106 | ||
2107 | /* Search IOC page 3 to determine if this is hidden physical disk | ||
2108 | * | ||
2109 | */ | ||
2110 | int | ||
2111 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) | ||
2112 | { | ||
2113 | int i; | ||
2114 | |||
2115 | if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) | ||
2116 | return 0; | ||
2117 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
2118 | if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) | ||
2119 | return 1; | ||
2120 | } | ||
2121 | return 0; | ||
2122 | } | ||
2123 | EXPORT_SYMBOL(mptscsih_is_phys_disk); | ||
2124 | |||
2125 | int | ||
2126 | mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) | ||
2127 | { | ||
2128 | int i; | ||
2129 | |||
2130 | if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3) | ||
2131 | return -ENXIO; | ||
2132 | |||
2133 | for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
2134 | if (physdiskid == | ||
2135 | hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) | ||
2136 | return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; | ||
2137 | } | ||
2138 | |||
2139 | return -ENXIO; | ||
2140 | } | ||
2141 | EXPORT_SYMBOL(mptscsih_raid_id_to_num); | ||
2142 | |||
2221 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2143 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
2222 | /* | 2144 | /* |
2223 | * OS entry point to allow host driver to alloc memory | 2145 | * OS entry point to allow host driver to alloc memory |
@@ -2233,6 +2155,7 @@ mptscsih_target_alloc(struct scsi_target *starget) | |||
2233 | if (!vtarget) | 2155 | if (!vtarget) |
2234 | return -ENOMEM; | 2156 | return -ENOMEM; |
2235 | starget->hostdata = vtarget; | 2157 | starget->hostdata = vtarget; |
2158 | vtarget->starget = starget; | ||
2236 | return 0; | 2159 | return 0; |
2237 | } | 2160 | } |
2238 | 2161 | ||
@@ -2258,14 +2181,12 @@ mptscsih_slave_alloc(struct scsi_device *sdev) | |||
2258 | return -ENOMEM; | 2181 | return -ENOMEM; |
2259 | } | 2182 | } |
2260 | 2183 | ||
2261 | vdev->ioc_id = hd->ioc->id; | ||
2262 | vdev->target_id = sdev->id; | ||
2263 | vdev->bus_id = sdev->channel; | ||
2264 | vdev->lun = sdev->lun; | 2184 | vdev->lun = sdev->lun; |
2265 | sdev->hostdata = vdev; | 2185 | sdev->hostdata = vdev; |
2266 | 2186 | ||
2267 | starget = scsi_target(sdev); | 2187 | starget = scsi_target(sdev); |
2268 | vtarget = starget->hostdata; | 2188 | vtarget = starget->hostdata; |
2189 | |||
2269 | vdev->vtarget = vtarget; | 2190 | vdev->vtarget = vtarget; |
2270 | 2191 | ||
2271 | if (vtarget->num_luns == 0) { | 2192 | if (vtarget->num_luns == 0) { |
@@ -2274,14 +2195,11 @@ mptscsih_slave_alloc(struct scsi_device *sdev) | |||
2274 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; | 2195 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; |
2275 | vtarget->target_id = sdev->id; | 2196 | vtarget->target_id = sdev->id; |
2276 | vtarget->bus_id = sdev->channel; | 2197 | vtarget->bus_id = sdev->channel; |
2277 | if (hd->ioc->bus_type == SPI) { | 2198 | if (hd->ioc->bus_type == SPI && sdev->channel == 0 && |
2278 | if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) { | 2199 | hd->ioc->raid_data.isRaid & (1 << sdev->id)) { |
2279 | vtarget->raidVolume = 1; | 2200 | vtarget->raidVolume = 1; |
2280 | ddvtprintk((KERN_INFO | 2201 | ddvtprintk((KERN_INFO |
2281 | "RAID Volume @ id %d\n", sdev->id)); | 2202 | "RAID Volume @ id %d\n", sdev->id)); |
2282 | } | ||
2283 | } else { | ||
2284 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; | ||
2285 | } | 2203 | } |
2286 | } | 2204 | } |
2287 | vtarget->num_luns++; | 2205 | vtarget->num_luns++; |
@@ -2321,19 +2239,6 @@ mptscsih_slave_destroy(struct scsi_device *sdev) | |||
2321 | vtarget->luns[0] &= ~(1 << vdevice->lun); | 2239 | vtarget->luns[0] &= ~(1 << vdevice->lun); |
2322 | vtarget->num_luns--; | 2240 | vtarget->num_luns--; |
2323 | if (vtarget->num_luns == 0) { | 2241 | if (vtarget->num_luns == 0) { |
2324 | mptscsih_negotiate_to_asyn_narrow(hd, vdevice); | ||
2325 | if (hd->ioc->bus_type == SPI) { | ||
2326 | if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) { | ||
2327 | hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; | ||
2328 | } else { | ||
2329 | hd->ioc->spi_data.dvStatus[vtarget->target_id] = | ||
2330 | MPT_SCSICFG_NEGOTIATE; | ||
2331 | if (!hd->negoNvram) { | ||
2332 | hd->ioc->spi_data.dvStatus[vtarget->target_id] |= | ||
2333 | MPT_SCSICFG_DV_NOT_DONE; | ||
2334 | } | ||
2335 | } | ||
2336 | } | ||
2337 | hd->Targets[sdev->id] = NULL; | 2242 | hd->Targets[sdev->id] = NULL; |
2338 | } | 2243 | } |
2339 | mptscsih_synchronize_cache(hd, vdevice); | 2244 | mptscsih_synchronize_cache(hd, vdevice); |
@@ -2362,18 +2267,13 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
2362 | vtarget = starget->hostdata; | 2267 | vtarget = starget->hostdata; |
2363 | 2268 | ||
2364 | if (hd->ioc->bus_type == SPI) { | 2269 | if (hd->ioc->bus_type == SPI) { |
2365 | if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { | 2270 | if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) |
2366 | if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) | ||
2367 | max_depth = 1; | ||
2368 | else if (((vtarget->inq_data[0] & 0x1f) == 0x00) && | ||
2369 | (vtarget->minSyncFactor <= MPT_ULTRA160 )) | ||
2370 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; | ||
2371 | else | ||
2372 | max_depth = MPT_SCSI_CMD_PER_DEV_LOW; | ||
2373 | } else { | ||
2374 | /* error case - No Inq. Data */ | ||
2375 | max_depth = 1; | 2271 | max_depth = 1; |
2376 | } | 2272 | else if (sdev->type == TYPE_DISK && |
2273 | vtarget->minSyncFactor <= MPT_ULTRA160) | ||
2274 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; | ||
2275 | else | ||
2276 | max_depth = MPT_SCSI_CMD_PER_DEV_LOW; | ||
2377 | } else | 2277 | } else |
2378 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; | 2278 | max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; |
2379 | 2279 | ||
@@ -2427,8 +2327,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) | |||
2427 | lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ | 2327 | lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ |
2428 | indexed_lun = (vdevice->lun % 32); | 2328 | indexed_lun = (vdevice->lun % 32); |
2429 | vtarget->luns[lun_index] |= (1 << indexed_lun); | 2329 | vtarget->luns[lun_index] |= (1 << indexed_lun); |
2430 | mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry, | 2330 | mptscsih_initTarget(hd, vtarget, sdev); |
2431 | sdev->inquiry_len ); | ||
2432 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); | 2331 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); |
2433 | 2332 | ||
2434 | dsprintk((MYIOC_s_INFO_FMT | 2333 | dsprintk((MYIOC_s_INFO_FMT |
@@ -2597,10 +2496,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
2597 | 2496 | ||
2598 | /* 4. Renegotiate to all devices, if SPI | 2497 | /* 4. Renegotiate to all devices, if SPI |
2599 | */ | 2498 | */ |
2600 | if (ioc->bus_type == SPI) { | ||
2601 | dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n")); | ||
2602 | mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM); | ||
2603 | } | ||
2604 | 2499 | ||
2605 | /* 5. Enable new commands to be posted | 2500 | /* 5. Enable new commands to be posted |
2606 | */ | 2501 | */ |
@@ -2624,13 +2519,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
2624 | hd->cmdPtr = NULL; | 2519 | hd->cmdPtr = NULL; |
2625 | } | 2520 | } |
2626 | 2521 | ||
2627 | /* 7. SPI: Set flag to force DV and re-read IOC Page 3 | ||
2628 | */ | ||
2629 | if (ioc->bus_type == SPI) { | ||
2630 | ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; | ||
2631 | ddvtprintk(("Set reload IOC Pg3 Flag\n")); | ||
2632 | } | ||
2633 | |||
2634 | /* 7. FC: Rescan for blocked rports which might have returned. | 2522 | /* 7. FC: Rescan for blocked rports which might have returned. |
2635 | */ | 2523 | */ |
2636 | else if (ioc->bus_type == FC) { | 2524 | else if (ioc->bus_type == FC) { |
@@ -2659,7 +2547,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2659 | int work_count; | 2547 | int work_count; |
2660 | unsigned long flags; | 2548 | unsigned long flags; |
2661 | 2549 | ||
2662 | devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", | 2550 | devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", |
2663 | ioc->name, event)); | 2551 | ioc->name, event)); |
2664 | 2552 | ||
2665 | if (ioc->sh == NULL || | 2553 | if (ioc->sh == NULL || |
@@ -2699,18 +2587,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2699 | break; | 2587 | break; |
2700 | 2588 | ||
2701 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ | 2589 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ |
2702 | { | ||
2703 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
2704 | pMpiEventDataRaid_t pRaidEventData = | ||
2705 | (pMpiEventDataRaid_t) pEvReply->Data; | ||
2706 | /* Domain Validation Needed */ | ||
2707 | if (ioc->bus_type == SPI && | ||
2708 | pRaidEventData->ReasonCode == | ||
2709 | MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) | ||
2710 | mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum); | ||
2711 | #endif | ||
2712 | break; | 2590 | break; |
2713 | } | ||
2714 | 2591 | ||
2715 | case MPI_EVENT_NONE: /* 00 */ | 2592 | case MPI_EVENT_NONE: /* 00 */ |
2716 | case MPI_EVENT_LOG_DATA: /* 01 */ | 2593 | case MPI_EVENT_LOG_DATA: /* 01 */ |
@@ -2729,9 +2606,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2729 | * mptscsih_initTarget - Target, LUN alloc/free functionality. | 2606 | * mptscsih_initTarget - Target, LUN alloc/free functionality. |
2730 | * @hd: Pointer to MPT_SCSI_HOST structure | 2607 | * @hd: Pointer to MPT_SCSI_HOST structure |
2731 | * @vtarget: per target private data | 2608 | * @vtarget: per target private data |
2732 | * @lun: SCSI LUN id | 2609 | * @sdev: SCSI device |
2733 | * @data: Pointer to data | ||
2734 | * @dlen: Number of INQUIRY bytes | ||
2735 | * | 2610 | * |
2736 | * NOTE: It's only SAFE to call this routine if data points to | 2611 | * NOTE: It's only SAFE to call this routine if data points to |
2737 | * sane & valid STANDARD INQUIRY data! | 2612 | * sane & valid STANDARD INQUIRY data! |
@@ -2741,98 +2616,46 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2741 | * | 2616 | * |
2742 | */ | 2617 | */ |
2743 | static void | 2618 | static void |
2744 | mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen) | 2619 | mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, |
2620 | struct scsi_device *sdev) | ||
2745 | { | 2621 | { |
2746 | SpiCfgData *pSpi; | ||
2747 | char data_56; | ||
2748 | int inq_len; | ||
2749 | |||
2750 | dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", | 2622 | dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", |
2751 | hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd)); | 2623 | hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd)); |
2752 | 2624 | ||
2753 | /* | ||
2754 | * If the peripheral qualifier filter is enabled then if the target reports a 0x1 | ||
2755 | * (i.e. The targer is capable of supporting the specified peripheral device type | ||
2756 | * on this logical unit; however, the physical device is not currently connected | ||
2757 | * to this logical unit) it will be converted to a 0x3 (i.e. The target is not | ||
2758 | * capable of supporting a physical device on this logical unit). This is to work | ||
2759 | * around a bug in th emid-layer in some distributions in which the mid-layer will | ||
2760 | * continue to try to communicate to the LUN and evntually create a dummy LUN. | ||
2761 | */ | ||
2762 | if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0)) | ||
2763 | data[0] |= 0x40; | ||
2764 | |||
2765 | /* Is LUN supported? If so, upper 2 bits will be 0 | 2625 | /* Is LUN supported? If so, upper 2 bits will be 0 |
2766 | * in first byte of inquiry data. | 2626 | * in first byte of inquiry data. |
2767 | */ | 2627 | */ |
2768 | if (data[0] & 0xe0) | 2628 | if (sdev->inq_periph_qual != 0) |
2769 | return; | 2629 | return; |
2770 | 2630 | ||
2771 | if (vtarget == NULL) | 2631 | if (vtarget == NULL) |
2772 | return; | 2632 | return; |
2773 | 2633 | ||
2774 | if (data) | 2634 | vtarget->type = sdev->type; |
2775 | vtarget->type = data[0]; | ||
2776 | 2635 | ||
2777 | if (hd->ioc->bus_type != SPI) | 2636 | if (hd->ioc->bus_type != SPI) |
2778 | return; | 2637 | return; |
2779 | 2638 | ||
2780 | if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { | 2639 | if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { |
2781 | /* Treat all Processors as SAF-TE if | 2640 | /* Treat all Processors as SAF-TE if |
2782 | * command line option is set */ | 2641 | * command line option is set */ |
2783 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; | 2642 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; |
2784 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); | 2643 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); |
2785 | }else if ((data[0] == TYPE_PROCESSOR) && | 2644 | }else if ((sdev->type == TYPE_PROCESSOR) && |
2786 | !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { | 2645 | !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { |
2787 | if ( dlen > 49 ) { | 2646 | if (sdev->inquiry_len > 49 ) { |
2788 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; | 2647 | if (sdev->inquiry[44] == 'S' && |
2789 | if ( data[44] == 'S' && | 2648 | sdev->inquiry[45] == 'A' && |
2790 | data[45] == 'A' && | 2649 | sdev->inquiry[46] == 'F' && |
2791 | data[46] == 'F' && | 2650 | sdev->inquiry[47] == '-' && |
2792 | data[47] == '-' && | 2651 | sdev->inquiry[48] == 'T' && |
2793 | data[48] == 'T' && | 2652 | sdev->inquiry[49] == 'E' ) { |
2794 | data[49] == 'E' ) { | ||
2795 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; | 2653 | vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; |
2796 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); | 2654 | mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); |
2797 | } | 2655 | } |
2798 | } | 2656 | } |
2799 | } | 2657 | } |
2800 | if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { | 2658 | mptscsih_setTargetNegoParms(hd, vtarget, sdev); |
2801 | inq_len = dlen < 8 ? dlen : 8; | ||
2802 | memcpy (vtarget->inq_data, data, inq_len); | ||
2803 | /* If have not done DV, set the DV flag. | ||
2804 | */ | ||
2805 | pSpi = &hd->ioc->spi_data; | ||
2806 | if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) { | ||
2807 | if (pSpi->dvStatus[vtarget->target_id] & MPT_SCSICFG_DV_NOT_DONE) | ||
2808 | pSpi->dvStatus[vtarget->target_id] |= MPT_SCSICFG_NEED_DV; | ||
2809 | } | ||
2810 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; | ||
2811 | |||
2812 | data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */ | ||
2813 | if (dlen > 56) { | ||
2814 | if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) { | ||
2815 | /* Update the target capabilities | ||
2816 | */ | ||
2817 | data_56 = data[56]; | ||
2818 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56; | ||
2819 | } | ||
2820 | } | ||
2821 | mptscsih_setTargetNegoParms(hd, vtarget, data_56); | ||
2822 | } else { | ||
2823 | /* Initial Inquiry may not request enough data bytes to | ||
2824 | * obtain byte 57. DV will; if target doesn't return | ||
2825 | * at least 57 bytes, data[56] will be zero. */ | ||
2826 | if (dlen > 56) { | ||
2827 | if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) { | ||
2828 | /* Update the target capabilities | ||
2829 | */ | ||
2830 | data_56 = data[56]; | ||
2831 | vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56; | ||
2832 | mptscsih_setTargetNegoParms(hd, vtarget, data_56); | ||
2833 | } | ||
2834 | } | ||
2835 | } | ||
2836 | } | 2659 | } |
2837 | 2660 | ||
2838 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2661 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -2842,66 +2665,51 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, | |||
2842 | * | 2665 | * |
2843 | */ | 2666 | */ |
2844 | static void | 2667 | static void |
2845 | mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) | 2668 | mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, |
2669 | struct scsi_device *sdev) | ||
2846 | { | 2670 | { |
2847 | SpiCfgData *pspi_data = &hd->ioc->spi_data; | 2671 | SpiCfgData *pspi_data = &hd->ioc->spi_data; |
2848 | int id = (int) target->target_id; | 2672 | int id = (int) target->target_id; |
2849 | int nvram; | 2673 | int nvram; |
2850 | VirtTarget *vtarget; | ||
2851 | int ii; | ||
2852 | u8 width = MPT_NARROW; | 2674 | u8 width = MPT_NARROW; |
2853 | u8 factor = MPT_ASYNC; | 2675 | u8 factor = MPT_ASYNC; |
2854 | u8 offset = 0; | 2676 | u8 offset = 0; |
2855 | u8 version, nfactor; | 2677 | u8 nfactor; |
2856 | u8 noQas = 1; | 2678 | u8 noQas = 1; |
2857 | 2679 | ||
2858 | target->negoFlags = pspi_data->noQas; | 2680 | target->negoFlags = pspi_data->noQas; |
2859 | 2681 | ||
2860 | /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine | 2682 | /* noQas == 0 => device supports QAS. */ |
2861 | * support. If available, default QAS to off and allow enabling. | ||
2862 | * If not available, default QAS to on, turn off for non-disks. | ||
2863 | */ | ||
2864 | 2683 | ||
2865 | /* Set flags based on Inquiry data | 2684 | if (sdev->scsi_level < SCSI_2) { |
2866 | */ | ||
2867 | version = target->inq_data[2] & 0x07; | ||
2868 | if (version < 2) { | ||
2869 | width = 0; | 2685 | width = 0; |
2870 | factor = MPT_ULTRA2; | 2686 | factor = MPT_ULTRA2; |
2871 | offset = pspi_data->maxSyncOffset; | 2687 | offset = pspi_data->maxSyncOffset; |
2872 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; | 2688 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; |
2873 | } else { | 2689 | } else { |
2874 | if (target->inq_data[7] & 0x20) { | 2690 | if (scsi_device_wide(sdev)) { |
2875 | width = 1; | 2691 | width = 1; |
2876 | } | 2692 | } |
2877 | 2693 | ||
2878 | if (target->inq_data[7] & 0x10) { | 2694 | if (scsi_device_sync(sdev)) { |
2879 | factor = pspi_data->minSyncFactor; | 2695 | factor = pspi_data->minSyncFactor; |
2880 | if (target->tflags & MPT_TARGET_FLAGS_VALID_56) { | 2696 | if (!scsi_device_dt(sdev)) |
2881 | /* bits 2 & 3 show Clocking support */ | ||
2882 | if ((byte56 & 0x0C) == 0) | ||
2883 | factor = MPT_ULTRA2; | 2697 | factor = MPT_ULTRA2; |
2698 | else { | ||
2699 | if (!scsi_device_ius(sdev) && | ||
2700 | !scsi_device_qas(sdev)) | ||
2701 | factor = MPT_ULTRA160; | ||
2884 | else { | 2702 | else { |
2885 | if ((byte56 & 0x03) == 0) | 2703 | factor = MPT_ULTRA320; |
2886 | factor = MPT_ULTRA160; | 2704 | if (scsi_device_qas(sdev)) { |
2887 | else { | 2705 | ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); |
2888 | factor = MPT_ULTRA320; | 2706 | noQas = 0; |
2889 | if (byte56 & 0x02) | ||
2890 | { | ||
2891 | ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); | ||
2892 | noQas = 0; | ||
2893 | } | ||
2894 | if (target->inq_data[0] == TYPE_TAPE) { | ||
2895 | if (byte56 & 0x01) | ||
2896 | target->negoFlags |= MPT_TAPE_NEGO_IDP; | ||
2897 | } | ||
2898 | } | 2707 | } |
2708 | if (sdev->type == TYPE_TAPE && | ||
2709 | scsi_device_ius(sdev)) | ||
2710 | target->negoFlags |= MPT_TAPE_NEGO_IDP; | ||
2899 | } | 2711 | } |
2900 | } else { | ||
2901 | ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id)); | ||
2902 | noQas = 0; | ||
2903 | } | 2712 | } |
2904 | |||
2905 | offset = pspi_data->maxSyncOffset; | 2713 | offset = pspi_data->maxSyncOffset; |
2906 | 2714 | ||
2907 | /* If RAID, never disable QAS | 2715 | /* If RAID, never disable QAS |
@@ -2919,7 +2727,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) | |||
2919 | } | 2727 | } |
2920 | } | 2728 | } |
2921 | 2729 | ||
2922 | if ( (target->inq_data[7] & 0x02) == 0) { | 2730 | if (!sdev->tagged_supported) { |
2923 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; | 2731 | target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; |
2924 | } | 2732 | } |
2925 | 2733 | ||
@@ -2977,305 +2785,23 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56) | |||
2977 | if ( factor > MPT_ULTRA320 ) | 2785 | if ( factor > MPT_ULTRA320 ) |
2978 | noQas = 0; | 2786 | noQas = 0; |
2979 | 2787 | ||
2980 | /* GEM, processor WORKAROUND | 2788 | if (noQas && (pspi_data->noQas == 0)) { |
2981 | */ | 2789 | pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; |
2982 | if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) { | 2790 | target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; |
2983 | target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); | 2791 | |
2984 | pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; | 2792 | /* Disable QAS in a mixed configuration case |
2985 | } else { | 2793 | */ |
2986 | if (noQas && (pspi_data->noQas == 0)) { | ||
2987 | pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; | ||
2988 | target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; | ||
2989 | |||
2990 | /* Disable QAS in a mixed configuration case | ||
2991 | */ | ||
2992 | |||
2993 | ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); | ||
2994 | for (ii = 0; ii < id; ii++) { | ||
2995 | if ( (vtarget = hd->Targets[ii]) ) { | ||
2996 | vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; | ||
2997 | mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags); | ||
2998 | } | ||
2999 | } | ||
3000 | } | ||
3001 | } | ||
3002 | 2794 | ||
3003 | /* Write SDP1 on this I/O to this target */ | 2795 | ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); |
3004 | if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) { | ||
3005 | ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id)); | ||
3006 | mptscsih_writeSDP1(hd, 0, id, hd->negoNvram); | ||
3007 | pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE; | ||
3008 | } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) { | ||
3009 | ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id)); | ||
3010 | mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO); | ||
3011 | pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO; | ||
3012 | } | 2796 | } |
3013 | } | 2797 | } |
3014 | 2798 | ||
3015 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2799 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3016 | /* | ||
3017 | * If no Target, bus reset on 1st I/O. Set the flag to | ||
3018 | * prevent any future negotiations to this device. | ||
3019 | */ | ||
3020 | static void | ||
3021 | mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc) | ||
3022 | { | ||
3023 | VirtDevice *vdev; | ||
3024 | |||
3025 | if ((vdev = sc->device->hostdata) != NULL) | ||
3026 | hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO; | ||
3027 | return; | ||
3028 | } | ||
3029 | 2800 | ||
3030 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2801 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3031 | /* | 2802 | /* |
3032 | * SCSI Config Page functionality ... | 2803 | * SCSI Config Page functionality ... |
3033 | */ | 2804 | */ |
3034 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
3035 | /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags | ||
3036 | * based on width, factor and offset parameters. | ||
3037 | * @width: bus width | ||
3038 | * @factor: sync factor | ||
3039 | * @offset: sync offset | ||
3040 | * @requestedPtr: pointer to requested values (updated) | ||
3041 | * @configurationPtr: pointer to configuration values (updated) | ||
3042 | * @flags: flags to block WDTR or SDTR negotiation | ||
3043 | * | ||
3044 | * Return: None. | ||
3045 | * | ||
3046 | * Remark: Called by writeSDP1 and _dv_params | ||
3047 | */ | ||
3048 | static void | ||
3049 | mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags) | ||
3050 | { | ||
3051 | u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE; | ||
3052 | u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC; | ||
3053 | |||
3054 | *configurationPtr = 0; | ||
3055 | *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; | ||
3056 | *requestedPtr |= (offset << 16) | (factor << 8); | ||
3057 | |||
3058 | if (width && offset && !nowide && !nosync) { | ||
3059 | if (factor < MPT_ULTRA160) { | ||
3060 | *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT); | ||
3061 | if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0) | ||
3062 | *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS; | ||
3063 | if (flags & MPT_TAPE_NEGO_IDP) | ||
3064 | *requestedPtr |= 0x08000000; | ||
3065 | } else if (factor < MPT_ULTRA2) { | ||
3066 | *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT; | ||
3067 | } | ||
3068 | } | ||
3069 | |||
3070 | if (nowide) | ||
3071 | *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED; | ||
3072 | |||
3073 | if (nosync) | ||
3074 | *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED; | ||
3075 | |||
3076 | return; | ||
3077 | } | ||
3078 | |||
3079 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
3080 | /* mptscsih_writeSDP1 - write SCSI Device Page 1 | ||
3081 | * @hd: Pointer to a SCSI Host Strucutre | ||
3082 | * @portnum: IOC port number | ||
3083 | * @target_id: writeSDP1 for single ID | ||
3084 | * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO | ||
3085 | * | ||
3086 | * Return: -EFAULT if read of config page header fails | ||
3087 | * or 0 if success. | ||
3088 | * | ||
3089 | * Remark: If a target has been found, the settings from the | ||
3090 | * target structure are used, else the device is set | ||
3091 | * to async/narrow. | ||
3092 | * | ||
3093 | * Remark: Called during init and after a FW reload. | ||
3094 | * Remark: We do not wait for a return, write pages sequentially. | ||
3095 | */ | ||
3096 | static int | ||
3097 | mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) | ||
3098 | { | ||
3099 | MPT_ADAPTER *ioc = hd->ioc; | ||
3100 | Config_t *pReq; | ||
3101 | SCSIDevicePage1_t *pData; | ||
3102 | VirtTarget *vtarget=NULL; | ||
3103 | MPT_FRAME_HDR *mf; | ||
3104 | dma_addr_t dataDma; | ||
3105 | u16 req_idx; | ||
3106 | u32 frameOffset; | ||
3107 | u32 requested, configuration, flagsLength; | ||
3108 | int ii, nvram; | ||
3109 | int id = 0, maxid = 0; | ||
3110 | u8 width; | ||
3111 | u8 factor; | ||
3112 | u8 offset; | ||
3113 | u8 bus = 0; | ||
3114 | u8 negoFlags; | ||
3115 | u8 maxwidth, maxoffset, maxfactor; | ||
3116 | |||
3117 | if (ioc->spi_data.sdp1length == 0) | ||
3118 | return 0; | ||
3119 | |||
3120 | if (flags & MPT_SCSICFG_ALL_IDS) { | ||
3121 | id = 0; | ||
3122 | maxid = ioc->sh->max_id - 1; | ||
3123 | } else if (ioc->sh) { | ||
3124 | id = target_id; | ||
3125 | maxid = min_t(int, id, ioc->sh->max_id - 1); | ||
3126 | } | ||
3127 | |||
3128 | for (; id <= maxid; id++) { | ||
3129 | |||
3130 | if (id == ioc->pfacts[portnum].PortSCSIID) | ||
3131 | continue; | ||
3132 | |||
3133 | /* Use NVRAM to get adapter and target maximums | ||
3134 | * Data over-riden by target structure information, if present | ||
3135 | */ | ||
3136 | maxwidth = ioc->spi_data.maxBusWidth; | ||
3137 | maxoffset = ioc->spi_data.maxSyncOffset; | ||
3138 | maxfactor = ioc->spi_data.minSyncFactor; | ||
3139 | if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { | ||
3140 | nvram = ioc->spi_data.nvram[id]; | ||
3141 | |||
3142 | if (maxwidth) | ||
3143 | maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; | ||
3144 | |||
3145 | if (maxoffset > 0) { | ||
3146 | maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; | ||
3147 | if (maxfactor == 0) { | ||
3148 | /* Key for async */ | ||
3149 | maxfactor = MPT_ASYNC; | ||
3150 | maxoffset = 0; | ||
3151 | } else if (maxfactor < ioc->spi_data.minSyncFactor) { | ||
3152 | maxfactor = ioc->spi_data.minSyncFactor; | ||
3153 | } | ||
3154 | } else | ||
3155 | maxfactor = MPT_ASYNC; | ||
3156 | } | ||
3157 | |||
3158 | /* Set the negotiation flags. | ||
3159 | */ | ||
3160 | negoFlags = ioc->spi_data.noQas; | ||
3161 | if (!maxwidth) | ||
3162 | negoFlags |= MPT_TARGET_NO_NEGO_WIDE; | ||
3163 | |||
3164 | if (!maxoffset) | ||
3165 | negoFlags |= MPT_TARGET_NO_NEGO_SYNC; | ||
3166 | |||
3167 | if (flags & MPT_SCSICFG_USE_NVRAM) { | ||
3168 | width = maxwidth; | ||
3169 | factor = maxfactor; | ||
3170 | offset = maxoffset; | ||
3171 | } else { | ||
3172 | width = 0; | ||
3173 | factor = MPT_ASYNC; | ||
3174 | offset = 0; | ||
3175 | //negoFlags = 0; | ||
3176 | //negoFlags = MPT_TARGET_NO_NEGO_SYNC; | ||
3177 | } | ||
3178 | |||
3179 | /* If id is not a raid volume, get the updated | ||
3180 | * transmission settings from the target structure. | ||
3181 | */ | ||
3182 | if (hd->Targets && (vtarget = hd->Targets[id]) && !vtarget->raidVolume) { | ||
3183 | width = vtarget->maxWidth; | ||
3184 | factor = vtarget->minSyncFactor; | ||
3185 | offset = vtarget->maxOffset; | ||
3186 | negoFlags = vtarget->negoFlags; | ||
3187 | } | ||
3188 | |||
3189 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
3190 | /* Force to async and narrow if DV has not been executed | ||
3191 | * for this ID | ||
3192 | */ | ||
3193 | if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) { | ||
3194 | width = 0; | ||
3195 | factor = MPT_ASYNC; | ||
3196 | offset = 0; | ||
3197 | } | ||
3198 | #endif | ||
3199 | |||
3200 | if (flags & MPT_SCSICFG_BLK_NEGO) | ||
3201 | negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; | ||
3202 | |||
3203 | mptscsih_setDevicePage1Flags(width, factor, offset, | ||
3204 | &requested, &configuration, negoFlags); | ||
3205 | dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", | ||
3206 | target_id, width, factor, offset, negoFlags, requested, configuration)); | ||
3207 | |||
3208 | /* Get a MF for this command. | ||
3209 | */ | ||
3210 | if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { | ||
3211 | dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n", | ||
3212 | ioc->name)); | ||
3213 | return -EAGAIN; | ||
3214 | } | ||
3215 | |||
3216 | ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n", | ||
3217 | hd->ioc->name, mf, id, requested, configuration)); | ||
3218 | |||
3219 | |||
3220 | /* Set the request and the data pointers. | ||
3221 | * Request takes: 36 bytes (32 bit SGE) | ||
3222 | * SCSI Device Page 1 requires 16 bytes | ||
3223 | * 40 + 16 <= size of SCSI IO Request = 56 bytes | ||
3224 | * and MF size >= 64 bytes. | ||
3225 | * Place data at end of MF. | ||
3226 | */ | ||
3227 | pReq = (Config_t *)mf; | ||
3228 | |||
3229 | req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
3230 | frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t); | ||
3231 | |||
3232 | pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset); | ||
3233 | dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset; | ||
3234 | |||
3235 | /* Complete the request frame (same for all requests). | ||
3236 | */ | ||
3237 | pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
3238 | pReq->Reserved = 0; | ||
3239 | pReq->ChainOffset = 0; | ||
3240 | pReq->Function = MPI_FUNCTION_CONFIG; | ||
3241 | pReq->ExtPageLength = 0; | ||
3242 | pReq->ExtPageType = 0; | ||
3243 | pReq->MsgFlags = 0; | ||
3244 | for (ii=0; ii < 8; ii++) { | ||
3245 | pReq->Reserved2[ii] = 0; | ||
3246 | } | ||
3247 | pReq->Header.PageVersion = ioc->spi_data.sdp1version; | ||
3248 | pReq->Header.PageLength = ioc->spi_data.sdp1length; | ||
3249 | pReq->Header.PageNumber = 1; | ||
3250 | pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
3251 | pReq->PageAddress = cpu_to_le32(id | (bus << 8 )); | ||
3252 | |||
3253 | /* Add a SGE to the config request. | ||
3254 | */ | ||
3255 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4; | ||
3256 | |||
3257 | mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); | ||
3258 | |||
3259 | /* Set up the common data portion | ||
3260 | */ | ||
3261 | pData->Header.PageVersion = pReq->Header.PageVersion; | ||
3262 | pData->Header.PageLength = pReq->Header.PageLength; | ||
3263 | pData->Header.PageNumber = pReq->Header.PageNumber; | ||
3264 | pData->Header.PageType = pReq->Header.PageType; | ||
3265 | pData->RequestedParameters = cpu_to_le32(requested); | ||
3266 | pData->Reserved = 0; | ||
3267 | pData->Configuration = cpu_to_le32(configuration); | ||
3268 | |||
3269 | dprintk((MYIOC_s_INFO_FMT | ||
3270 | "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n", | ||
3271 | ioc->name, id, (id | (bus<<8)), | ||
3272 | requested, configuration)); | ||
3273 | |||
3274 | mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); | ||
3275 | } | ||
3276 | |||
3277 | return 0; | ||
3278 | } | ||
3279 | 2805 | ||
3280 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2806 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3281 | /* mptscsih_writeIOCPage4 - write IOC Page 4 | 2807 | /* mptscsih_writeIOCPage4 - write IOC Page 4 |
@@ -3465,6 +2991,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
3465 | completionCode = MPT_SCANDV_GOOD; | 2991 | completionCode = MPT_SCANDV_GOOD; |
3466 | else | 2992 | else |
3467 | completionCode = MPT_SCANDV_SOME_ERROR; | 2993 | completionCode = MPT_SCANDV_SOME_ERROR; |
2994 | memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense)); | ||
3468 | 2995 | ||
3469 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { | 2996 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { |
3470 | u8 *sense_data; | 2997 | u8 *sense_data; |
@@ -3578,78 +3105,6 @@ mptscsih_timer_expired(unsigned long data) | |||
3578 | return; | 3105 | return; |
3579 | } | 3106 | } |
3580 | 3107 | ||
3581 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
3582 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
3583 | /* mptscsih_do_raid - Format and Issue a RAID volume request message. | ||
3584 | * @hd: Pointer to scsi host structure | ||
3585 | * @action: What do be done. | ||
3586 | * @id: Logical target id. | ||
3587 | * @bus: Target locations bus. | ||
3588 | * | ||
3589 | * Returns: < 0 on a fatal error | ||
3590 | * 0 on success | ||
3591 | * | ||
3592 | * Remark: Wait to return until reply processed by the ISR. | ||
3593 | */ | ||
3594 | static int | ||
3595 | mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io) | ||
3596 | { | ||
3597 | MpiRaidActionRequest_t *pReq; | ||
3598 | MPT_FRAME_HDR *mf; | ||
3599 | int in_isr; | ||
3600 | |||
3601 | in_isr = in_interrupt(); | ||
3602 | if (in_isr) { | ||
3603 | dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n", | ||
3604 | hd->ioc->name)); | ||
3605 | return -EPERM; | ||
3606 | } | ||
3607 | |||
3608 | /* Get and Populate a free Frame | ||
3609 | */ | ||
3610 | if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { | ||
3611 | ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", | ||
3612 | hd->ioc->name)); | ||
3613 | return -EAGAIN; | ||
3614 | } | ||
3615 | pReq = (MpiRaidActionRequest_t *)mf; | ||
3616 | pReq->Action = action; | ||
3617 | pReq->Reserved1 = 0; | ||
3618 | pReq->ChainOffset = 0; | ||
3619 | pReq->Function = MPI_FUNCTION_RAID_ACTION; | ||
3620 | pReq->VolumeID = io->id; | ||
3621 | pReq->VolumeBus = io->bus; | ||
3622 | pReq->PhysDiskNum = io->physDiskNum; | ||
3623 | pReq->MsgFlags = 0; | ||
3624 | pReq->Reserved2 = 0; | ||
3625 | pReq->ActionDataWord = 0; /* Reserved for this action */ | ||
3626 | //pReq->ActionDataSGE = 0; | ||
3627 | |||
3628 | mpt_add_sge((char *)&pReq->ActionDataSGE, | ||
3629 | MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); | ||
3630 | |||
3631 | ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", | ||
3632 | hd->ioc->name, action, io->id)); | ||
3633 | |||
3634 | hd->pLocal = NULL; | ||
3635 | hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ | ||
3636 | hd->scandv_wait_done = 0; | ||
3637 | |||
3638 | /* Save cmd pointer, for resource free if timeout or | ||
3639 | * FW reload occurs | ||
3640 | */ | ||
3641 | hd->cmdPtr = mf; | ||
3642 | |||
3643 | add_timer(&hd->timer); | ||
3644 | mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); | ||
3645 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | ||
3646 | |||
3647 | if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD)) | ||
3648 | return -1; | ||
3649 | |||
3650 | return 0; | ||
3651 | } | ||
3652 | #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */ | ||
3653 | 3108 | ||
3654 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3109 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3655 | /** | 3110 | /** |
@@ -3903,93 +3358,6 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3903 | 3358 | ||
3904 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3359 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3905 | /** | 3360 | /** |
3906 | * mptscsih_negotiate_to_asyn_narrow - Restore devices to default state | ||
3907 | * @hd: Pointer to a SCSI HOST structure | ||
3908 | * @vtarget: per device private data | ||
3909 | * | ||
3910 | * Uses the ISR, but with special processing. | ||
3911 | * MUST be single-threaded. | ||
3912 | * | ||
3913 | */ | ||
3914 | static void | ||
3915 | mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | ||
3916 | { | ||
3917 | VirtTarget *vtarget = vdevice->vtarget; | ||
3918 | MPT_ADAPTER *ioc= hd->ioc; | ||
3919 | SCSIDevicePage1_t *pcfg1Data; | ||
3920 | CONFIGPARMS cfg; | ||
3921 | dma_addr_t cfg1_dma_addr; | ||
3922 | ConfigPageHeader_t header; | ||
3923 | int id; | ||
3924 | int requested, configuration, data,i; | ||
3925 | u8 flags, factor; | ||
3926 | |||
3927 | if ((ioc->bus_type != SPI) || | ||
3928 | (!vdevice->configured_lun)) | ||
3929 | return; | ||
3930 | |||
3931 | if (!ioc->spi_data.sdp1length) | ||
3932 | return; | ||
3933 | |||
3934 | pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev, | ||
3935 | ioc->spi_data.sdp1length * 4, &cfg1_dma_addr); | ||
3936 | |||
3937 | if (pcfg1Data == NULL) | ||
3938 | return; | ||
3939 | |||
3940 | header.PageVersion = ioc->spi_data.sdp1version; | ||
3941 | header.PageLength = ioc->spi_data.sdp1length; | ||
3942 | header.PageNumber = 1; | ||
3943 | header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
3944 | cfg.cfghdr.hdr = &header; | ||
3945 | cfg.physAddr = cfg1_dma_addr; | ||
3946 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
3947 | cfg.dir = 1; | ||
3948 | cfg.timeout = 0; | ||
3949 | |||
3950 | if (vtarget->raidVolume && ioc->raid_data.pIocPg3) { | ||
3951 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
3952 | id = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID; | ||
3953 | flags = hd->ioc->spi_data.noQas; | ||
3954 | if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { | ||
3955 | data = hd->ioc->spi_data.nvram[id]; | ||
3956 | if (data & MPT_NVRAM_WIDE_DISABLE) | ||
3957 | flags |= MPT_TARGET_NO_NEGO_WIDE; | ||
3958 | factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; | ||
3959 | if ((factor == 0) || (factor == MPT_ASYNC)) | ||
3960 | flags |= MPT_TARGET_NO_NEGO_SYNC; | ||
3961 | } | ||
3962 | mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, | ||
3963 | &configuration, flags); | ||
3964 | dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC " | ||
3965 | "offset=0 negoFlags=%x request=%x config=%x\n", | ||
3966 | id, flags, requested, configuration)); | ||
3967 | pcfg1Data->RequestedParameters = cpu_to_le32(requested); | ||
3968 | pcfg1Data->Reserved = 0; | ||
3969 | pcfg1Data->Configuration = cpu_to_le32(configuration); | ||
3970 | cfg.pageAddr = (vtarget->bus_id<<8) | id; | ||
3971 | mpt_config(hd->ioc, &cfg); | ||
3972 | } | ||
3973 | } else { | ||
3974 | flags = vtarget->negoFlags; | ||
3975 | mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, | ||
3976 | &configuration, flags); | ||
3977 | dnegoprintk(("nego asyn narrow: id=%d width=0 factor=MPT_ASYNC " | ||
3978 | "offset=0 negoFlags=%x request=%x config=%x\n", | ||
3979 | vtarget->target_id, flags, requested, configuration)); | ||
3980 | pcfg1Data->RequestedParameters = cpu_to_le32(requested); | ||
3981 | pcfg1Data->Reserved = 0; | ||
3982 | pcfg1Data->Configuration = cpu_to_le32(configuration); | ||
3983 | cfg.pageAddr = (vtarget->bus_id<<8) | vtarget->target_id; | ||
3984 | mpt_config(hd->ioc, &cfg); | ||
3985 | } | ||
3986 | |||
3987 | if (pcfg1Data) | ||
3988 | pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr); | ||
3989 | } | ||
3990 | |||
3991 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
3992 | /** | ||
3993 | * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. | 3361 | * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. |
3994 | * @hd: Pointer to a SCSI HOST structure | 3362 | * @hd: Pointer to a SCSI HOST structure |
3995 | * @vtarget: per device private data | 3363 | * @vtarget: per device private data |
@@ -4014,1637 +3382,15 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | |||
4014 | iocmd.data_dma = -1; | 3382 | iocmd.data_dma = -1; |
4015 | iocmd.size = 0; | 3383 | iocmd.size = 0; |
4016 | iocmd.rsvd = iocmd.rsvd2 = 0; | 3384 | iocmd.rsvd = iocmd.rsvd2 = 0; |
4017 | iocmd.bus = vdevice->bus_id; | 3385 | iocmd.bus = vdevice->vtarget->bus_id; |
4018 | iocmd.id = vdevice->target_id; | 3386 | iocmd.id = vdevice->vtarget->target_id; |
4019 | iocmd.lun = (u8)vdevice->lun; | 3387 | iocmd.lun = (u8)vdevice->lun; |
4020 | 3388 | ||
4021 | if ((vdevice->vtarget->type & TYPE_DISK) && | 3389 | if ((vdevice->vtarget->type == TYPE_DISK) && |
4022 | (vdevice->configured_lun)) | 3390 | (vdevice->configured_lun)) |
4023 | mptscsih_do_cmd(hd, &iocmd); | 3391 | mptscsih_do_cmd(hd, &iocmd); |
4024 | } | 3392 | } |
4025 | 3393 | ||
4026 | /* Search IOC page 3 to determine if this is hidden physical disk | ||
4027 | */ | ||
4028 | static int | ||
4029 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) | ||
4030 | { | ||
4031 | int i; | ||
4032 | |||
4033 | if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) | ||
4034 | return 0; | ||
4035 | |||
4036 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
4037 | if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) | ||
4038 | return 1; | ||
4039 | } | ||
4040 | |||
4041 | return 0; | ||
4042 | } | ||
4043 | |||
4044 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
4045 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
4046 | /** | ||
4047 | * mptscsih_domainValidation - Top level handler for domain validation. | ||
4048 | * @hd: Pointer to MPT_SCSI_HOST structure. | ||
4049 | * | ||
4050 | * Uses the ISR, but with special processing. | ||
4051 | * Called from schedule, should not be in interrupt mode. | ||
4052 | * While thread alive, do dv for all devices needing dv | ||
4053 | * | ||
4054 | * Return: None. | ||
4055 | */ | ||
4056 | static void | ||
4057 | mptscsih_domainValidation(void *arg) | ||
4058 | { | ||
4059 | MPT_SCSI_HOST *hd; | ||
4060 | MPT_ADAPTER *ioc; | ||
4061 | unsigned long flags; | ||
4062 | int id, maxid, dvStatus, did; | ||
4063 | int ii, isPhysDisk; | ||
4064 | |||
4065 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
4066 | dvtaskQ_active = 1; | ||
4067 | if (dvtaskQ_release) { | ||
4068 | dvtaskQ_active = 0; | ||
4069 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4070 | return; | ||
4071 | } | ||
4072 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4073 | |||
4074 | /* For this ioc, loop through all devices and do dv to each device. | ||
4075 | * When complete with this ioc, search through the ioc list, and | ||
4076 | * for each scsi ioc found, do dv for all devices. Exit when no | ||
4077 | * device needs dv. | ||
4078 | */ | ||
4079 | did = 1; | ||
4080 | while (did) { | ||
4081 | did = 0; | ||
4082 | list_for_each_entry(ioc, &ioc_list, list) { | ||
4083 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
4084 | if (dvtaskQ_release) { | ||
4085 | dvtaskQ_active = 0; | ||
4086 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4087 | return; | ||
4088 | } | ||
4089 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4090 | |||
4091 | msleep(250); | ||
4092 | |||
4093 | /* DV only to SPI adapters */ | ||
4094 | if (ioc->bus_type != SPI) | ||
4095 | continue; | ||
4096 | |||
4097 | /* Make sure everything looks ok */ | ||
4098 | if (ioc->sh == NULL) | ||
4099 | continue; | ||
4100 | |||
4101 | hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; | ||
4102 | if (hd == NULL) | ||
4103 | continue; | ||
4104 | |||
4105 | if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { | ||
4106 | mpt_read_ioc_pg_3(ioc); | ||
4107 | if (ioc->raid_data.pIocPg3) { | ||
4108 | Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; | ||
4109 | int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; | ||
4110 | |||
4111 | while (numPDisk) { | ||
4112 | if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) | ||
4113 | ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; | ||
4114 | |||
4115 | pPDisk++; | ||
4116 | numPDisk--; | ||
4117 | } | ||
4118 | } | ||
4119 | ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3; | ||
4120 | } | ||
4121 | |||
4122 | maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES); | ||
4123 | |||
4124 | for (id = 0; id < maxid; id++) { | ||
4125 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
4126 | if (dvtaskQ_release) { | ||
4127 | dvtaskQ_active = 0; | ||
4128 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4129 | return; | ||
4130 | } | ||
4131 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4132 | dvStatus = hd->ioc->spi_data.dvStatus[id]; | ||
4133 | |||
4134 | if (dvStatus & MPT_SCSICFG_NEED_DV) { | ||
4135 | did++; | ||
4136 | hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING; | ||
4137 | hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV; | ||
4138 | |||
4139 | msleep(250); | ||
4140 | |||
4141 | /* If hidden phys disk, block IO's to all | ||
4142 | * raid volumes | ||
4143 | * else, process normally | ||
4144 | */ | ||
4145 | isPhysDisk = mptscsih_is_phys_disk(ioc, id); | ||
4146 | if (isPhysDisk) { | ||
4147 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | ||
4148 | if (hd->ioc->raid_data.isRaid & (1 << ii)) { | ||
4149 | hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING; | ||
4150 | } | ||
4151 | } | ||
4152 | } | ||
4153 | |||
4154 | if(mpt_alt_ioc_wait(hd->ioc)!=0) { | ||
4155 | ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n", | ||
4156 | hd->ioc->name)); | ||
4157 | continue; | ||
4158 | } | ||
4159 | |||
4160 | if (mptscsih_doDv(hd, 0, id) == 1) { | ||
4161 | /* Untagged device was busy, try again | ||
4162 | */ | ||
4163 | hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV; | ||
4164 | hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING; | ||
4165 | } else { | ||
4166 | /* DV is complete. Clear flags. | ||
4167 | */ | ||
4168 | hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING); | ||
4169 | } | ||
4170 | |||
4171 | spin_lock(&hd->ioc->initializing_hba_lock); | ||
4172 | hd->ioc->initializing_hba_lock_flag=0; | ||
4173 | spin_unlock(&hd->ioc->initializing_hba_lock); | ||
4174 | |||
4175 | if (isPhysDisk) { | ||
4176 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | ||
4177 | if (hd->ioc->raid_data.isRaid & (1 << ii)) { | ||
4178 | hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING; | ||
4179 | } | ||
4180 | } | ||
4181 | } | ||
4182 | |||
4183 | if (hd->ioc->spi_data.noQas) | ||
4184 | mptscsih_qas_check(hd, id); | ||
4185 | } | ||
4186 | } | ||
4187 | } | ||
4188 | } | ||
4189 | |||
4190 | spin_lock_irqsave(&dvtaskQ_lock, flags); | ||
4191 | dvtaskQ_active = 0; | ||
4192 | spin_unlock_irqrestore(&dvtaskQ_lock, flags); | ||
4193 | |||
4194 | return; | ||
4195 | } | ||
4196 | |||
4197 | /* Write SDP1 if no QAS has been enabled | ||
4198 | */ | ||
4199 | static void | ||
4200 | mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) | ||
4201 | { | ||
4202 | VirtTarget *vtarget; | ||
4203 | int ii; | ||
4204 | |||
4205 | if (hd->Targets == NULL) | ||
4206 | return; | ||
4207 | |||
4208 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | ||
4209 | if (ii == id) | ||
4210 | continue; | ||
4211 | |||
4212 | if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0) | ||
4213 | continue; | ||
4214 | |||
4215 | vtarget = hd->Targets[ii]; | ||
4216 | |||
4217 | if ((vtarget != NULL) && (!vtarget->raidVolume)) { | ||
4218 | if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) { | ||
4219 | vtarget->negoFlags |= hd->ioc->spi_data.noQas; | ||
4220 | dnegoprintk(("writeSDP1: id=%d flags=0\n", id)); | ||
4221 | mptscsih_writeSDP1(hd, 0, ii, 0); | ||
4222 | } | ||
4223 | } else { | ||
4224 | if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) { | ||
4225 | dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id)); | ||
4226 | mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM); | ||
4227 | } | ||
4228 | } | ||
4229 | } | ||
4230 | return; | ||
4231 | } | ||
4232 | |||
4233 | |||
4234 | |||
4235 | #define MPT_GET_NVRAM_VALS 0x01 | ||
4236 | #define MPT_UPDATE_MAX 0x02 | ||
4237 | #define MPT_SET_MAX 0x04 | ||
4238 | #define MPT_SET_MIN 0x08 | ||
4239 | #define MPT_FALLBACK 0x10 | ||
4240 | #define MPT_SAVE 0x20 | ||
4241 | |||
4242 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
4243 | /** | ||
4244 | * mptscsih_doDv - Perform domain validation to a target. | ||
4245 | * @hd: Pointer to MPT_SCSI_HOST structure. | ||
4246 | * @portnum: IOC port number. | ||
4247 | * @target: Physical ID of this target | ||
4248 | * | ||
4249 | * Uses the ISR, but with special processing. | ||
4250 | * MUST be single-threaded. | ||
4251 | * Test will exit if target is at async & narrow. | ||
4252 | * | ||
4253 | * Return: None. | ||
4254 | */ | ||
4255 | static int | ||
4256 | mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) | ||
4257 | { | ||
4258 | MPT_ADAPTER *ioc = hd->ioc; | ||
4259 | VirtTarget *vtarget; | ||
4260 | SCSIDevicePage1_t *pcfg1Data; | ||
4261 | SCSIDevicePage0_t *pcfg0Data; | ||
4262 | u8 *pbuf1; | ||
4263 | u8 *pbuf2; | ||
4264 | u8 *pDvBuf; | ||
4265 | dma_addr_t dvbuf_dma = -1; | ||
4266 | dma_addr_t buf1_dma = -1; | ||
4267 | dma_addr_t buf2_dma = -1; | ||
4268 | dma_addr_t cfg1_dma_addr = -1; | ||
4269 | dma_addr_t cfg0_dma_addr = -1; | ||
4270 | ConfigPageHeader_t header1; | ||
4271 | ConfigPageHeader_t header0; | ||
4272 | DVPARAMETERS dv; | ||
4273 | INTERNAL_CMD iocmd; | ||
4274 | CONFIGPARMS cfg; | ||
4275 | int dv_alloc = 0; | ||
4276 | int rc, sz = 0; | ||
4277 | int bufsize = 0; | ||
4278 | int dataBufSize = 0; | ||
4279 | int echoBufSize = 0; | ||
4280 | int notDone; | ||
4281 | int patt; | ||
4282 | int repeat; | ||
4283 | int retcode = 0; | ||
4284 | int nfactor = MPT_ULTRA320; | ||
4285 | char firstPass = 1; | ||
4286 | char doFallback = 0; | ||
4287 | char readPage0; | ||
4288 | char bus, lun; | ||
4289 | char inq0 = 0; | ||
4290 | |||
4291 | if (ioc->spi_data.sdp1length == 0) | ||
4292 | return 0; | ||
4293 | |||
4294 | if (ioc->spi_data.sdp0length == 0) | ||
4295 | return 0; | ||
4296 | |||
4297 | /* If multiple buses are used, require that the initiator | ||
4298 | * id be the same on all buses. | ||
4299 | */ | ||
4300 | if (id == ioc->pfacts[0].PortSCSIID) | ||
4301 | return 0; | ||
4302 | |||
4303 | lun = 0; | ||
4304 | bus = (u8) bus_number; | ||
4305 | ddvtprintk((MYIOC_s_NOTE_FMT | ||
4306 | "DV started: bus=%d, id=%d dv @ %p\n", | ||
4307 | ioc->name, bus, id, &dv)); | ||
4308 | |||
4309 | /* Prep DV structure | ||
4310 | */ | ||
4311 | memset (&dv, 0, sizeof(DVPARAMETERS)); | ||
4312 | dv.id = id; | ||
4313 | |||
4314 | /* Populate tmax with the current maximum | ||
4315 | * transfer parameters for this target. | ||
4316 | * Exit if narrow and async. | ||
4317 | */ | ||
4318 | dv.cmd = MPT_GET_NVRAM_VALS; | ||
4319 | mptscsih_dv_parms(hd, &dv, NULL); | ||
4320 | |||
4321 | /* Prep SCSI IO structure | ||
4322 | */ | ||
4323 | iocmd.id = id; | ||
4324 | iocmd.bus = bus; | ||
4325 | iocmd.lun = lun; | ||
4326 | iocmd.flags = 0; | ||
4327 | iocmd.physDiskNum = -1; | ||
4328 | iocmd.rsvd = iocmd.rsvd2 = 0; | ||
4329 | |||
4330 | vtarget = hd->Targets[id]; | ||
4331 | |||
4332 | /* Use tagged commands if possible. | ||
4333 | */ | ||
4334 | if (vtarget) { | ||
4335 | if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) | ||
4336 | iocmd.flags |= MPT_ICFLAG_TAGGED_CMD; | ||
4337 | else { | ||
4338 | if (hd->ioc->facts.FWVersion.Word < 0x01000600) | ||
4339 | return 0; | ||
4340 | |||
4341 | if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && | ||
4342 | (hd->ioc->facts.FWVersion.Word < 0x01010B00)) | ||
4343 | return 0; | ||
4344 | } | ||
4345 | } | ||
4346 | |||
4347 | /* Prep cfg structure | ||
4348 | */ | ||
4349 | cfg.pageAddr = (bus<<8) | id; | ||
4350 | cfg.cfghdr.hdr = NULL; | ||
4351 | |||
4352 | /* Prep SDP0 header | ||
4353 | */ | ||
4354 | header0.PageVersion = ioc->spi_data.sdp0version; | ||
4355 | header0.PageLength = ioc->spi_data.sdp0length; | ||
4356 | header0.PageNumber = 0; | ||
4357 | header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
4358 | |||
4359 | /* Prep SDP1 header | ||
4360 | */ | ||
4361 | header1.PageVersion = ioc->spi_data.sdp1version; | ||
4362 | header1.PageLength = ioc->spi_data.sdp1length; | ||
4363 | header1.PageNumber = 1; | ||
4364 | header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
4365 | |||
4366 | if (header0.PageLength & 1) | ||
4367 | dv_alloc = (header0.PageLength * 4) + 4; | ||
4368 | |||
4369 | dv_alloc += (2048 + (header1.PageLength * 4)); | ||
4370 | |||
4371 | pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma); | ||
4372 | if (pDvBuf == NULL) | ||
4373 | return 0; | ||
4374 | |||
4375 | sz = 0; | ||
4376 | pbuf1 = (u8 *)pDvBuf; | ||
4377 | buf1_dma = dvbuf_dma; | ||
4378 | sz +=1024; | ||
4379 | |||
4380 | pbuf2 = (u8 *) (pDvBuf + sz); | ||
4381 | buf2_dma = dvbuf_dma + sz; | ||
4382 | sz +=1024; | ||
4383 | |||
4384 | pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz); | ||
4385 | cfg0_dma_addr = dvbuf_dma + sz; | ||
4386 | sz += header0.PageLength * 4; | ||
4387 | |||
4388 | /* 8-byte alignment | ||
4389 | */ | ||
4390 | if (header0.PageLength & 1) | ||
4391 | sz += 4; | ||
4392 | |||
4393 | pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz); | ||
4394 | cfg1_dma_addr = dvbuf_dma + sz; | ||
4395 | |||
4396 | /* Skip this ID? Set cfg.cfghdr.hdr to force config page write | ||
4397 | */ | ||
4398 | { | ||
4399 | SpiCfgData *pspi_data = &hd->ioc->spi_data; | ||
4400 | if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { | ||
4401 | /* Set the factor from nvram */ | ||
4402 | nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; | ||
4403 | if (nfactor < pspi_data->minSyncFactor ) | ||
4404 | nfactor = pspi_data->minSyncFactor; | ||
4405 | |||
4406 | if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) || | ||
4407 | (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) { | ||
4408 | |||
4409 | ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n", | ||
4410 | ioc->name, bus, id, lun)); | ||
4411 | |||
4412 | dv.cmd = MPT_SET_MAX; | ||
4413 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
4414 | cfg.cfghdr.hdr = &header1; | ||
4415 | |||
4416 | /* Save the final negotiated settings to | ||
4417 | * SCSI device page 1. | ||
4418 | */ | ||
4419 | cfg.physAddr = cfg1_dma_addr; | ||
4420 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
4421 | cfg.dir = 1; | ||
4422 | mpt_config(hd->ioc, &cfg); | ||
4423 | goto target_done; | ||
4424 | } | ||
4425 | } | ||
4426 | } | ||
4427 | |||
4428 | /* Finish iocmd inititialization - hidden or visible disk? */ | ||
4429 | if (ioc->raid_data.pIocPg3) { | ||
4430 | /* Search IOC page 3 for matching id | ||
4431 | */ | ||
4432 | Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; | ||
4433 | int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; | ||
4434 | |||
4435 | while (numPDisk) { | ||
4436 | if (pPDisk->PhysDiskID == id) { | ||
4437 | /* match */ | ||
4438 | iocmd.flags |= MPT_ICFLAG_PHYS_DISK; | ||
4439 | iocmd.physDiskNum = pPDisk->PhysDiskNum; | ||
4440 | |||
4441 | /* Quiesce the IM | ||
4442 | */ | ||
4443 | if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) { | ||
4444 | ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name)); | ||
4445 | goto target_done; | ||
4446 | } | ||
4447 | break; | ||
4448 | } | ||
4449 | pPDisk++; | ||
4450 | numPDisk--; | ||
4451 | } | ||
4452 | } | ||
4453 | |||
4454 | /* RAID Volume ID's may double for a physical device. If RAID but | ||
4455 | * not a physical ID as well, skip DV. | ||
4456 | */ | ||
4457 | if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) | ||
4458 | goto target_done; | ||
4459 | |||
4460 | |||
4461 | /* Basic Test. | ||
4462 | * Async & Narrow - Inquiry | ||
4463 | * Async & Narrow - Inquiry | ||
4464 | * Maximum transfer rate - Inquiry | ||
4465 | * Compare buffers: | ||
4466 | * If compare, test complete. | ||
4467 | * If miscompare and first pass, repeat | ||
4468 | * If miscompare and not first pass, fall back and repeat | ||
4469 | */ | ||
4470 | hd->pLocal = NULL; | ||
4471 | readPage0 = 0; | ||
4472 | sz = SCSI_MAX_INQUIRY_BYTES; | ||
4473 | rc = MPT_SCANDV_GOOD; | ||
4474 | while (1) { | ||
4475 | ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id)); | ||
4476 | retcode = 0; | ||
4477 | dv.cmd = MPT_SET_MIN; | ||
4478 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
4479 | |||
4480 | cfg.cfghdr.hdr = &header1; | ||
4481 | cfg.physAddr = cfg1_dma_addr; | ||
4482 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
4483 | cfg.dir = 1; | ||
4484 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
4485 | goto target_done; | ||
4486 | |||
4487 | /* Wide - narrow - wide workaround case | ||
4488 | */ | ||
4489 | if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) { | ||
4490 | /* Send an untagged command to reset disk Qs corrupted | ||
4491 | * when a parity error occurs on a Request Sense. | ||
4492 | */ | ||
4493 | if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) || | ||
4494 | ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && | ||
4495 | (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) { | ||
4496 | |||
4497 | iocmd.cmd = REQUEST_SENSE; | ||
4498 | iocmd.data_dma = buf1_dma; | ||
4499 | iocmd.data = pbuf1; | ||
4500 | iocmd.size = 0x12; | ||
4501 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4502 | goto target_done; | ||
4503 | else { | ||
4504 | if (hd->pLocal == NULL) | ||
4505 | goto target_done; | ||
4506 | rc = hd->pLocal->completion; | ||
4507 | if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) { | ||
4508 | dv.max.width = 0; | ||
4509 | doFallback = 0; | ||
4510 | } else | ||
4511 | goto target_done; | ||
4512 | } | ||
4513 | } else | ||
4514 | goto target_done; | ||
4515 | } | ||
4516 | |||
4517 | iocmd.cmd = INQUIRY; | ||
4518 | iocmd.data_dma = buf1_dma; | ||
4519 | iocmd.data = pbuf1; | ||
4520 | iocmd.size = sz; | ||
4521 | memset(pbuf1, 0x00, sz); | ||
4522 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4523 | goto target_done; | ||
4524 | else { | ||
4525 | if (hd->pLocal == NULL) | ||
4526 | goto target_done; | ||
4527 | rc = hd->pLocal->completion; | ||
4528 | if (rc == MPT_SCANDV_GOOD) { | ||
4529 | if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) { | ||
4530 | if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0) | ||
4531 | retcode = 1; | ||
4532 | else | ||
4533 | retcode = 0; | ||
4534 | |||
4535 | goto target_done; | ||
4536 | } | ||
4537 | } else if (rc == MPT_SCANDV_SENSE) { | ||
4538 | ; | ||
4539 | } else { | ||
4540 | /* If first command doesn't complete | ||
4541 | * with a good status or with a check condition, | ||
4542 | * exit. | ||
4543 | */ | ||
4544 | goto target_done; | ||
4545 | } | ||
4546 | } | ||
4547 | |||
4548 | /* Reset the size for disks | ||
4549 | */ | ||
4550 | inq0 = (*pbuf1) & 0x1F; | ||
4551 | if ((inq0 == 0) && vtarget && !vtarget->raidVolume) { | ||
4552 | sz = 0x40; | ||
4553 | iocmd.size = sz; | ||
4554 | } | ||
4555 | |||
4556 | /* Another GEM workaround. Check peripheral device type, | ||
4557 | * if PROCESSOR, quit DV. | ||
4558 | */ | ||
4559 | if (inq0 == TYPE_PROCESSOR) { | ||
4560 | mptscsih_initTarget(hd, | ||
4561 | vtarget, | ||
4562 | lun, | ||
4563 | pbuf1, | ||
4564 | sz); | ||
4565 | goto target_done; | ||
4566 | } | ||
4567 | |||
4568 | if (inq0 > 0x08) | ||
4569 | goto target_done; | ||
4570 | |||
4571 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4572 | goto target_done; | ||
4573 | |||
4574 | if (sz == 0x40) { | ||
4575 | if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A) | ||
4576 | && (vtarget->minSyncFactor > 0x09)) { | ||
4577 | if ((pbuf1[56] & 0x04) == 0) | ||
4578 | ; | ||
4579 | else if ((pbuf1[56] & 0x01) == 1) { | ||
4580 | vtarget->minSyncFactor = | ||
4581 | nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320; | ||
4582 | } else { | ||
4583 | vtarget->minSyncFactor = | ||
4584 | nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160; | ||
4585 | } | ||
4586 | |||
4587 | dv.max.factor = vtarget->minSyncFactor; | ||
4588 | |||
4589 | if ((pbuf1[56] & 0x02) == 0) { | ||
4590 | vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; | ||
4591 | hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; | ||
4592 | ddvprintk((MYIOC_s_NOTE_FMT | ||
4593 | "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", | ||
4594 | ioc->name, id, pbuf1[56])); | ||
4595 | } | ||
4596 | } | ||
4597 | } | ||
4598 | |||
4599 | if (doFallback) | ||
4600 | dv.cmd = MPT_FALLBACK; | ||
4601 | else | ||
4602 | dv.cmd = MPT_SET_MAX; | ||
4603 | |||
4604 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
4605 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
4606 | goto target_done; | ||
4607 | |||
4608 | if ((!dv.now.width) && (!dv.now.offset)) | ||
4609 | goto target_done; | ||
4610 | |||
4611 | iocmd.cmd = INQUIRY; | ||
4612 | iocmd.data_dma = buf2_dma; | ||
4613 | iocmd.data = pbuf2; | ||
4614 | iocmd.size = sz; | ||
4615 | memset(pbuf2, 0x00, sz); | ||
4616 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4617 | goto target_done; | ||
4618 | else if (hd->pLocal == NULL) | ||
4619 | goto target_done; | ||
4620 | else { | ||
4621 | /* Save the return code. | ||
4622 | * If this is the first pass, | ||
4623 | * read SCSI Device Page 0 | ||
4624 | * and update the target max parameters. | ||
4625 | */ | ||
4626 | rc = hd->pLocal->completion; | ||
4627 | doFallback = 0; | ||
4628 | if (rc == MPT_SCANDV_GOOD) { | ||
4629 | if (!readPage0) { | ||
4630 | u32 sdp0_info; | ||
4631 | u32 sdp0_nego; | ||
4632 | |||
4633 | cfg.cfghdr.hdr = &header0; | ||
4634 | cfg.physAddr = cfg0_dma_addr; | ||
4635 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
4636 | cfg.dir = 0; | ||
4637 | |||
4638 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
4639 | goto target_done; | ||
4640 | |||
4641 | sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E; | ||
4642 | sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8; | ||
4643 | |||
4644 | /* Quantum and Fujitsu workarounds. | ||
4645 | * Quantum: PPR U320 -> PPR reply with Ultra2 and wide | ||
4646 | * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide | ||
4647 | * Resetart with a request for U160. | ||
4648 | */ | ||
4649 | if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) { | ||
4650 | doFallback = 1; | ||
4651 | } else { | ||
4652 | dv.cmd = MPT_UPDATE_MAX; | ||
4653 | mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data); | ||
4654 | /* Update the SCSI device page 1 area | ||
4655 | */ | ||
4656 | pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters; | ||
4657 | readPage0 = 1; | ||
4658 | } | ||
4659 | } | ||
4660 | |||
4661 | /* Quantum workaround. Restart this test will the fallback | ||
4662 | * flag set. | ||
4663 | */ | ||
4664 | if (doFallback == 0) { | ||
4665 | if (memcmp(pbuf1, pbuf2, sz) != 0) { | ||
4666 | if (!firstPass) | ||
4667 | doFallback = 1; | ||
4668 | } else { | ||
4669 | ddvprintk((MYIOC_s_NOTE_FMT | ||
4670 | "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id)); | ||
4671 | hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE; | ||
4672 | mptscsih_initTarget(hd, | ||
4673 | vtarget, | ||
4674 | lun, | ||
4675 | pbuf1, | ||
4676 | sz); | ||
4677 | break; /* test complete */ | ||
4678 | } | ||
4679 | } | ||
4680 | |||
4681 | |||
4682 | } else if (rc == MPT_SCANDV_ISSUE_SENSE) | ||
4683 | doFallback = 1; /* set fallback flag */ | ||
4684 | else if ((rc == MPT_SCANDV_DID_RESET) || | ||
4685 | (rc == MPT_SCANDV_SENSE) || | ||
4686 | (rc == MPT_SCANDV_FALLBACK)) | ||
4687 | doFallback = 1; /* set fallback flag */ | ||
4688 | else | ||
4689 | goto target_done; | ||
4690 | |||
4691 | firstPass = 0; | ||
4692 | } | ||
4693 | } | ||
4694 | ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id)); | ||
4695 | |||
4696 | if (ioc->spi_data.mpt_dv == 0) | ||
4697 | goto target_done; | ||
4698 | |||
4699 | inq0 = (*pbuf1) & 0x1F; | ||
4700 | |||
4701 | /* Continue only for disks | ||
4702 | */ | ||
4703 | if (inq0 != 0) | ||
4704 | goto target_done; | ||
4705 | |||
4706 | if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY ) | ||
4707 | goto target_done; | ||
4708 | |||
4709 | /* Start the Enhanced Test. | ||
4710 | * 0) issue TUR to clear out check conditions | ||
4711 | * 1) read capacity of echo (regular) buffer | ||
4712 | * 2) reserve device | ||
4713 | * 3) do write-read-compare data pattern test | ||
4714 | * 4) release | ||
4715 | * 5) update nego parms to target struct | ||
4716 | */ | ||
4717 | cfg.cfghdr.hdr = &header1; | ||
4718 | cfg.physAddr = cfg1_dma_addr; | ||
4719 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
4720 | cfg.dir = 1; | ||
4721 | |||
4722 | iocmd.cmd = TEST_UNIT_READY; | ||
4723 | iocmd.data_dma = -1; | ||
4724 | iocmd.data = NULL; | ||
4725 | iocmd.size = 0; | ||
4726 | notDone = 1; | ||
4727 | while (notDone) { | ||
4728 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4729 | goto target_done; | ||
4730 | |||
4731 | if (hd->pLocal == NULL) | ||
4732 | goto target_done; | ||
4733 | |||
4734 | rc = hd->pLocal->completion; | ||
4735 | if (rc == MPT_SCANDV_GOOD) | ||
4736 | notDone = 0; | ||
4737 | else if (rc == MPT_SCANDV_SENSE) { | ||
4738 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
4739 | u8 asc = hd->pLocal->sense[12]; | ||
4740 | u8 ascq = hd->pLocal->sense[13]; | ||
4741 | ddvprintk((MYIOC_s_INFO_FMT | ||
4742 | "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", | ||
4743 | ioc->name, skey, asc, ascq)); | ||
4744 | |||
4745 | if (skey == UNIT_ATTENTION) | ||
4746 | notDone++; /* repeat */ | ||
4747 | else if ((skey == NOT_READY) && | ||
4748 | (asc == 0x04)&&(ascq == 0x01)) { | ||
4749 | /* wait then repeat */ | ||
4750 | mdelay (2000); | ||
4751 | notDone++; | ||
4752 | } else if ((skey == NOT_READY) && (asc == 0x3A)) { | ||
4753 | /* no medium, try read test anyway */ | ||
4754 | notDone = 0; | ||
4755 | } else { | ||
4756 | /* All other errors are fatal. | ||
4757 | */ | ||
4758 | ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.", | ||
4759 | ioc->name)); | ||
4760 | goto target_done; | ||
4761 | } | ||
4762 | } else | ||
4763 | goto target_done; | ||
4764 | } | ||
4765 | |||
4766 | iocmd.cmd = READ_BUFFER; | ||
4767 | iocmd.data_dma = buf1_dma; | ||
4768 | iocmd.data = pbuf1; | ||
4769 | iocmd.size = 4; | ||
4770 | iocmd.flags |= MPT_ICFLAG_BUF_CAP; | ||
4771 | |||
4772 | dataBufSize = 0; | ||
4773 | echoBufSize = 0; | ||
4774 | for (patt = 0; patt < 2; patt++) { | ||
4775 | if (patt == 0) | ||
4776 | iocmd.flags |= MPT_ICFLAG_ECHO; | ||
4777 | else | ||
4778 | iocmd.flags &= ~MPT_ICFLAG_ECHO; | ||
4779 | |||
4780 | notDone = 1; | ||
4781 | while (notDone) { | ||
4782 | bufsize = 0; | ||
4783 | |||
4784 | /* If not ready after 8 trials, | ||
4785 | * give up on this device. | ||
4786 | */ | ||
4787 | if (notDone > 8) | ||
4788 | goto target_done; | ||
4789 | |||
4790 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4791 | goto target_done; | ||
4792 | else if (hd->pLocal == NULL) | ||
4793 | goto target_done; | ||
4794 | else { | ||
4795 | rc = hd->pLocal->completion; | ||
4796 | ddvprintk(("ReadBuffer Comp Code %d", rc)); | ||
4797 | ddvprintk((" buff: %0x %0x %0x %0x\n", | ||
4798 | pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3])); | ||
4799 | |||
4800 | if (rc == MPT_SCANDV_GOOD) { | ||
4801 | notDone = 0; | ||
4802 | if (iocmd.flags & MPT_ICFLAG_ECHO) { | ||
4803 | bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3]; | ||
4804 | if (pbuf1[0] & 0x01) | ||
4805 | iocmd.flags |= MPT_ICFLAG_EBOS; | ||
4806 | } else { | ||
4807 | bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3]; | ||
4808 | } | ||
4809 | } else if (rc == MPT_SCANDV_SENSE) { | ||
4810 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
4811 | u8 asc = hd->pLocal->sense[12]; | ||
4812 | u8 ascq = hd->pLocal->sense[13]; | ||
4813 | ddvprintk((MYIOC_s_INFO_FMT | ||
4814 | "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", | ||
4815 | ioc->name, skey, asc, ascq)); | ||
4816 | if (skey == ILLEGAL_REQUEST) { | ||
4817 | notDone = 0; | ||
4818 | } else if (skey == UNIT_ATTENTION) { | ||
4819 | notDone++; /* repeat */ | ||
4820 | } else if ((skey == NOT_READY) && | ||
4821 | (asc == 0x04)&&(ascq == 0x01)) { | ||
4822 | /* wait then repeat */ | ||
4823 | mdelay (2000); | ||
4824 | notDone++; | ||
4825 | } else { | ||
4826 | /* All other errors are fatal. | ||
4827 | */ | ||
4828 | ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.", | ||
4829 | ioc->name)); | ||
4830 | goto target_done; | ||
4831 | } | ||
4832 | } else { | ||
4833 | /* All other errors are fatal | ||
4834 | */ | ||
4835 | goto target_done; | ||
4836 | } | ||
4837 | } | ||
4838 | } | ||
4839 | |||
4840 | if (iocmd.flags & MPT_ICFLAG_ECHO) | ||
4841 | echoBufSize = bufsize; | ||
4842 | else | ||
4843 | dataBufSize = bufsize; | ||
4844 | } | ||
4845 | sz = 0; | ||
4846 | iocmd.flags &= ~MPT_ICFLAG_BUF_CAP; | ||
4847 | |||
4848 | /* Use echo buffers if possible, | ||
4849 | * Exit if both buffers are 0. | ||
4850 | */ | ||
4851 | if (echoBufSize > 0) { | ||
4852 | iocmd.flags |= MPT_ICFLAG_ECHO; | ||
4853 | if (dataBufSize > 0) | ||
4854 | bufsize = min(echoBufSize, dataBufSize); | ||
4855 | else | ||
4856 | bufsize = echoBufSize; | ||
4857 | } else if (dataBufSize == 0) | ||
4858 | goto target_done; | ||
4859 | |||
4860 | ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name, | ||
4861 | (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize)); | ||
4862 | |||
4863 | /* Data buffers for write-read-compare test max 1K. | ||
4864 | */ | ||
4865 | sz = min(bufsize, 1024); | ||
4866 | |||
4867 | /* --- loop ---- | ||
4868 | * On first pass, always issue a reserve. | ||
4869 | * On additional loops, only if a reset has occurred. | ||
4870 | * iocmd.flags indicates if echo or regular buffer | ||
4871 | */ | ||
4872 | for (patt = 0; patt < 4; patt++) { | ||
4873 | ddvprintk(("Pattern %d\n", patt)); | ||
4874 | if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) { | ||
4875 | iocmd.cmd = TEST_UNIT_READY; | ||
4876 | iocmd.data_dma = -1; | ||
4877 | iocmd.data = NULL; | ||
4878 | iocmd.size = 0; | ||
4879 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4880 | goto target_done; | ||
4881 | |||
4882 | iocmd.cmd = RELEASE; | ||
4883 | iocmd.data_dma = -1; | ||
4884 | iocmd.data = NULL; | ||
4885 | iocmd.size = 0; | ||
4886 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4887 | goto target_done; | ||
4888 | else if (hd->pLocal == NULL) | ||
4889 | goto target_done; | ||
4890 | else { | ||
4891 | rc = hd->pLocal->completion; | ||
4892 | ddvprintk(("Release rc %d\n", rc)); | ||
4893 | if (rc == MPT_SCANDV_GOOD) | ||
4894 | iocmd.flags &= ~MPT_ICFLAG_RESERVED; | ||
4895 | else | ||
4896 | goto target_done; | ||
4897 | } | ||
4898 | iocmd.flags &= ~MPT_ICFLAG_RESERVED; | ||
4899 | } | ||
4900 | iocmd.flags &= ~MPT_ICFLAG_DID_RESET; | ||
4901 | |||
4902 | if (iocmd.flags & MPT_ICFLAG_EBOS) | ||
4903 | goto skip_Reserve; | ||
4904 | |||
4905 | repeat = 5; | ||
4906 | while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) { | ||
4907 | iocmd.cmd = RESERVE; | ||
4908 | iocmd.data_dma = -1; | ||
4909 | iocmd.data = NULL; | ||
4910 | iocmd.size = 0; | ||
4911 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4912 | goto target_done; | ||
4913 | else if (hd->pLocal == NULL) | ||
4914 | goto target_done; | ||
4915 | else { | ||
4916 | rc = hd->pLocal->completion; | ||
4917 | if (rc == MPT_SCANDV_GOOD) { | ||
4918 | iocmd.flags |= MPT_ICFLAG_RESERVED; | ||
4919 | } else if (rc == MPT_SCANDV_SENSE) { | ||
4920 | /* Wait if coming ready | ||
4921 | */ | ||
4922 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
4923 | u8 asc = hd->pLocal->sense[12]; | ||
4924 | u8 ascq = hd->pLocal->sense[13]; | ||
4925 | ddvprintk((MYIOC_s_INFO_FMT | ||
4926 | "DV: Reserve Failed: ", ioc->name)); | ||
4927 | ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", | ||
4928 | skey, asc, ascq)); | ||
4929 | |||
4930 | if ((skey == NOT_READY) && (asc == 0x04)&& | ||
4931 | (ascq == 0x01)) { | ||
4932 | /* wait then repeat */ | ||
4933 | mdelay (2000); | ||
4934 | notDone++; | ||
4935 | } else { | ||
4936 | ddvprintk((MYIOC_s_INFO_FMT | ||
4937 | "DV: Reserved Failed.", ioc->name)); | ||
4938 | goto target_done; | ||
4939 | } | ||
4940 | } else { | ||
4941 | ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.", | ||
4942 | ioc->name)); | ||
4943 | goto target_done; | ||
4944 | } | ||
4945 | } | ||
4946 | } | ||
4947 | |||
4948 | skip_Reserve: | ||
4949 | mptscsih_fillbuf(pbuf1, sz, patt, 1); | ||
4950 | iocmd.cmd = WRITE_BUFFER; | ||
4951 | iocmd.data_dma = buf1_dma; | ||
4952 | iocmd.data = pbuf1; | ||
4953 | iocmd.size = sz; | ||
4954 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
4955 | goto target_done; | ||
4956 | else if (hd->pLocal == NULL) | ||
4957 | goto target_done; | ||
4958 | else { | ||
4959 | rc = hd->pLocal->completion; | ||
4960 | if (rc == MPT_SCANDV_GOOD) | ||
4961 | ; /* Issue read buffer */ | ||
4962 | else if (rc == MPT_SCANDV_DID_RESET) { | ||
4963 | /* If using echo buffers, reset to data buffers. | ||
4964 | * Else do Fallback and restart | ||
4965 | * this test (re-issue reserve | ||
4966 | * because of bus reset). | ||
4967 | */ | ||
4968 | if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) { | ||
4969 | iocmd.flags &= ~MPT_ICFLAG_ECHO; | ||
4970 | } else { | ||
4971 | dv.cmd = MPT_FALLBACK; | ||
4972 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
4973 | |||
4974 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
4975 | goto target_done; | ||
4976 | |||
4977 | if ((!dv.now.width) && (!dv.now.offset)) | ||
4978 | goto target_done; | ||
4979 | } | ||
4980 | |||
4981 | iocmd.flags |= MPT_ICFLAG_DID_RESET; | ||
4982 | patt = -1; | ||
4983 | continue; | ||
4984 | } else if (rc == MPT_SCANDV_SENSE) { | ||
4985 | /* Restart data test if UA, else quit. | ||
4986 | */ | ||
4987 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
4988 | ddvprintk((MYIOC_s_INFO_FMT | ||
4989 | "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, | ||
4990 | hd->pLocal->sense[12], hd->pLocal->sense[13])); | ||
4991 | if (skey == UNIT_ATTENTION) { | ||
4992 | patt = -1; | ||
4993 | continue; | ||
4994 | } else if (skey == ILLEGAL_REQUEST) { | ||
4995 | if (iocmd.flags & MPT_ICFLAG_ECHO) { | ||
4996 | if (dataBufSize >= bufsize) { | ||
4997 | iocmd.flags &= ~MPT_ICFLAG_ECHO; | ||
4998 | patt = -1; | ||
4999 | continue; | ||
5000 | } | ||
5001 | } | ||
5002 | goto target_done; | ||
5003 | } | ||
5004 | else | ||
5005 | goto target_done; | ||
5006 | } else { | ||
5007 | /* fatal error */ | ||
5008 | goto target_done; | ||
5009 | } | ||
5010 | } | ||
5011 | |||
5012 | iocmd.cmd = READ_BUFFER; | ||
5013 | iocmd.data_dma = buf2_dma; | ||
5014 | iocmd.data = pbuf2; | ||
5015 | iocmd.size = sz; | ||
5016 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
5017 | goto target_done; | ||
5018 | else if (hd->pLocal == NULL) | ||
5019 | goto target_done; | ||
5020 | else { | ||
5021 | rc = hd->pLocal->completion; | ||
5022 | if (rc == MPT_SCANDV_GOOD) { | ||
5023 | /* If buffers compare, | ||
5024 | * go to next pattern, | ||
5025 | * else, do a fallback and restart | ||
5026 | * data transfer test. | ||
5027 | */ | ||
5028 | if (memcmp (pbuf1, pbuf2, sz) == 0) { | ||
5029 | ; /* goto next pattern */ | ||
5030 | } else { | ||
5031 | /* Miscompare with Echo buffer, go to data buffer, | ||
5032 | * if that buffer exists. | ||
5033 | * Miscompare with Data buffer, check first 4 bytes, | ||
5034 | * some devices return capacity. Exit in this case. | ||
5035 | */ | ||
5036 | if (iocmd.flags & MPT_ICFLAG_ECHO) { | ||
5037 | if (dataBufSize >= bufsize) | ||
5038 | iocmd.flags &= ~MPT_ICFLAG_ECHO; | ||
5039 | else | ||
5040 | goto target_done; | ||
5041 | } else { | ||
5042 | if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) { | ||
5043 | /* Argh. Device returning wrong data. | ||
5044 | * Quit DV for this device. | ||
5045 | */ | ||
5046 | goto target_done; | ||
5047 | } | ||
5048 | |||
5049 | /* Had an actual miscompare. Slow down.*/ | ||
5050 | dv.cmd = MPT_FALLBACK; | ||
5051 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
5052 | |||
5053 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
5054 | goto target_done; | ||
5055 | |||
5056 | if ((!dv.now.width) && (!dv.now.offset)) | ||
5057 | goto target_done; | ||
5058 | } | ||
5059 | |||
5060 | patt = -1; | ||
5061 | continue; | ||
5062 | } | ||
5063 | } else if (rc == MPT_SCANDV_DID_RESET) { | ||
5064 | /* Do Fallback and restart | ||
5065 | * this test (re-issue reserve | ||
5066 | * because of bus reset). | ||
5067 | */ | ||
5068 | dv.cmd = MPT_FALLBACK; | ||
5069 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
5070 | |||
5071 | if (mpt_config(hd->ioc, &cfg) != 0) | ||
5072 | goto target_done; | ||
5073 | |||
5074 | if ((!dv.now.width) && (!dv.now.offset)) | ||
5075 | goto target_done; | ||
5076 | |||
5077 | iocmd.flags |= MPT_ICFLAG_DID_RESET; | ||
5078 | patt = -1; | ||
5079 | continue; | ||
5080 | } else if (rc == MPT_SCANDV_SENSE) { | ||
5081 | /* Restart data test if UA, else quit. | ||
5082 | */ | ||
5083 | u8 skey = hd->pLocal->sense[2] & 0x0F; | ||
5084 | ddvprintk((MYIOC_s_INFO_FMT | ||
5085 | "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, | ||
5086 | hd->pLocal->sense[12], hd->pLocal->sense[13])); | ||
5087 | if (skey == UNIT_ATTENTION) { | ||
5088 | patt = -1; | ||
5089 | continue; | ||
5090 | } | ||
5091 | else | ||
5092 | goto target_done; | ||
5093 | } else { | ||
5094 | /* fatal error */ | ||
5095 | goto target_done; | ||
5096 | } | ||
5097 | } | ||
5098 | |||
5099 | } /* --- end of patt loop ---- */ | ||
5100 | |||
5101 | target_done: | ||
5102 | if (iocmd.flags & MPT_ICFLAG_RESERVED) { | ||
5103 | iocmd.cmd = RELEASE; | ||
5104 | iocmd.data_dma = -1; | ||
5105 | iocmd.data = NULL; | ||
5106 | iocmd.size = 0; | ||
5107 | if (mptscsih_do_cmd(hd, &iocmd) < 0) | ||
5108 | printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d", | ||
5109 | ioc->name, id); | ||
5110 | else if (hd->pLocal) { | ||
5111 | if (hd->pLocal->completion == MPT_SCANDV_GOOD) | ||
5112 | iocmd.flags &= ~MPT_ICFLAG_RESERVED; | ||
5113 | } else { | ||
5114 | printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d", | ||
5115 | ioc->name, id); | ||
5116 | } | ||
5117 | } | ||
5118 | |||
5119 | |||
5120 | /* Set if cfg1_dma_addr contents is valid | ||
5121 | */ | ||
5122 | if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){ | ||
5123 | /* If disk, not U320, disable QAS | ||
5124 | */ | ||
5125 | if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) { | ||
5126 | hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; | ||
5127 | ddvprintk((MYIOC_s_NOTE_FMT | ||
5128 | "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor)); | ||
5129 | } | ||
5130 | |||
5131 | dv.cmd = MPT_SAVE; | ||
5132 | mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); | ||
5133 | |||
5134 | /* Double writes to SDP1 can cause problems, | ||
5135 | * skip save of the final negotiated settings to | ||
5136 | * SCSI device page 1. | ||
5137 | * | ||
5138 | cfg.cfghdr.hdr = &header1; | ||
5139 | cfg.physAddr = cfg1_dma_addr; | ||
5140 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
5141 | cfg.dir = 1; | ||
5142 | mpt_config(hd->ioc, &cfg); | ||
5143 | */ | ||
5144 | } | ||
5145 | |||
5146 | /* If this is a RAID Passthrough, enable internal IOs | ||
5147 | */ | ||
5148 | if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) { | ||
5149 | if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0) | ||
5150 | ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name)); | ||
5151 | } | ||
5152 | |||
5153 | /* Done with the DV scan of the current target | ||
5154 | */ | ||
5155 | if (pDvBuf) | ||
5156 | pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma); | ||
5157 | |||
5158 | ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n", | ||
5159 | ioc->name, id)); | ||
5160 | |||
5161 | return retcode; | ||
5162 | } | ||
5163 | |||
5164 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
5165 | /* mptscsih_dv_parms - perform a variety of operations on the | ||
5166 | * parameters used for negotiation. | ||
5167 | * @hd: Pointer to a SCSI host. | ||
5168 | * @dv: Pointer to a structure that contains the maximum and current | ||
5169 | * negotiated parameters. | ||
5170 | */ | ||
5171 | static void | ||
5172 | mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) | ||
5173 | { | ||
5174 | VirtTarget *vtarget; | ||
5175 | SCSIDevicePage0_t *pPage0; | ||
5176 | SCSIDevicePage1_t *pPage1; | ||
5177 | int val = 0, data, configuration; | ||
5178 | u8 width = 0; | ||
5179 | u8 offset = 0; | ||
5180 | u8 factor = 0; | ||
5181 | u8 negoFlags = 0; | ||
5182 | u8 cmd = dv->cmd; | ||
5183 | u8 id = dv->id; | ||
5184 | |||
5185 | switch (cmd) { | ||
5186 | case MPT_GET_NVRAM_VALS: | ||
5187 | ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ", | ||
5188 | hd->ioc->name)); | ||
5189 | /* Get the NVRAM values and save in tmax | ||
5190 | * If not an LVD bus, the adapter minSyncFactor has been | ||
5191 | * already throttled back. | ||
5192 | */ | ||
5193 | negoFlags = hd->ioc->spi_data.noQas; | ||
5194 | if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) { | ||
5195 | width = vtarget->maxWidth; | ||
5196 | offset = vtarget->maxOffset; | ||
5197 | factor = vtarget->minSyncFactor; | ||
5198 | negoFlags |= vtarget->negoFlags; | ||
5199 | } else { | ||
5200 | if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { | ||
5201 | data = hd->ioc->spi_data.nvram[id]; | ||
5202 | width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; | ||
5203 | if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0) | ||
5204 | factor = MPT_ASYNC; | ||
5205 | else { | ||
5206 | factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; | ||
5207 | if ((factor == 0) || (factor == MPT_ASYNC)){ | ||
5208 | factor = MPT_ASYNC; | ||
5209 | offset = 0; | ||
5210 | } | ||
5211 | } | ||
5212 | } else { | ||
5213 | width = MPT_NARROW; | ||
5214 | offset = 0; | ||
5215 | factor = MPT_ASYNC; | ||
5216 | } | ||
5217 | |||
5218 | /* Set the negotiation flags */ | ||
5219 | if (!width) | ||
5220 | negoFlags |= MPT_TARGET_NO_NEGO_WIDE; | ||
5221 | |||
5222 | if (!offset) | ||
5223 | negoFlags |= MPT_TARGET_NO_NEGO_SYNC; | ||
5224 | } | ||
5225 | |||
5226 | /* limit by adapter capabilities */ | ||
5227 | width = min(width, hd->ioc->spi_data.maxBusWidth); | ||
5228 | offset = min(offset, hd->ioc->spi_data.maxSyncOffset); | ||
5229 | factor = max(factor, hd->ioc->spi_data.minSyncFactor); | ||
5230 | |||
5231 | /* Check Consistency */ | ||
5232 | if (offset && (factor < MPT_ULTRA2) && !width) | ||
5233 | factor = MPT_ULTRA2; | ||
5234 | |||
5235 | dv->max.width = width; | ||
5236 | dv->max.offset = offset; | ||
5237 | dv->max.factor = factor; | ||
5238 | dv->max.flags = negoFlags; | ||
5239 | ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n", | ||
5240 | id, width, factor, offset, negoFlags)); | ||
5241 | break; | ||
5242 | |||
5243 | case MPT_UPDATE_MAX: | ||
5244 | ddvprintk((MYIOC_s_NOTE_FMT | ||
5245 | "Updating with SDP0 Data: ", hd->ioc->name)); | ||
5246 | /* Update tmax values with those from Device Page 0.*/ | ||
5247 | pPage0 = (SCSIDevicePage0_t *) pPage; | ||
5248 | if (pPage0) { | ||
5249 | val = le32_to_cpu(pPage0->NegotiatedParameters); | ||
5250 | dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0; | ||
5251 | dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16; | ||
5252 | dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8; | ||
5253 | } | ||
5254 | |||
5255 | dv->now.width = dv->max.width; | ||
5256 | dv->now.offset = dv->max.offset; | ||
5257 | dv->now.factor = dv->max.factor; | ||
5258 | ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n", | ||
5259 | id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); | ||
5260 | break; | ||
5261 | |||
5262 | case MPT_SET_MAX: | ||
5263 | ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ", | ||
5264 | hd->ioc->name)); | ||
5265 | /* Set current to the max values. Update the config page.*/ | ||
5266 | dv->now.width = dv->max.width; | ||
5267 | dv->now.offset = dv->max.offset; | ||
5268 | dv->now.factor = dv->max.factor; | ||
5269 | dv->now.flags = dv->max.flags; | ||
5270 | |||
5271 | pPage1 = (SCSIDevicePage1_t *)pPage; | ||
5272 | if (pPage1) { | ||
5273 | mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor, | ||
5274 | dv->now.offset, &val, &configuration, dv->now.flags); | ||
5275 | dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", | ||
5276 | id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); | ||
5277 | pPage1->RequestedParameters = cpu_to_le32(val); | ||
5278 | pPage1->Reserved = 0; | ||
5279 | pPage1->Configuration = cpu_to_le32(configuration); | ||
5280 | } | ||
5281 | |||
5282 | ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n", | ||
5283 | id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); | ||
5284 | break; | ||
5285 | |||
5286 | case MPT_SET_MIN: | ||
5287 | ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ", | ||
5288 | hd->ioc->name)); | ||
5289 | /* Set page to asynchronous and narrow | ||
5290 | * Do not update now, breaks fallback routine. */ | ||
5291 | width = MPT_NARROW; | ||
5292 | offset = 0; | ||
5293 | factor = MPT_ASYNC; | ||
5294 | negoFlags = dv->max.flags; | ||
5295 | |||
5296 | pPage1 = (SCSIDevicePage1_t *)pPage; | ||
5297 | if (pPage1) { | ||
5298 | mptscsih_setDevicePage1Flags (width, factor, | ||
5299 | offset, &val, &configuration, negoFlags); | ||
5300 | dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", | ||
5301 | id, width, factor, offset, negoFlags, val, configuration)); | ||
5302 | pPage1->RequestedParameters = cpu_to_le32(val); | ||
5303 | pPage1->Reserved = 0; | ||
5304 | pPage1->Configuration = cpu_to_le32(configuration); | ||
5305 | } | ||
5306 | ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n", | ||
5307 | id, width, factor, offset, val, configuration, negoFlags)); | ||
5308 | break; | ||
5309 | |||
5310 | case MPT_FALLBACK: | ||
5311 | ddvprintk((MYIOC_s_NOTE_FMT | ||
5312 | "Fallback: Start: offset %d, factor %x, width %d \n", | ||
5313 | hd->ioc->name, dv->now.offset, | ||
5314 | dv->now.factor, dv->now.width)); | ||
5315 | width = dv->now.width; | ||
5316 | offset = dv->now.offset; | ||
5317 | factor = dv->now.factor; | ||
5318 | if ((offset) && (dv->max.width)) { | ||
5319 | if (factor < MPT_ULTRA160) | ||
5320 | factor = MPT_ULTRA160; | ||
5321 | else if (factor < MPT_ULTRA2) { | ||
5322 | factor = MPT_ULTRA2; | ||
5323 | width = MPT_WIDE; | ||
5324 | } else if ((factor == MPT_ULTRA2) && width) { | ||
5325 | factor = MPT_ULTRA2; | ||
5326 | width = MPT_NARROW; | ||
5327 | } else if (factor < MPT_ULTRA) { | ||
5328 | factor = MPT_ULTRA; | ||
5329 | width = MPT_WIDE; | ||
5330 | } else if ((factor == MPT_ULTRA) && width) { | ||
5331 | width = MPT_NARROW; | ||
5332 | } else if (factor < MPT_FAST) { | ||
5333 | factor = MPT_FAST; | ||
5334 | width = MPT_WIDE; | ||
5335 | } else if ((factor == MPT_FAST) && width) { | ||
5336 | factor = MPT_FAST; | ||
5337 | width = MPT_NARROW; | ||
5338 | } else if (factor < MPT_SCSI) { | ||
5339 | factor = MPT_SCSI; | ||
5340 | width = MPT_WIDE; | ||
5341 | } else if ((factor == MPT_SCSI) && width) { | ||
5342 | factor = MPT_SCSI; | ||
5343 | width = MPT_NARROW; | ||
5344 | } else { | ||
5345 | factor = MPT_ASYNC; | ||
5346 | offset = 0; | ||
5347 | } | ||
5348 | |||
5349 | } else if (offset) { | ||
5350 | width = MPT_NARROW; | ||
5351 | if (factor < MPT_ULTRA) | ||
5352 | factor = MPT_ULTRA; | ||
5353 | else if (factor < MPT_FAST) | ||
5354 | factor = MPT_FAST; | ||
5355 | else if (factor < MPT_SCSI) | ||
5356 | factor = MPT_SCSI; | ||
5357 | else { | ||
5358 | factor = MPT_ASYNC; | ||
5359 | offset = 0; | ||
5360 | } | ||
5361 | |||
5362 | } else { | ||
5363 | width = MPT_NARROW; | ||
5364 | factor = MPT_ASYNC; | ||
5365 | } | ||
5366 | dv->max.flags |= MPT_TARGET_NO_NEGO_QAS; | ||
5367 | dv->max.flags &= ~MPT_TAPE_NEGO_IDP; | ||
5368 | |||
5369 | dv->now.width = width; | ||
5370 | dv->now.offset = offset; | ||
5371 | dv->now.factor = factor; | ||
5372 | dv->now.flags = dv->max.flags; | ||
5373 | |||
5374 | pPage1 = (SCSIDevicePage1_t *)pPage; | ||
5375 | if (pPage1) { | ||
5376 | mptscsih_setDevicePage1Flags (width, factor, offset, &val, | ||
5377 | &configuration, dv->now.flags); | ||
5378 | dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n", | ||
5379 | id, width, offset, factor, dv->now.flags, val, configuration)); | ||
5380 | |||
5381 | pPage1->RequestedParameters = cpu_to_le32(val); | ||
5382 | pPage1->Reserved = 0; | ||
5383 | pPage1->Configuration = cpu_to_le32(configuration); | ||
5384 | } | ||
5385 | |||
5386 | ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n", | ||
5387 | id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration)); | ||
5388 | break; | ||
5389 | |||
5390 | case MPT_SAVE: | ||
5391 | ddvprintk((MYIOC_s_NOTE_FMT | ||
5392 | "Saving to Target structure: ", hd->ioc->name)); | ||
5393 | ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n", | ||
5394 | id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); | ||
5395 | |||
5396 | /* Save these values to target structures | ||
5397 | * or overwrite nvram (phys disks only). | ||
5398 | */ | ||
5399 | |||
5400 | if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) { | ||
5401 | vtarget->maxWidth = dv->now.width; | ||
5402 | vtarget->maxOffset = dv->now.offset; | ||
5403 | vtarget->minSyncFactor = dv->now.factor; | ||
5404 | vtarget->negoFlags = dv->now.flags; | ||
5405 | } else { | ||
5406 | /* Preserv all flags, use | ||
5407 | * read-modify-write algorithm | ||
5408 | */ | ||
5409 | if (hd->ioc->spi_data.nvram) { | ||
5410 | data = hd->ioc->spi_data.nvram[id]; | ||
5411 | |||
5412 | if (dv->now.width) | ||
5413 | data &= ~MPT_NVRAM_WIDE_DISABLE; | ||
5414 | else | ||
5415 | data |= MPT_NVRAM_WIDE_DISABLE; | ||
5416 | |||
5417 | if (!dv->now.offset) | ||
5418 | factor = MPT_ASYNC; | ||
5419 | |||
5420 | data &= ~MPT_NVRAM_SYNC_MASK; | ||
5421 | data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK; | ||
5422 | |||
5423 | hd->ioc->spi_data.nvram[id] = data; | ||
5424 | } | ||
5425 | } | ||
5426 | break; | ||
5427 | } | ||
5428 | } | ||
5429 | |||
5430 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
5431 | /* mptscsih_fillbuf - fill a buffer with a special data pattern | ||
5432 | * cleanup. For bus scan only. | ||
5433 | * | ||
5434 | * @buffer: Pointer to data buffer to be filled. | ||
5435 | * @size: Number of bytes to fill | ||
5436 | * @index: Pattern index | ||
5437 | * @width: bus width, 0 (8 bits) or 1 (16 bits) | ||
5438 | */ | ||
5439 | static void | ||
5440 | mptscsih_fillbuf(char *buffer, int size, int index, int width) | ||
5441 | { | ||
5442 | char *ptr = buffer; | ||
5443 | int ii; | ||
5444 | char byte; | ||
5445 | short val; | ||
5446 | |||
5447 | switch (index) { | ||
5448 | case 0: | ||
5449 | |||
5450 | if (width) { | ||
5451 | /* Pattern: 0000 FFFF 0000 FFFF | ||
5452 | */ | ||
5453 | for (ii=0; ii < size; ii++, ptr++) { | ||
5454 | if (ii & 0x02) | ||
5455 | *ptr = 0xFF; | ||
5456 | else | ||
5457 | *ptr = 0x00; | ||
5458 | } | ||
5459 | } else { | ||
5460 | /* Pattern: 00 FF 00 FF | ||
5461 | */ | ||
5462 | for (ii=0; ii < size; ii++, ptr++) { | ||
5463 | if (ii & 0x01) | ||
5464 | *ptr = 0xFF; | ||
5465 | else | ||
5466 | *ptr = 0x00; | ||
5467 | } | ||
5468 | } | ||
5469 | break; | ||
5470 | |||
5471 | case 1: | ||
5472 | if (width) { | ||
5473 | /* Pattern: 5555 AAAA 5555 AAAA 5555 | ||
5474 | */ | ||
5475 | for (ii=0; ii < size; ii++, ptr++) { | ||
5476 | if (ii & 0x02) | ||
5477 | *ptr = 0xAA; | ||
5478 | else | ||
5479 | *ptr = 0x55; | ||
5480 | } | ||
5481 | } else { | ||
5482 | /* Pattern: 55 AA 55 AA 55 | ||
5483 | */ | ||
5484 | for (ii=0; ii < size; ii++, ptr++) { | ||
5485 | if (ii & 0x01) | ||
5486 | *ptr = 0xAA; | ||
5487 | else | ||
5488 | *ptr = 0x55; | ||
5489 | } | ||
5490 | } | ||
5491 | break; | ||
5492 | |||
5493 | case 2: | ||
5494 | /* Pattern: 00 01 02 03 04 05 | ||
5495 | * ... FE FF 00 01.. | ||
5496 | */ | ||
5497 | for (ii=0; ii < size; ii++, ptr++) | ||
5498 | *ptr = (char) ii; | ||
5499 | break; | ||
5500 | |||
5501 | case 3: | ||
5502 | if (width) { | ||
5503 | /* Wide Pattern: FFFE 0001 FFFD 0002 | ||
5504 | * ... 4000 DFFF 8000 EFFF | ||
5505 | */ | ||
5506 | byte = 0; | ||
5507 | for (ii=0; ii < size/2; ii++) { | ||
5508 | /* Create the base pattern | ||
5509 | */ | ||
5510 | val = (1 << byte); | ||
5511 | /* every 64 (0x40) bytes flip the pattern | ||
5512 | * since we fill 2 bytes / iteration, | ||
5513 | * test for ii = 0x20 | ||
5514 | */ | ||
5515 | if (ii & 0x20) | ||
5516 | val = ~(val); | ||
5517 | |||
5518 | if (ii & 0x01) { | ||
5519 | *ptr = (char)( (val & 0xFF00) >> 8); | ||
5520 | ptr++; | ||
5521 | *ptr = (char)(val & 0xFF); | ||
5522 | byte++; | ||
5523 | byte &= 0x0F; | ||
5524 | } else { | ||
5525 | val = ~val; | ||
5526 | *ptr = (char)( (val & 0xFF00) >> 8); | ||
5527 | ptr++; | ||
5528 | *ptr = (char)(val & 0xFF); | ||
5529 | } | ||
5530 | |||
5531 | ptr++; | ||
5532 | } | ||
5533 | } else { | ||
5534 | /* Narrow Pattern: FE 01 FD 02 FB 04 | ||
5535 | * .. 7F 80 01 FE 02 FD ... 80 7F | ||
5536 | */ | ||
5537 | byte = 0; | ||
5538 | for (ii=0; ii < size; ii++, ptr++) { | ||
5539 | /* Base pattern - first 32 bytes | ||
5540 | */ | ||
5541 | if (ii & 0x01) { | ||
5542 | *ptr = (1 << byte); | ||
5543 | byte++; | ||
5544 | byte &= 0x07; | ||
5545 | } else { | ||
5546 | *ptr = (char) (~(1 << byte)); | ||
5547 | } | ||
5548 | |||
5549 | /* Flip the pattern every 32 bytes | ||
5550 | */ | ||
5551 | if (ii & 0x20) | ||
5552 | *ptr = ~(*ptr); | ||
5553 | } | ||
5554 | } | ||
5555 | break; | ||
5556 | } | ||
5557 | } | ||
5558 | |||
5559 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
5560 | /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return. | ||
5561 | * Else set the NEED_DV flag after Read Capacity Issued (disks) | ||
5562 | * or Mode Sense (cdroms). | ||
5563 | * | ||
5564 | * Tapes, initTarget will set this flag on completion of Inquiry command. | ||
5565 | * Called only if DV_NOT_DONE flag is set | ||
5566 | */ | ||
5567 | static void | ||
5568 | mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc) | ||
5569 | { | ||
5570 | MPT_ADAPTER *ioc = hd->ioc; | ||
5571 | u8 cmd; | ||
5572 | SpiCfgData *pSpi; | ||
5573 | |||
5574 | ddvtprintk((MYIOC_s_NOTE_FMT | ||
5575 | " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", | ||
5576 | hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0])); | ||
5577 | |||
5578 | if ((sc->device->lun != 0) || (hd->negoNvram != 0)) | ||
5579 | return; | ||
5580 | |||
5581 | cmd = sc->cmnd[0]; | ||
5582 | |||
5583 | if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { | ||
5584 | pSpi = &ioc->spi_data; | ||
5585 | if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) { | ||
5586 | /* Set NEED_DV for all hidden disks | ||
5587 | */ | ||
5588 | Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; | ||
5589 | int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; | ||
5590 | |||
5591 | while (numPDisk) { | ||
5592 | pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; | ||
5593 | ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); | ||
5594 | pPDisk++; | ||
5595 | numPDisk--; | ||
5596 | } | ||
5597 | } | ||
5598 | pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV; | ||
5599 | ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id)); | ||
5600 | } | ||
5601 | } | ||
5602 | |||
5603 | /* mptscsih_raid_set_dv_flags() | ||
5604 | * | ||
5605 | * New or replaced disk. Set DV flag and schedule DV. | ||
5606 | */ | ||
5607 | static void | ||
5608 | mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id) | ||
5609 | { | ||
5610 | MPT_ADAPTER *ioc = hd->ioc; | ||
5611 | SpiCfgData *pSpi = &ioc->spi_data; | ||
5612 | Ioc3PhysDisk_t *pPDisk; | ||
5613 | int numPDisk; | ||
5614 | |||
5615 | if (hd->negoNvram != 0) | ||
5616 | return; | ||
5617 | |||
5618 | ddvtprintk(("DV requested for phys disk id %d\n", id)); | ||
5619 | if (ioc->raid_data.pIocPg3) { | ||
5620 | pPDisk = ioc->raid_data.pIocPg3->PhysDisk; | ||
5621 | numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; | ||
5622 | while (numPDisk) { | ||
5623 | if (id == pPDisk->PhysDiskNum) { | ||
5624 | pSpi->dvStatus[pPDisk->PhysDiskID] = | ||
5625 | (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); | ||
5626 | pSpi->forceDv = MPT_SCSICFG_NEED_DV; | ||
5627 | ddvtprintk(("NEED_DV set for phys disk id %d\n", | ||
5628 | pPDisk->PhysDiskID)); | ||
5629 | break; | ||
5630 | } | ||
5631 | pPDisk++; | ||
5632 | numPDisk--; | ||
5633 | } | ||
5634 | |||
5635 | if (numPDisk == 0) { | ||
5636 | /* The physical disk that needs DV was not found | ||
5637 | * in the stored IOC Page 3. The driver must reload | ||
5638 | * this page. DV routine will set the NEED_DV flag for | ||
5639 | * all phys disks that have DV_NOT_DONE set. | ||
5640 | */ | ||
5641 | pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; | ||
5642 | ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id)); | ||
5643 | } | ||
5644 | } | ||
5645 | } | ||
5646 | #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */ | ||
5647 | |||
5648 | EXPORT_SYMBOL(mptscsih_remove); | 3394 | EXPORT_SYMBOL(mptscsih_remove); |
5649 | EXPORT_SYMBOL(mptscsih_shutdown); | 3395 | EXPORT_SYMBOL(mptscsih_shutdown); |
5650 | #ifdef CONFIG_PM | 3396 | #ifdef CONFIG_PM |
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 44b248d51ea3..14a5b6c2e2bd 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h | |||
@@ -60,16 +60,6 @@ | |||
60 | 60 | ||
61 | #define MPT_SCSI_MAX_SECTORS 8192 | 61 | #define MPT_SCSI_MAX_SECTORS 8192 |
62 | 62 | ||
63 | /* To disable domain validation, uncomment the | ||
64 | * following line. No effect for FC devices. | ||
65 | * For SCSI devices, driver will negotiate to | ||
66 | * NVRAM settings (if available) or to maximum adapter | ||
67 | * capabilities. | ||
68 | */ | ||
69 | |||
70 | #define MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
71 | |||
72 | |||
73 | /* SCSI driver setup structure. Settings can be overridden | 63 | /* SCSI driver setup structure. Settings can be overridden |
74 | * by command line options. | 64 | * by command line options. |
75 | */ | 65 | */ |
@@ -109,3 +99,5 @@ extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | |||
109 | extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); | 99 | extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); |
110 | extern void mptscsih_timer_expired(unsigned long data); | 100 | extern void mptscsih_timer_expired(unsigned long data); |
111 | extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); | 101 | extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); |
102 | extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); | ||
103 | extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); | ||
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index f148dfa39117..09c745b19cc8 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c | |||
@@ -56,12 +56,15 @@ | |||
56 | #include <linux/reboot.h> /* notifier code */ | 56 | #include <linux/reboot.h> /* notifier code */ |
57 | #include <linux/sched.h> | 57 | #include <linux/sched.h> |
58 | #include <linux/workqueue.h> | 58 | #include <linux/workqueue.h> |
59 | #include <linux/raid_class.h> | ||
59 | 60 | ||
60 | #include <scsi/scsi.h> | 61 | #include <scsi/scsi.h> |
61 | #include <scsi/scsi_cmnd.h> | 62 | #include <scsi/scsi_cmnd.h> |
62 | #include <scsi/scsi_device.h> | 63 | #include <scsi/scsi_device.h> |
63 | #include <scsi/scsi_host.h> | 64 | #include <scsi/scsi_host.h> |
64 | #include <scsi/scsi_tcq.h> | 65 | #include <scsi/scsi_tcq.h> |
66 | #include <scsi/scsi_transport.h> | ||
67 | #include <scsi/scsi_transport_spi.h> | ||
65 | 68 | ||
66 | #include "mptbase.h" | 69 | #include "mptbase.h" |
67 | #include "mptscsih.h" | 70 | #include "mptscsih.h" |
@@ -76,20 +79,6 @@ MODULE_DESCRIPTION(my_NAME); | |||
76 | MODULE_LICENSE("GPL"); | 79 | MODULE_LICENSE("GPL"); |
77 | 80 | ||
78 | /* Command line args */ | 81 | /* Command line args */ |
79 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
80 | static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION; | ||
81 | module_param(mpt_dv, int, 0); | ||
82 | MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)"); | ||
83 | |||
84 | static int mpt_width = MPTSCSIH_MAX_WIDTH; | ||
85 | module_param(mpt_width, int, 0); | ||
86 | MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)"); | ||
87 | |||
88 | static ushort mpt_factor = MPTSCSIH_MIN_SYNC; | ||
89 | module_param(mpt_factor, ushort, 0); | ||
90 | MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)"); | ||
91 | #endif | ||
92 | |||
93 | static int mpt_saf_te = MPTSCSIH_SAF_TE; | 82 | static int mpt_saf_te = MPTSCSIH_SAF_TE; |
94 | module_param(mpt_saf_te, int, 0); | 83 | module_param(mpt_saf_te, int, 0); |
95 | MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); | 84 | MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); |
@@ -98,10 +87,308 @@ static int mpt_pq_filter = 0; | |||
98 | module_param(mpt_pq_filter, int, 0); | 87 | module_param(mpt_pq_filter, int, 0); |
99 | MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); | 88 | MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); |
100 | 89 | ||
90 | static void mptspi_write_offset(struct scsi_target *, int); | ||
91 | static void mptspi_write_width(struct scsi_target *, int); | ||
92 | static int mptspi_write_spi_device_pg1(struct scsi_target *, | ||
93 | struct _CONFIG_PAGE_SCSI_DEVICE_1 *); | ||
94 | |||
95 | static struct scsi_transport_template *mptspi_transport_template = NULL; | ||
96 | |||
101 | static int mptspiDoneCtx = -1; | 97 | static int mptspiDoneCtx = -1; |
102 | static int mptspiTaskCtx = -1; | 98 | static int mptspiTaskCtx = -1; |
103 | static int mptspiInternalCtx = -1; /* Used only for internal commands */ | 99 | static int mptspiInternalCtx = -1; /* Used only for internal commands */ |
104 | 100 | ||
101 | static int mptspi_target_alloc(struct scsi_target *starget) | ||
102 | { | ||
103 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
104 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
105 | int ret; | ||
106 | |||
107 | if (hd == NULL) | ||
108 | return -ENODEV; | ||
109 | |||
110 | ret = mptscsih_target_alloc(starget); | ||
111 | if (ret) | ||
112 | return ret; | ||
113 | |||
114 | /* if we're a device on virtual channel 1 and we're not part | ||
115 | * of an array, just return here (otherwise the setup below | ||
116 | * may actually affect a real physical device on channel 0 */ | ||
117 | if (starget->channel == 1 && | ||
118 | mptscsih_raid_id_to_num(hd, starget->id) < 0) | ||
119 | return 0; | ||
120 | |||
121 | if (hd->ioc->spi_data.nvram && | ||
122 | hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { | ||
123 | u32 nvram = hd->ioc->spi_data.nvram[starget->id]; | ||
124 | spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; | ||
125 | spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; | ||
126 | } else { | ||
127 | spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor; | ||
128 | spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth; | ||
129 | } | ||
130 | spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset; | ||
131 | |||
132 | spi_offset(starget) = 0; | ||
133 | mptspi_write_width(starget, 0); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int mptspi_read_spi_device_pg0(struct scsi_target *starget, | ||
139 | struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) | ||
140 | { | ||
141 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
142 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
143 | struct _MPT_ADAPTER *ioc = hd->ioc; | ||
144 | struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0; | ||
145 | dma_addr_t pg0_dma; | ||
146 | int size; | ||
147 | struct _x_config_parms cfg; | ||
148 | struct _CONFIG_PAGE_HEADER hdr; | ||
149 | int err = -EBUSY; | ||
150 | |||
151 | /* No SPI parameters for RAID devices */ | ||
152 | if (starget->channel == 0 && | ||
153 | (hd->ioc->raid_data.isRaid & (1 << starget->id))) | ||
154 | return -1; | ||
155 | |||
156 | size = ioc->spi_data.sdp0length * 4; | ||
157 | /* | ||
158 | if (ioc->spi_data.sdp0length & 1) | ||
159 | size += size + 4; | ||
160 | size += 2048; | ||
161 | */ | ||
162 | |||
163 | pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL); | ||
164 | if (pg0 == NULL) { | ||
165 | starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | |||
169 | memset(&hdr, 0, sizeof(hdr)); | ||
170 | |||
171 | hdr.PageVersion = ioc->spi_data.sdp0version; | ||
172 | hdr.PageLength = ioc->spi_data.sdp0length; | ||
173 | hdr.PageNumber = 0; | ||
174 | hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
175 | |||
176 | memset(&cfg, 0, sizeof(cfg)); | ||
177 | |||
178 | cfg.cfghdr.hdr = &hdr; | ||
179 | cfg.physAddr = pg0_dma; | ||
180 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
181 | cfg.dir = 0; | ||
182 | cfg.pageAddr = starget->id; | ||
183 | |||
184 | if (mpt_config(ioc, &cfg)) { | ||
185 | starget_printk(KERN_ERR, starget, "mpt_config failed\n"); | ||
186 | goto out_free; | ||
187 | } | ||
188 | err = 0; | ||
189 | memcpy(pass_pg0, pg0, size); | ||
190 | |||
191 | out_free: | ||
192 | dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma); | ||
193 | return err; | ||
194 | } | ||
195 | |||
196 | static u32 mptspi_getRP(struct scsi_target *starget) | ||
197 | { | ||
198 | u32 nego = 0; | ||
199 | |||
200 | nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0; | ||
201 | nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0; | ||
202 | nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0; | ||
203 | nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0; | ||
204 | nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0; | ||
205 | nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0; | ||
206 | nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0; | ||
207 | nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0; | ||
208 | |||
209 | nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK; | ||
210 | nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK; | ||
211 | nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; | ||
212 | |||
213 | return nego; | ||
214 | } | ||
215 | |||
216 | static void mptspi_read_parameters(struct scsi_target *starget) | ||
217 | { | ||
218 | int nego; | ||
219 | struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0; | ||
220 | |||
221 | mptspi_read_spi_device_pg0(starget, &pg0); | ||
222 | |||
223 | nego = le32_to_cpu(pg0.NegotiatedParameters); | ||
224 | |||
225 | spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0; | ||
226 | spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0; | ||
227 | spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0; | ||
228 | spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0; | ||
229 | spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0; | ||
230 | spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0; | ||
231 | spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0; | ||
232 | spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0; | ||
233 | spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD; | ||
234 | spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET; | ||
235 | spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0; | ||
236 | } | ||
237 | |||
238 | static int | ||
239 | mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) | ||
240 | { | ||
241 | MpiRaidActionRequest_t *pReq; | ||
242 | MPT_FRAME_HDR *mf; | ||
243 | |||
244 | /* Get and Populate a free Frame | ||
245 | */ | ||
246 | if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { | ||
247 | ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", | ||
248 | hd->ioc->name)); | ||
249 | return -EAGAIN; | ||
250 | } | ||
251 | pReq = (MpiRaidActionRequest_t *)mf; | ||
252 | if (quiesce) | ||
253 | pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO; | ||
254 | else | ||
255 | pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO; | ||
256 | pReq->Reserved1 = 0; | ||
257 | pReq->ChainOffset = 0; | ||
258 | pReq->Function = MPI_FUNCTION_RAID_ACTION; | ||
259 | pReq->VolumeID = disk; | ||
260 | pReq->VolumeBus = 0; | ||
261 | pReq->PhysDiskNum = 0; | ||
262 | pReq->MsgFlags = 0; | ||
263 | pReq->Reserved2 = 0; | ||
264 | pReq->ActionDataWord = 0; /* Reserved for this action */ | ||
265 | |||
266 | mpt_add_sge((char *)&pReq->ActionDataSGE, | ||
267 | MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); | ||
268 | |||
269 | ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", | ||
270 | hd->ioc->name, action, io->id)); | ||
271 | |||
272 | hd->pLocal = NULL; | ||
273 | hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ | ||
274 | hd->scandv_wait_done = 0; | ||
275 | |||
276 | /* Save cmd pointer, for resource free if timeout or | ||
277 | * FW reload occurs | ||
278 | */ | ||
279 | hd->cmdPtr = mf; | ||
280 | |||
281 | add_timer(&hd->timer); | ||
282 | mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); | ||
283 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | ||
284 | |||
285 | if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0)) | ||
286 | return -1; | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, | ||
292 | struct scsi_device *sdev) | ||
293 | { | ||
294 | VirtTarget *vtarget = scsi_target(sdev)->hostdata; | ||
295 | |||
296 | /* no DV on RAID devices */ | ||
297 | if (sdev->channel == 0 && | ||
298 | (hd->ioc->raid_data.isRaid & (1 << sdev->id))) | ||
299 | return; | ||
300 | |||
301 | /* If this is a piece of a RAID, then quiesce first */ | ||
302 | if (sdev->channel == 1 && | ||
303 | mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) { | ||
304 | starget_printk(KERN_ERR, scsi_target(sdev), | ||
305 | "Integrated RAID quiesce failed\n"); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | spi_dv_device(sdev); | ||
310 | |||
311 | if (sdev->channel == 1 && | ||
312 | mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0) | ||
313 | starget_printk(KERN_ERR, scsi_target(sdev), | ||
314 | "Integrated RAID resume failed\n"); | ||
315 | |||
316 | mptspi_read_parameters(sdev->sdev_target); | ||
317 | spi_display_xfer_agreement(sdev->sdev_target); | ||
318 | mptspi_read_parameters(sdev->sdev_target); | ||
319 | } | ||
320 | |||
321 | static int mptspi_slave_alloc(struct scsi_device *sdev) | ||
322 | { | ||
323 | int ret; | ||
324 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; | ||
325 | /* gcc doesn't see that all uses of this variable occur within | ||
326 | * the if() statements, so stop it from whining */ | ||
327 | int physdisknum = 0; | ||
328 | |||
329 | if (sdev->channel == 1) { | ||
330 | physdisknum = mptscsih_raid_id_to_num(hd, sdev->id); | ||
331 | |||
332 | if (physdisknum < 0) | ||
333 | return physdisknum; | ||
334 | } | ||
335 | |||
336 | ret = mptscsih_slave_alloc(sdev); | ||
337 | |||
338 | if (ret) | ||
339 | return ret; | ||
340 | |||
341 | if (sdev->channel == 1) { | ||
342 | VirtDevice *vdev = sdev->hostdata; | ||
343 | sdev->no_uld_attach = 1; | ||
344 | vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
345 | /* The real channel for this device is zero */ | ||
346 | vdev->vtarget->bus_id = 0; | ||
347 | /* The actual physdisknum (for RAID passthrough) */ | ||
348 | vdev->vtarget->target_id = physdisknum; | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int mptspi_slave_configure(struct scsi_device *sdev) | ||
355 | { | ||
356 | int ret = mptscsih_slave_configure(sdev); | ||
357 | struct _MPT_SCSI_HOST *hd = | ||
358 | (struct _MPT_SCSI_HOST *)sdev->host->hostdata; | ||
359 | |||
360 | if (ret) | ||
361 | return ret; | ||
362 | |||
363 | if ((sdev->channel == 1 || | ||
364 | !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) && | ||
365 | !spi_initial_dv(sdev->sdev_target)) | ||
366 | mptspi_dv_device(hd, sdev); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static void mptspi_slave_destroy(struct scsi_device *sdev) | ||
372 | { | ||
373 | struct scsi_target *starget = scsi_target(sdev); | ||
374 | VirtTarget *vtarget = starget->hostdata; | ||
375 | VirtDevice *vdevice = sdev->hostdata; | ||
376 | |||
377 | /* Will this be the last lun on a non-raid device? */ | ||
378 | if (vtarget->num_luns == 1 && vdevice->configured_lun) { | ||
379 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
380 | |||
381 | /* Async Narrow */ | ||
382 | pg1.RequestedParameters = 0; | ||
383 | pg1.Reserved = 0; | ||
384 | pg1.Configuration = 0; | ||
385 | |||
386 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
387 | } | ||
388 | |||
389 | mptscsih_slave_destroy(sdev); | ||
390 | } | ||
391 | |||
105 | static struct scsi_host_template mptspi_driver_template = { | 392 | static struct scsi_host_template mptspi_driver_template = { |
106 | .module = THIS_MODULE, | 393 | .module = THIS_MODULE, |
107 | .proc_name = "mptspi", | 394 | .proc_name = "mptspi", |
@@ -109,11 +396,11 @@ static struct scsi_host_template mptspi_driver_template = { | |||
109 | .name = "MPT SPI Host", | 396 | .name = "MPT SPI Host", |
110 | .info = mptscsih_info, | 397 | .info = mptscsih_info, |
111 | .queuecommand = mptscsih_qcmd, | 398 | .queuecommand = mptscsih_qcmd, |
112 | .target_alloc = mptscsih_target_alloc, | 399 | .target_alloc = mptspi_target_alloc, |
113 | .slave_alloc = mptscsih_slave_alloc, | 400 | .slave_alloc = mptspi_slave_alloc, |
114 | .slave_configure = mptscsih_slave_configure, | 401 | .slave_configure = mptspi_slave_configure, |
115 | .target_destroy = mptscsih_target_destroy, | 402 | .target_destroy = mptscsih_target_destroy, |
116 | .slave_destroy = mptscsih_slave_destroy, | 403 | .slave_destroy = mptspi_slave_destroy, |
117 | .change_queue_depth = mptscsih_change_queue_depth, | 404 | .change_queue_depth = mptscsih_change_queue_depth, |
118 | .eh_abort_handler = mptscsih_abort, | 405 | .eh_abort_handler = mptscsih_abort, |
119 | .eh_device_reset_handler = mptscsih_dev_reset, | 406 | .eh_device_reset_handler = mptscsih_dev_reset, |
@@ -128,6 +415,360 @@ static struct scsi_host_template mptspi_driver_template = { | |||
128 | .use_clustering = ENABLE_CLUSTERING, | 415 | .use_clustering = ENABLE_CLUSTERING, |
129 | }; | 416 | }; |
130 | 417 | ||
418 | static int mptspi_write_spi_device_pg1(struct scsi_target *starget, | ||
419 | struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1) | ||
420 | { | ||
421 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
422 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
423 | struct _MPT_ADAPTER *ioc = hd->ioc; | ||
424 | struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1; | ||
425 | dma_addr_t pg1_dma; | ||
426 | int size; | ||
427 | struct _x_config_parms cfg; | ||
428 | struct _CONFIG_PAGE_HEADER hdr; | ||
429 | int err = -EBUSY; | ||
430 | |||
431 | /* don't allow updating nego parameters on RAID devices */ | ||
432 | if (starget->channel == 0 && | ||
433 | (hd->ioc->raid_data.isRaid & (1 << starget->id))) | ||
434 | return -1; | ||
435 | |||
436 | size = ioc->spi_data.sdp1length * 4; | ||
437 | |||
438 | pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL); | ||
439 | if (pg1 == NULL) { | ||
440 | starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | |||
444 | memset(&hdr, 0, sizeof(hdr)); | ||
445 | |||
446 | hdr.PageVersion = ioc->spi_data.sdp1version; | ||
447 | hdr.PageLength = ioc->spi_data.sdp1length; | ||
448 | hdr.PageNumber = 1; | ||
449 | hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
450 | |||
451 | memset(&cfg, 0, sizeof(cfg)); | ||
452 | |||
453 | cfg.cfghdr.hdr = &hdr; | ||
454 | cfg.physAddr = pg1_dma; | ||
455 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
456 | cfg.dir = 1; | ||
457 | cfg.pageAddr = starget->id; | ||
458 | |||
459 | memcpy(pg1, pass_pg1, size); | ||
460 | |||
461 | pg1->Header.PageVersion = hdr.PageVersion; | ||
462 | pg1->Header.PageLength = hdr.PageLength; | ||
463 | pg1->Header.PageNumber = hdr.PageNumber; | ||
464 | pg1->Header.PageType = hdr.PageType; | ||
465 | |||
466 | if (mpt_config(ioc, &cfg)) { | ||
467 | starget_printk(KERN_ERR, starget, "mpt_config failed\n"); | ||
468 | goto out_free; | ||
469 | } | ||
470 | err = 0; | ||
471 | |||
472 | out_free: | ||
473 | dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma); | ||
474 | return err; | ||
475 | } | ||
476 | |||
477 | static void mptspi_write_offset(struct scsi_target *starget, int offset) | ||
478 | { | ||
479 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
480 | u32 nego; | ||
481 | |||
482 | if (offset < 0) | ||
483 | offset = 0; | ||
484 | |||
485 | if (offset > 255) | ||
486 | offset = 255; | ||
487 | |||
488 | if (spi_offset(starget) == -1) | ||
489 | mptspi_read_parameters(starget); | ||
490 | |||
491 | spi_offset(starget) = offset; | ||
492 | |||
493 | nego = mptspi_getRP(starget); | ||
494 | |||
495 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
496 | pg1.Reserved = 0; | ||
497 | pg1.Configuration = 0; | ||
498 | |||
499 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
500 | } | ||
501 | |||
502 | static void mptspi_write_period(struct scsi_target *starget, int period) | ||
503 | { | ||
504 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
505 | u32 nego; | ||
506 | |||
507 | if (period < 8) | ||
508 | period = 8; | ||
509 | |||
510 | if (period > 255) | ||
511 | period = 255; | ||
512 | |||
513 | if (spi_period(starget) == -1) | ||
514 | mptspi_read_parameters(starget); | ||
515 | |||
516 | if (period == 8) { | ||
517 | spi_iu(starget) = 1; | ||
518 | spi_dt(starget) = 1; | ||
519 | } else if (period == 9) { | ||
520 | spi_dt(starget) = 1; | ||
521 | } | ||
522 | |||
523 | spi_period(starget) = period; | ||
524 | |||
525 | nego = mptspi_getRP(starget); | ||
526 | |||
527 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
528 | pg1.Reserved = 0; | ||
529 | pg1.Configuration = 0; | ||
530 | |||
531 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
532 | } | ||
533 | |||
534 | static void mptspi_write_dt(struct scsi_target *starget, int dt) | ||
535 | { | ||
536 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
537 | u32 nego; | ||
538 | |||
539 | if (spi_period(starget) == -1) | ||
540 | mptspi_read_parameters(starget); | ||
541 | |||
542 | if (!dt && spi_period(starget) < 10) | ||
543 | spi_period(starget) = 10; | ||
544 | |||
545 | spi_dt(starget) = dt; | ||
546 | |||
547 | nego = mptspi_getRP(starget); | ||
548 | |||
549 | |||
550 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
551 | pg1.Reserved = 0; | ||
552 | pg1.Configuration = 0; | ||
553 | |||
554 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
555 | } | ||
556 | |||
557 | static void mptspi_write_iu(struct scsi_target *starget, int iu) | ||
558 | { | ||
559 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
560 | u32 nego; | ||
561 | |||
562 | if (spi_period(starget) == -1) | ||
563 | mptspi_read_parameters(starget); | ||
564 | |||
565 | if (!iu && spi_period(starget) < 9) | ||
566 | spi_period(starget) = 9; | ||
567 | |||
568 | spi_iu(starget) = iu; | ||
569 | |||
570 | nego = mptspi_getRP(starget); | ||
571 | |||
572 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
573 | pg1.Reserved = 0; | ||
574 | pg1.Configuration = 0; | ||
575 | |||
576 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
577 | } | ||
578 | |||
579 | #define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) \ | ||
580 | static void mptspi_write_##parm(struct scsi_target *starget, int parm)\ | ||
581 | { \ | ||
582 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; \ | ||
583 | u32 nego; \ | ||
584 | \ | ||
585 | spi_##parm(starget) = parm; \ | ||
586 | \ | ||
587 | nego = mptspi_getRP(starget); \ | ||
588 | \ | ||
589 | pg1.RequestedParameters = cpu_to_le32(nego); \ | ||
590 | pg1.Reserved = 0; \ | ||
591 | pg1.Configuration = 0; \ | ||
592 | \ | ||
593 | mptspi_write_spi_device_pg1(starget, &pg1); \ | ||
594 | } | ||
595 | |||
596 | MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm) | ||
597 | MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow) | ||
598 | MPTSPI_SIMPLE_TRANSPORT_PARM(rti) | ||
599 | MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs) | ||
600 | MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en) | ||
601 | |||
602 | static void mptspi_write_qas(struct scsi_target *starget, int qas) | ||
603 | { | ||
604 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
605 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
606 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
607 | VirtTarget *vtarget = starget->hostdata; | ||
608 | u32 nego; | ||
609 | |||
610 | if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) || | ||
611 | hd->ioc->spi_data.noQas) | ||
612 | spi_qas(starget) = 0; | ||
613 | else | ||
614 | spi_qas(starget) = qas; | ||
615 | |||
616 | nego = mptspi_getRP(starget); | ||
617 | |||
618 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
619 | pg1.Reserved = 0; | ||
620 | pg1.Configuration = 0; | ||
621 | |||
622 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
623 | } | ||
624 | |||
625 | static void mptspi_write_width(struct scsi_target *starget, int width) | ||
626 | { | ||
627 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
628 | u32 nego; | ||
629 | |||
630 | if (!width) { | ||
631 | spi_dt(starget) = 0; | ||
632 | if (spi_period(starget) < 10) | ||
633 | spi_period(starget) = 10; | ||
634 | } | ||
635 | |||
636 | spi_width(starget) = width; | ||
637 | |||
638 | nego = mptspi_getRP(starget); | ||
639 | |||
640 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
641 | pg1.Reserved = 0; | ||
642 | pg1.Configuration = 0; | ||
643 | |||
644 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
645 | } | ||
646 | |||
647 | struct work_queue_wrapper { | ||
648 | struct work_struct work; | ||
649 | struct _MPT_SCSI_HOST *hd; | ||
650 | int disk; | ||
651 | }; | ||
652 | |||
653 | static void mpt_work_wrapper(void *data) | ||
654 | { | ||
655 | struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; | ||
656 | struct _MPT_SCSI_HOST *hd = wqw->hd; | ||
657 | struct Scsi_Host *shost = hd->ioc->sh; | ||
658 | struct scsi_device *sdev; | ||
659 | int disk = wqw->disk; | ||
660 | struct _CONFIG_PAGE_IOC_3 *pg3; | ||
661 | |||
662 | kfree(wqw); | ||
663 | |||
664 | mpt_findImVolumes(hd->ioc); | ||
665 | pg3 = hd->ioc->raid_data.pIocPg3; | ||
666 | if (!pg3) | ||
667 | return; | ||
668 | |||
669 | shost_for_each_device(sdev,shost) { | ||
670 | struct scsi_target *starget = scsi_target(sdev); | ||
671 | VirtTarget *vtarget = starget->hostdata; | ||
672 | |||
673 | /* only want to search RAID components */ | ||
674 | if (sdev->channel != 1) | ||
675 | continue; | ||
676 | |||
677 | /* The target_id is the raid PhysDiskNum, even if | ||
678 | * starget->id is the actual target address */ | ||
679 | if(vtarget->target_id != disk) | ||
680 | continue; | ||
681 | |||
682 | starget_printk(KERN_INFO, vtarget->starget, | ||
683 | "Integrated RAID requests DV of new device\n"); | ||
684 | mptspi_dv_device(hd, sdev); | ||
685 | } | ||
686 | shost_printk(KERN_INFO, shost, | ||
687 | "Integrated RAID detects new device %d\n", disk); | ||
688 | scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1); | ||
689 | } | ||
690 | |||
691 | |||
692 | static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk) | ||
693 | { | ||
694 | struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC); | ||
695 | |||
696 | if (!wqw) { | ||
697 | shost_printk(KERN_ERR, hd->ioc->sh, | ||
698 | "Failed to act on RAID event for physical disk %d\n", | ||
699 | disk); | ||
700 | return; | ||
701 | } | ||
702 | INIT_WORK(&wqw->work, mpt_work_wrapper, wqw); | ||
703 | wqw->hd = hd; | ||
704 | wqw->disk = disk; | ||
705 | |||
706 | schedule_work(&wqw->work); | ||
707 | } | ||
708 | |||
709 | static int | ||
710 | mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | ||
711 | { | ||
712 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; | ||
713 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; | ||
714 | |||
715 | if (hd && event == MPI_EVENT_INTEGRATED_RAID) { | ||
716 | int reason | ||
717 | = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; | ||
718 | |||
719 | if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { | ||
720 | int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24; | ||
721 | mpt_dv_raid(hd, disk); | ||
722 | } | ||
723 | } | ||
724 | return mptscsih_event_process(ioc, pEvReply); | ||
725 | } | ||
726 | |||
727 | static int | ||
728 | mptspi_deny_binding(struct scsi_target *starget) | ||
729 | { | ||
730 | struct _MPT_SCSI_HOST *hd = | ||
731 | (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata; | ||
732 | return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) && | ||
733 | starget->channel == 0) ? 1 : 0; | ||
734 | } | ||
735 | |||
736 | static struct spi_function_template mptspi_transport_functions = { | ||
737 | .get_offset = mptspi_read_parameters, | ||
738 | .set_offset = mptspi_write_offset, | ||
739 | .show_offset = 1, | ||
740 | .get_period = mptspi_read_parameters, | ||
741 | .set_period = mptspi_write_period, | ||
742 | .show_period = 1, | ||
743 | .get_width = mptspi_read_parameters, | ||
744 | .set_width = mptspi_write_width, | ||
745 | .show_width = 1, | ||
746 | .get_iu = mptspi_read_parameters, | ||
747 | .set_iu = mptspi_write_iu, | ||
748 | .show_iu = 1, | ||
749 | .get_dt = mptspi_read_parameters, | ||
750 | .set_dt = mptspi_write_dt, | ||
751 | .show_dt = 1, | ||
752 | .get_qas = mptspi_read_parameters, | ||
753 | .set_qas = mptspi_write_qas, | ||
754 | .show_qas = 1, | ||
755 | .get_wr_flow = mptspi_read_parameters, | ||
756 | .set_wr_flow = mptspi_write_wr_flow, | ||
757 | .show_wr_flow = 1, | ||
758 | .get_rd_strm = mptspi_read_parameters, | ||
759 | .set_rd_strm = mptspi_write_rd_strm, | ||
760 | .show_rd_strm = 1, | ||
761 | .get_rti = mptspi_read_parameters, | ||
762 | .set_rti = mptspi_write_rti, | ||
763 | .show_rti = 1, | ||
764 | .get_pcomp_en = mptspi_read_parameters, | ||
765 | .set_pcomp_en = mptspi_write_pcomp_en, | ||
766 | .show_pcomp_en = 1, | ||
767 | .get_hold_mcs = mptspi_read_parameters, | ||
768 | .set_hold_mcs = mptspi_write_hold_mcs, | ||
769 | .show_hold_mcs = 1, | ||
770 | .deny_binding = mptspi_deny_binding, | ||
771 | }; | ||
131 | 772 | ||
132 | /**************************************************************************** | 773 | /**************************************************************************** |
133 | * Supported hardware | 774 | * Supported hardware |
@@ -242,7 +883,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
242 | sh->max_id = MPT_MAX_SCSI_DEVICES; | 883 | sh->max_id = MPT_MAX_SCSI_DEVICES; |
243 | 884 | ||
244 | sh->max_lun = MPT_LAST_LUN + 1; | 885 | sh->max_lun = MPT_LAST_LUN + 1; |
245 | sh->max_channel = 0; | 886 | /* |
887 | * If RAID Firmware Detected, setup virtual channel | ||
888 | */ | ||
889 | if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | ||
890 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) | ||
891 | sh->max_channel = 1; | ||
892 | else | ||
893 | sh->max_channel = 0; | ||
246 | sh->this_id = ioc->pfacts[0].PortSCSIID; | 894 | sh->this_id = ioc->pfacts[0].PortSCSIID; |
247 | 895 | ||
248 | /* Required entry. | 896 | /* Required entry. |
@@ -301,7 +949,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
301 | * indicates a device exists. | 949 | * indicates a device exists. |
302 | * max_id = 1 + maximum id (hosts.h) | 950 | * max_id = 1 + maximum id (hosts.h) |
303 | */ | 951 | */ |
304 | hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); | 952 | hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1), |
953 | sizeof(void *), GFP_ATOMIC); | ||
305 | if (!hd->Targets) { | 954 | if (!hd->Targets) { |
306 | error = -ENOMEM; | 955 | error = -ENOMEM; |
307 | goto out_mptspi_probe; | 956 | goto out_mptspi_probe; |
@@ -334,49 +983,23 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
334 | ioc->spi_data.Saf_Te = mpt_saf_te; | 983 | ioc->spi_data.Saf_Te = mpt_saf_te; |
335 | hd->mpt_pq_filter = mpt_pq_filter; | 984 | hd->mpt_pq_filter = mpt_pq_filter; |
336 | 985 | ||
337 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
338 | if (ioc->spi_data.maxBusWidth > mpt_width) | ||
339 | ioc->spi_data.maxBusWidth = mpt_width; | ||
340 | if (ioc->spi_data.minSyncFactor < mpt_factor) | ||
341 | ioc->spi_data.minSyncFactor = mpt_factor; | ||
342 | if (ioc->spi_data.minSyncFactor == MPT_ASYNC) { | ||
343 | ioc->spi_data.maxSyncOffset = 0; | ||
344 | } | ||
345 | ioc->spi_data.mpt_dv = mpt_dv; | ||
346 | hd->negoNvram = 0; | ||
347 | |||
348 | ddvprintk((MYIOC_s_INFO_FMT | ||
349 | "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n", | ||
350 | ioc->name, | ||
351 | mpt_dv, | ||
352 | mpt_width, | ||
353 | mpt_factor, | ||
354 | mpt_saf_te, | ||
355 | mpt_pq_filter)); | ||
356 | #else | ||
357 | hd->negoNvram = MPT_SCSICFG_USE_NVRAM; | 986 | hd->negoNvram = MPT_SCSICFG_USE_NVRAM; |
358 | ddvprintk((MYIOC_s_INFO_FMT | 987 | ddvprintk((MYIOC_s_INFO_FMT |
359 | "saf_te %x mpt_pq_filter %x\n", | 988 | "saf_te %x mpt_pq_filter %x\n", |
360 | ioc->name, | 989 | ioc->name, |
361 | mpt_saf_te, | 990 | mpt_saf_te, |
362 | mpt_pq_filter)); | 991 | mpt_pq_filter)); |
363 | #endif | ||
364 | |||
365 | ioc->spi_data.forceDv = 0; | ||
366 | ioc->spi_data.noQas = 0; | 992 | ioc->spi_data.noQas = 0; |
367 | 993 | ||
368 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) | ||
369 | ioc->spi_data.dvStatus[ii] = | ||
370 | MPT_SCSICFG_NEGOTIATE; | ||
371 | |||
372 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) | ||
373 | ioc->spi_data.dvStatus[ii] |= | ||
374 | MPT_SCSICFG_DV_NOT_DONE; | ||
375 | |||
376 | init_waitqueue_head(&hd->scandv_waitq); | 994 | init_waitqueue_head(&hd->scandv_waitq); |
377 | hd->scandv_wait_done = 0; | 995 | hd->scandv_wait_done = 0; |
378 | hd->last_queue_full = 0; | 996 | hd->last_queue_full = 0; |
379 | 997 | ||
998 | /* Some versions of the firmware don't support page 0; without | ||
999 | * that we can't get the parameters */ | ||
1000 | if (hd->ioc->spi_data.sdp0length != 0) | ||
1001 | sh->transportt = mptspi_transport_template; | ||
1002 | |||
380 | error = scsi_add_host (sh, &ioc->pcidev->dev); | 1003 | error = scsi_add_host (sh, &ioc->pcidev->dev); |
381 | if(error) { | 1004 | if(error) { |
382 | dprintk((KERN_ERR MYNAM | 1005 | dprintk((KERN_ERR MYNAM |
@@ -423,15 +1046,18 @@ static struct pci_driver mptspi_driver = { | |||
423 | static int __init | 1046 | static int __init |
424 | mptspi_init(void) | 1047 | mptspi_init(void) |
425 | { | 1048 | { |
426 | |||
427 | show_mptmod_ver(my_NAME, my_VERSION); | 1049 | show_mptmod_ver(my_NAME, my_VERSION); |
428 | 1050 | ||
1051 | mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions); | ||
1052 | if (!mptspi_transport_template) | ||
1053 | return -ENODEV; | ||
1054 | |||
429 | mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); | 1055 | mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); |
430 | mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); | 1056 | mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); |
431 | mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); | 1057 | mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); |
432 | 1058 | ||
433 | if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) { | 1059 | if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) { |
434 | devtprintk((KERN_INFO MYNAM | 1060 | devtverboseprintk((KERN_INFO MYNAM |
435 | ": Registered for IOC event notifications\n")); | 1061 | ": Registered for IOC event notifications\n")); |
436 | } | 1062 | } |
437 | 1063 | ||
@@ -465,6 +1091,7 @@ mptspi_exit(void) | |||
465 | mpt_deregister(mptspiInternalCtx); | 1091 | mpt_deregister(mptspiInternalCtx); |
466 | mpt_deregister(mptspiTaskCtx); | 1092 | mpt_deregister(mptspiTaskCtx); |
467 | mpt_deregister(mptspiDoneCtx); | 1093 | mpt_deregister(mptspiDoneCtx); |
1094 | spi_release_transport(mptspi_transport_template); | ||
468 | } | 1095 | } |
469 | 1096 | ||
470 | module_init(mptspi_init); | 1097 | module_init(mptspi_init); |