diff options
author | Brian King <brking@linux.vnet.ibm.com> | 2007-04-26 17:00:16 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:20 -0400 |
commit | ac09c349080008fdd54a15616a1b14771772d867 (patch) | |
tree | c4099da7d7c6b1072ea68145b044e0390756c08d | |
parent | 8cf093e275d0d703d3e6c23725e340006082beec (diff) |
[SCSI] ipr: Enable multi-initator RAID support
Enables multi-initiator support on ipr RAID adapters that support it.
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/ipr.c | 140 | ||||
-rw-r--r-- | drivers/scsi/ipr.h | 26 |
2 files changed, 159 insertions, 7 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index d9f208343a24..b15dfcbde4a0 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -92,6 +92,7 @@ static unsigned int ipr_fastfail = 0; | |||
92 | static unsigned int ipr_transop_timeout = 0; | 92 | static unsigned int ipr_transop_timeout = 0; |
93 | static unsigned int ipr_enable_cache = 1; | 93 | static unsigned int ipr_enable_cache = 1; |
94 | static unsigned int ipr_debug = 0; | 94 | static unsigned int ipr_debug = 0; |
95 | static unsigned int ipr_dual_ioa_raid = 1; | ||
95 | static DEFINE_SPINLOCK(ipr_driver_lock); | 96 | static DEFINE_SPINLOCK(ipr_driver_lock); |
96 | 97 | ||
97 | /* This table describes the differences between DMA controller chips */ | 98 | /* This table describes the differences between DMA controller chips */ |
@@ -158,6 +159,8 @@ module_param_named(enable_cache, ipr_enable_cache, int, 0); | |||
158 | MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)"); | 159 | MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)"); |
159 | module_param_named(debug, ipr_debug, int, 0); | 160 | module_param_named(debug, ipr_debug, int, 0); |
160 | MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)"); | 161 | MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)"); |
162 | module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0); | ||
163 | MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)"); | ||
161 | MODULE_LICENSE("GPL"); | 164 | MODULE_LICENSE("GPL"); |
162 | MODULE_VERSION(IPR_DRIVER_VERSION); | 165 | MODULE_VERSION(IPR_DRIVER_VERSION); |
163 | 166 | ||
@@ -5882,6 +5885,94 @@ static int ipr_ioafp_mode_sense_page28(struct ipr_cmnd *ipr_cmd) | |||
5882 | } | 5885 | } |
5883 | 5886 | ||
5884 | /** | 5887 | /** |
5888 | * ipr_ioafp_mode_select_page24 - Issue Mode Select to IOA | ||
5889 | * @ipr_cmd: ipr command struct | ||
5890 | * | ||
5891 | * This function enables dual IOA RAID support if possible. | ||
5892 | * | ||
5893 | * Return value: | ||
5894 | * IPR_RC_JOB_RETURN | ||
5895 | **/ | ||
5896 | static int ipr_ioafp_mode_select_page24(struct ipr_cmnd *ipr_cmd) | ||
5897 | { | ||
5898 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
5899 | struct ipr_mode_pages *mode_pages = &ioa_cfg->vpd_cbs->mode_pages; | ||
5900 | struct ipr_mode_page24 *mode_page; | ||
5901 | int length; | ||
5902 | |||
5903 | ENTER; | ||
5904 | mode_page = ipr_get_mode_page(mode_pages, 0x24, | ||
5905 | sizeof(struct ipr_mode_page24)); | ||
5906 | |||
5907 | if (mode_page) | ||
5908 | mode_page->flags |= IPR_ENABLE_DUAL_IOA_AF; | ||
5909 | |||
5910 | length = mode_pages->hdr.length + 1; | ||
5911 | mode_pages->hdr.length = 0; | ||
5912 | |||
5913 | ipr_build_mode_select(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), 0x11, | ||
5914 | ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, mode_pages), | ||
5915 | length); | ||
5916 | |||
5917 | ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; | ||
5918 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT); | ||
5919 | |||
5920 | LEAVE; | ||
5921 | return IPR_RC_JOB_RETURN; | ||
5922 | } | ||
5923 | |||
5924 | /** | ||
5925 | * ipr_reset_mode_sense_page24_failed - Handle failure of IOAFP mode sense | ||
5926 | * @ipr_cmd: ipr command struct | ||
5927 | * | ||
5928 | * This function handles the failure of a Mode Sense to the IOAFP. | ||
5929 | * Some adapters do not handle all mode pages. | ||
5930 | * | ||
5931 | * Return value: | ||
5932 | * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN | ||
5933 | **/ | ||
5934 | static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd) | ||
5935 | { | ||
5936 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | ||
5937 | |||
5938 | if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { | ||
5939 | ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; | ||
5940 | return IPR_RC_JOB_CONTINUE; | ||
5941 | } | ||
5942 | |||
5943 | return ipr_reset_cmd_failed(ipr_cmd); | ||
5944 | } | ||
5945 | |||
5946 | /** | ||
5947 | * ipr_ioafp_mode_sense_page24 - Issue Page 24 Mode Sense to IOA | ||
5948 | * @ipr_cmd: ipr command struct | ||
5949 | * | ||
5950 | * This function send a mode sense to the IOA to retrieve | ||
5951 | * the IOA Advanced Function Control mode page. | ||
5952 | * | ||
5953 | * Return value: | ||
5954 | * IPR_RC_JOB_RETURN | ||
5955 | **/ | ||
5956 | static int ipr_ioafp_mode_sense_page24(struct ipr_cmnd *ipr_cmd) | ||
5957 | { | ||
5958 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
5959 | |||
5960 | ENTER; | ||
5961 | ipr_build_mode_sense(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), | ||
5962 | 0x24, ioa_cfg->vpd_cbs_dma + | ||
5963 | offsetof(struct ipr_misc_cbs, mode_pages), | ||
5964 | sizeof(struct ipr_mode_pages)); | ||
5965 | |||
5966 | ipr_cmd->job_step = ipr_ioafp_mode_select_page24; | ||
5967 | ipr_cmd->job_step_failed = ipr_reset_mode_sense_page24_failed; | ||
5968 | |||
5969 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT); | ||
5970 | |||
5971 | LEAVE; | ||
5972 | return IPR_RC_JOB_RETURN; | ||
5973 | } | ||
5974 | |||
5975 | /** | ||
5885 | * ipr_init_res_table - Initialize the resource table | 5976 | * ipr_init_res_table - Initialize the resource table |
5886 | * @ipr_cmd: ipr command struct | 5977 | * @ipr_cmd: ipr command struct |
5887 | * | 5978 | * |
@@ -5949,7 +6040,10 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd) | |||
5949 | } | 6040 | } |
5950 | } | 6041 | } |
5951 | 6042 | ||
5952 | ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; | 6043 | if (ioa_cfg->dual_raid && ipr_dual_ioa_raid) |
6044 | ipr_cmd->job_step = ipr_ioafp_mode_sense_page24; | ||
6045 | else | ||
6046 | ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; | ||
5953 | 6047 | ||
5954 | LEAVE; | 6048 | LEAVE; |
5955 | return IPR_RC_JOB_CONTINUE; | 6049 | return IPR_RC_JOB_CONTINUE; |
@@ -5971,8 +6065,11 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd) | |||
5971 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; | 6065 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; |
5972 | struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl; | 6066 | struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl; |
5973 | struct ipr_inquiry_page3 *ucode_vpd = &ioa_cfg->vpd_cbs->page3_data; | 6067 | struct ipr_inquiry_page3 *ucode_vpd = &ioa_cfg->vpd_cbs->page3_data; |
6068 | struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap; | ||
5974 | 6069 | ||
5975 | ENTER; | 6070 | ENTER; |
6071 | if (cap->cap & IPR_CAP_DUAL_IOA_RAID) | ||
6072 | ioa_cfg->dual_raid = 1; | ||
5976 | dev_info(&ioa_cfg->pdev->dev, "Adapter firmware version: %02X%02X%02X%02X\n", | 6073 | dev_info(&ioa_cfg->pdev->dev, "Adapter firmware version: %02X%02X%02X%02X\n", |
5977 | ucode_vpd->major_release, ucode_vpd->card_type, | 6074 | ucode_vpd->major_release, ucode_vpd->card_type, |
5978 | ucode_vpd->minor_release[0], ucode_vpd->minor_release[1]); | 6075 | ucode_vpd->minor_release[0], ucode_vpd->minor_release[1]); |
@@ -6056,6 +6153,37 @@ static int ipr_inquiry_page_supported(struct ipr_inquiry_page0 *page0, u8 page) | |||
6056 | } | 6153 | } |
6057 | 6154 | ||
6058 | /** | 6155 | /** |
6156 | * ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter. | ||
6157 | * @ipr_cmd: ipr command struct | ||
6158 | * | ||
6159 | * This function sends a Page 0xD0 inquiry to the adapter | ||
6160 | * to retrieve adapter capabilities. | ||
6161 | * | ||
6162 | * Return value: | ||
6163 | * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN | ||
6164 | **/ | ||
6165 | static int ipr_ioafp_cap_inquiry(struct ipr_cmnd *ipr_cmd) | ||
6166 | { | ||
6167 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
6168 | struct ipr_inquiry_page0 *page0 = &ioa_cfg->vpd_cbs->page0_data; | ||
6169 | struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap; | ||
6170 | |||
6171 | ENTER; | ||
6172 | ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg; | ||
6173 | memset(cap, 0, sizeof(*cap)); | ||
6174 | |||
6175 | if (ipr_inquiry_page_supported(page0, 0xD0)) { | ||
6176 | ipr_ioafp_inquiry(ipr_cmd, 1, 0xD0, | ||
6177 | ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, cap), | ||
6178 | sizeof(struct ipr_inquiry_cap)); | ||
6179 | return IPR_RC_JOB_RETURN; | ||
6180 | } | ||
6181 | |||
6182 | LEAVE; | ||
6183 | return IPR_RC_JOB_CONTINUE; | ||
6184 | } | ||
6185 | |||
6186 | /** | ||
6059 | * ipr_ioafp_page3_inquiry - Send a Page 3 Inquiry to the adapter. | 6187 | * ipr_ioafp_page3_inquiry - Send a Page 3 Inquiry to the adapter. |
6060 | * @ipr_cmd: ipr command struct | 6188 | * @ipr_cmd: ipr command struct |
6061 | * | 6189 | * |
@@ -6075,7 +6203,7 @@ static int ipr_ioafp_page3_inquiry(struct ipr_cmnd *ipr_cmd) | |||
6075 | if (!ipr_inquiry_page_supported(page0, 1)) | 6203 | if (!ipr_inquiry_page_supported(page0, 1)) |
6076 | ioa_cfg->cache_state = CACHE_NONE; | 6204 | ioa_cfg->cache_state = CACHE_NONE; |
6077 | 6205 | ||
6078 | ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg; | 6206 | ipr_cmd->job_step = ipr_ioafp_cap_inquiry; |
6079 | 6207 | ||
6080 | ipr_ioafp_inquiry(ipr_cmd, 1, 3, | 6208 | ipr_ioafp_inquiry(ipr_cmd, 1, 3, |
6081 | ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, page3_data), | 6209 | ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, page3_data), |
@@ -6679,12 +6807,14 @@ static int ipr_reset_shutdown_ioa(struct ipr_cmnd *ipr_cmd) | |||
6679 | ipr_cmd->ioarcb.cmd_pkt.cdb[0] = IPR_IOA_SHUTDOWN; | 6807 | ipr_cmd->ioarcb.cmd_pkt.cdb[0] = IPR_IOA_SHUTDOWN; |
6680 | ipr_cmd->ioarcb.cmd_pkt.cdb[1] = shutdown_type; | 6808 | ipr_cmd->ioarcb.cmd_pkt.cdb[1] = shutdown_type; |
6681 | 6809 | ||
6682 | if (shutdown_type == IPR_SHUTDOWN_ABBREV) | 6810 | if (shutdown_type == IPR_SHUTDOWN_NORMAL) |
6683 | timeout = IPR_ABBREV_SHUTDOWN_TIMEOUT; | 6811 | timeout = IPR_SHUTDOWN_TIMEOUT; |
6684 | else if (shutdown_type == IPR_SHUTDOWN_PREPARE_FOR_NORMAL) | 6812 | else if (shutdown_type == IPR_SHUTDOWN_PREPARE_FOR_NORMAL) |
6685 | timeout = IPR_INTERNAL_TIMEOUT; | 6813 | timeout = IPR_INTERNAL_TIMEOUT; |
6814 | else if (ioa_cfg->dual_raid && ipr_dual_ioa_raid) | ||
6815 | timeout = IPR_DUAL_IOA_ABBR_SHUTDOWN_TO; | ||
6686 | else | 6816 | else |
6687 | timeout = IPR_SHUTDOWN_TIMEOUT; | 6817 | timeout = IPR_ABBREV_SHUTDOWN_TIMEOUT; |
6688 | 6818 | ||
6689 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, timeout); | 6819 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, timeout); |
6690 | 6820 | ||
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index c7e045aa16a0..daa96ee19d4f 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -37,8 +37,8 @@ | |||
37 | /* | 37 | /* |
38 | * Literals | 38 | * Literals |
39 | */ | 39 | */ |
40 | #define IPR_DRIVER_VERSION "2.3.2" | 40 | #define IPR_DRIVER_VERSION "2.4.0" |
41 | #define IPR_DRIVER_DATE "(March 23, 2007)" | 41 | #define IPR_DRIVER_DATE "(April 24, 2007)" |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding | 44 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding |
@@ -180,6 +180,7 @@ | |||
180 | #define IPR_SHUTDOWN_TIMEOUT (ipr_fastfail ? 60 * HZ : 10 * 60 * HZ) | 180 | #define IPR_SHUTDOWN_TIMEOUT (ipr_fastfail ? 60 * HZ : 10 * 60 * HZ) |
181 | #define IPR_VSET_RW_TIMEOUT (ipr_fastfail ? 30 * HZ : 2 * 60 * HZ) | 181 | #define IPR_VSET_RW_TIMEOUT (ipr_fastfail ? 30 * HZ : 2 * 60 * HZ) |
182 | #define IPR_ABBREV_SHUTDOWN_TIMEOUT (10 * HZ) | 182 | #define IPR_ABBREV_SHUTDOWN_TIMEOUT (10 * HZ) |
183 | #define IPR_DUAL_IOA_ABBR_SHUTDOWN_TO (2 * 60 * HZ) | ||
183 | #define IPR_DEVICE_RESET_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) | 184 | #define IPR_DEVICE_RESET_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) |
184 | #define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) | 185 | #define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) |
185 | #define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) | 186 | #define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) |
@@ -603,6 +604,12 @@ struct ipr_mode_page28 { | |||
603 | struct ipr_dev_bus_entry bus[0]; | 604 | struct ipr_dev_bus_entry bus[0]; |
604 | }__attribute__((packed)); | 605 | }__attribute__((packed)); |
605 | 606 | ||
607 | struct ipr_mode_page24 { | ||
608 | struct ipr_mode_page_hdr hdr; | ||
609 | u8 flags; | ||
610 | #define IPR_ENABLE_DUAL_IOA_AF 0x80 | ||
611 | }__attribute__((packed)); | ||
612 | |||
606 | struct ipr_ioa_vpd { | 613 | struct ipr_ioa_vpd { |
607 | struct ipr_std_inq_data std_inq_data; | 614 | struct ipr_std_inq_data std_inq_data; |
608 | u8 ascii_part_num[12]; | 615 | u8 ascii_part_num[12]; |
@@ -625,6 +632,19 @@ struct ipr_inquiry_page3 { | |||
625 | u8 patch_number[4]; | 632 | u8 patch_number[4]; |
626 | }__attribute__((packed)); | 633 | }__attribute__((packed)); |
627 | 634 | ||
635 | struct ipr_inquiry_cap { | ||
636 | u8 peri_qual_dev_type; | ||
637 | u8 page_code; | ||
638 | u8 reserved1; | ||
639 | u8 page_length; | ||
640 | u8 ascii_len; | ||
641 | u8 reserved2; | ||
642 | u8 sis_version[2]; | ||
643 | u8 cap; | ||
644 | #define IPR_CAP_DUAL_IOA_RAID 0x80 | ||
645 | u8 reserved3[15]; | ||
646 | }__attribute__((packed)); | ||
647 | |||
628 | #define IPR_INQUIRY_PAGE0_ENTRIES 20 | 648 | #define IPR_INQUIRY_PAGE0_ENTRIES 20 |
629 | struct ipr_inquiry_page0 { | 649 | struct ipr_inquiry_page0 { |
630 | u8 peri_qual_dev_type; | 650 | u8 peri_qual_dev_type; |
@@ -963,6 +983,7 @@ struct ipr_misc_cbs { | |||
963 | struct ipr_ioa_vpd ioa_vpd; | 983 | struct ipr_ioa_vpd ioa_vpd; |
964 | struct ipr_inquiry_page0 page0_data; | 984 | struct ipr_inquiry_page0 page0_data; |
965 | struct ipr_inquiry_page3 page3_data; | 985 | struct ipr_inquiry_page3 page3_data; |
986 | struct ipr_inquiry_cap cap; | ||
966 | struct ipr_mode_pages mode_pages; | 987 | struct ipr_mode_pages mode_pages; |
967 | struct ipr_supported_device supp_dev; | 988 | struct ipr_supported_device supp_dev; |
968 | }; | 989 | }; |
@@ -1069,6 +1090,7 @@ struct ipr_ioa_cfg { | |||
1069 | u8 allow_cmds:1; | 1090 | u8 allow_cmds:1; |
1070 | u8 allow_ml_add_del:1; | 1091 | u8 allow_ml_add_del:1; |
1071 | u8 needs_hard_reset:1; | 1092 | u8 needs_hard_reset:1; |
1093 | u8 dual_raid:1; | ||
1072 | 1094 | ||
1073 | enum ipr_cache_state cache_state; | 1095 | enum ipr_cache_state cache_state; |
1074 | u16 type; /* CCIN of the card */ | 1096 | u16 type; /* CCIN of the card */ |