diff options
Diffstat (limited to 'drivers/message')
| -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 | ||||
| -rw-r--r-- | drivers/message/i2o/exec-osm.c | 21 |
13 files changed, 1665 insertions, 2807 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); |
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 9bb9859f6dfe..5ea133c59afb 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c | |||
| @@ -57,6 +57,13 @@ struct i2o_exec_wait { | |||
| 57 | struct list_head list; /* node in global wait list */ | 57 | struct list_head list; /* node in global wait list */ |
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | /* Work struct needed to handle LCT NOTIFY replies */ | ||
| 61 | struct i2o_exec_lct_notify_work { | ||
| 62 | struct work_struct work; /* work struct */ | ||
| 63 | struct i2o_controller *c; /* controller on which the LCT NOTIFY | ||
| 64 | was received */ | ||
| 65 | }; | ||
| 66 | |||
| 60 | /* Exec OSM class handling definition */ | 67 | /* Exec OSM class handling definition */ |
| 61 | static struct i2o_class_id i2o_exec_class_id[] = { | 68 | static struct i2o_class_id i2o_exec_class_id[] = { |
| 62 | {I2O_CLASS_EXECUTIVE}, | 69 | {I2O_CLASS_EXECUTIVE}, |
| @@ -355,9 +362,12 @@ static int i2o_exec_remove(struct device *dev) | |||
| 355 | * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY | 362 | * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY |
| 356 | * again, otherwise send LCT NOTIFY to get informed on next LCT change. | 363 | * again, otherwise send LCT NOTIFY to get informed on next LCT change. |
| 357 | */ | 364 | */ |
| 358 | static void i2o_exec_lct_modified(struct i2o_controller *c) | 365 | static void i2o_exec_lct_modified(struct i2o_exec_lct_notify_work *work) |
| 359 | { | 366 | { |
| 360 | u32 change_ind = 0; | 367 | u32 change_ind = 0; |
| 368 | struct i2o_controller *c = work->c; | ||
| 369 | |||
| 370 | kfree(work); | ||
| 361 | 371 | ||
| 362 | if (i2o_device_parse_lct(c) != -EAGAIN) | 372 | if (i2o_device_parse_lct(c) != -EAGAIN) |
| 363 | change_ind = c->lct->change_ind + 1; | 373 | change_ind = c->lct->change_ind + 1; |
| @@ -410,7 +420,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, | |||
| 410 | return i2o_msg_post_wait_complete(c, m, msg, context); | 420 | return i2o_msg_post_wait_complete(c, m, msg, context); |
| 411 | 421 | ||
| 412 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { | 422 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { |
| 413 | struct work_struct *work; | 423 | struct i2o_exec_lct_notify_work *work; |
| 414 | 424 | ||
| 415 | pr_debug("%s: LCT notify received\n", c->name); | 425 | pr_debug("%s: LCT notify received\n", c->name); |
| 416 | 426 | ||
| @@ -418,8 +428,11 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, | |||
| 418 | if (!work) | 428 | if (!work) |
| 419 | return -ENOMEM; | 429 | return -ENOMEM; |
| 420 | 430 | ||
| 421 | INIT_WORK(work, (void (*)(void *))i2o_exec_lct_modified, c); | 431 | work->c = c; |
| 422 | queue_work(i2o_exec_driver.event_queue, work); | 432 | |
| 433 | INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified, | ||
| 434 | work); | ||
| 435 | queue_work(i2o_exec_driver.event_queue, &work->work); | ||
| 423 | return 1; | 436 | return 1; |
| 424 | } | 437 | } |
| 425 | 438 | ||
