aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ipr.c
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2007-04-26 17:00:16 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-05-06 10:33:20 -0400
commitac09c349080008fdd54a15616a1b14771772d867 (patch)
treec4099da7d7c6b1072ea68145b044e0390756c08d /drivers/scsi/ipr.c
parent8cf093e275d0d703d3e6c23725e340006082beec (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>
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r--drivers/scsi/ipr.c140
1 files changed, 135 insertions, 5 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;
92static unsigned int ipr_transop_timeout = 0; 92static unsigned int ipr_transop_timeout = 0;
93static unsigned int ipr_enable_cache = 1; 93static unsigned int ipr_enable_cache = 1;
94static unsigned int ipr_debug = 0; 94static unsigned int ipr_debug = 0;
95static unsigned int ipr_dual_ioa_raid = 1;
95static DEFINE_SPINLOCK(ipr_driver_lock); 96static 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);
158MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)"); 159MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
159module_param_named(debug, ipr_debug, int, 0); 160module_param_named(debug, ipr_debug, int, 0);
160MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)"); 161MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
162module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0);
163MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)");
161MODULE_LICENSE("GPL"); 164MODULE_LICENSE("GPL");
162MODULE_VERSION(IPR_DRIVER_VERSION); 165MODULE_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 **/
5896static 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 **/
5934static 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 **/
5956static 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 **/
6165static 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