diff options
author | James Smart <james.smart@emulex.com> | 2013-04-17 20:16:15 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-05-02 15:46:20 -0400 |
commit | 96f7077f671254e957a2815e54bb20e8d50f0bbc (patch) | |
tree | 491594535761bfcddeea83fbc56976211d8cb961 /drivers/scsi/lpfc/lpfc_init.c | |
parent | 09294d4623a3149ae2f5d35acf9d119bd957ddd8 (diff) |
[SCSI] lpfc 8.3.39: Fix driver issues with large s/g lists for BlockGuard
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 130 |
1 files changed, 93 insertions, 37 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b2227fc17c9c..1874b327494e 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -4730,23 +4730,52 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) | |||
4730 | return -ENOMEM; | 4730 | return -ENOMEM; |
4731 | 4731 | ||
4732 | /* | 4732 | /* |
4733 | * Since the sg_tablesize is module parameter, the sg_dma_buf_size | 4733 | * Since lpfc_sg_seg_cnt is module parameter, the sg_dma_buf_size |
4734 | * used to create the sg_dma_buf_pool must be dynamically calculated. | 4734 | * used to create the sg_dma_buf_pool must be dynamically calculated. |
4735 | * 2 segments are added since the IOCB needs a command and response bde. | ||
4736 | */ | 4735 | */ |
4737 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + | ||
4738 | sizeof(struct fcp_rsp) + | ||
4739 | ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct ulp_bde64)); | ||
4740 | 4736 | ||
4737 | /* Initialize the host templates the configured values. */ | ||
4738 | lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt; | ||
4739 | lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt; | ||
4740 | |||
4741 | /* There are going to be 2 reserved BDEs: 1 FCP cmnd + 1 FCP rsp */ | ||
4741 | if (phba->cfg_enable_bg) { | 4742 | if (phba->cfg_enable_bg) { |
4742 | phba->cfg_sg_seg_cnt = LPFC_MAX_BPL_SEG_CNT; | 4743 | /* |
4743 | phba->cfg_sg_dma_buf_size += | 4744 | * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd, |
4744 | phba->cfg_prot_sg_seg_cnt * sizeof(struct ulp_bde64); | 4745 | * the FCP rsp, and a BDE for each. Sice we have no control |
4746 | * over how many protection data segments the SCSI Layer | ||
4747 | * will hand us (ie: there could be one for every block | ||
4748 | * in the IO), we just allocate enough BDEs to accomidate | ||
4749 | * our max amount and we need to limit lpfc_sg_seg_cnt to | ||
4750 | * minimize the risk of running out. | ||
4751 | */ | ||
4752 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + | ||
4753 | sizeof(struct fcp_rsp) + | ||
4754 | (LPFC_MAX_SG_SEG_CNT * sizeof(struct ulp_bde64)); | ||
4755 | |||
4756 | if (phba->cfg_sg_seg_cnt > LPFC_MAX_SG_SEG_CNT_DIF) | ||
4757 | phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SEG_CNT_DIF; | ||
4758 | |||
4759 | /* Total BDEs in BPL for scsi_sg_list and scsi_sg_prot_list */ | ||
4760 | phba->cfg_total_seg_cnt = LPFC_MAX_SG_SEG_CNT; | ||
4761 | } else { | ||
4762 | /* | ||
4763 | * The scsi_buf for a regular I/O will hold the FCP cmnd, | ||
4764 | * the FCP rsp, a BDE for each, and a BDE for up to | ||
4765 | * cfg_sg_seg_cnt data segments. | ||
4766 | */ | ||
4767 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + | ||
4768 | sizeof(struct fcp_rsp) + | ||
4769 | ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct ulp_bde64)); | ||
4770 | |||
4771 | /* Total BDEs in BPL for scsi_sg_list */ | ||
4772 | phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + 2; | ||
4745 | } | 4773 | } |
4746 | 4774 | ||
4747 | /* Also reinitialize the host templates with new values. */ | 4775 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP, |
4748 | lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt; | 4776 | "9088 sg_tablesize:%d dmabuf_size:%d total_bde:%d\n", |
4749 | lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt; | 4777 | phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size, |
4778 | phba->cfg_total_seg_cnt); | ||
4750 | 4779 | ||
4751 | phba->max_vpi = LPFC_MAX_VPI; | 4780 | phba->max_vpi = LPFC_MAX_VPI; |
4752 | /* This will be set to correct value after config_port mbox */ | 4781 | /* This will be set to correct value after config_port mbox */ |
@@ -4814,11 +4843,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4814 | { | 4843 | { |
4815 | struct lpfc_sli *psli; | 4844 | struct lpfc_sli *psli; |
4816 | LPFC_MBOXQ_t *mboxq; | 4845 | LPFC_MBOXQ_t *mboxq; |
4817 | int rc, i, hbq_count, buf_size, dma_buf_size, max_buf_size; | 4846 | int rc, i, hbq_count, max_buf_size; |
4818 | uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0}; | 4847 | uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0}; |
4819 | struct lpfc_mqe *mqe; | 4848 | struct lpfc_mqe *mqe; |
4820 | int longs; | 4849 | int longs; |
4821 | int sges_per_segment; | ||
4822 | 4850 | ||
4823 | /* Before proceed, wait for POST done and device ready */ | 4851 | /* Before proceed, wait for POST done and device ready */ |
4824 | rc = lpfc_sli4_post_status_check(phba); | 4852 | rc = lpfc_sli4_post_status_check(phba); |
@@ -4886,11 +4914,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4886 | phba->fc_map[1] = LPFC_FCOE_FCF_MAP1; | 4914 | phba->fc_map[1] = LPFC_FCOE_FCF_MAP1; |
4887 | phba->fc_map[2] = LPFC_FCOE_FCF_MAP2; | 4915 | phba->fc_map[2] = LPFC_FCOE_FCF_MAP2; |
4888 | 4916 | ||
4889 | /* With BlockGuard we can have multiple SGEs per Data Segemnt */ | ||
4890 | sges_per_segment = 1; | ||
4891 | if (phba->cfg_enable_bg) | ||
4892 | sges_per_segment = 2; | ||
4893 | |||
4894 | /* | 4917 | /* |
4895 | * For SLI4, instead of using ring 0 (LPFC_FCP_RING) for FCP commands | 4918 | * For SLI4, instead of using ring 0 (LPFC_FCP_RING) for FCP commands |
4896 | * we will associate a new ring, for each FCP fastpath EQ/CQ/WQ tuple. | 4919 | * we will associate a new ring, for each FCP fastpath EQ/CQ/WQ tuple. |
@@ -4910,29 +4933,62 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4910 | max_buf_size = (2 * SLI4_PAGE_SIZE); | 4933 | max_buf_size = (2 * SLI4_PAGE_SIZE); |
4911 | if (phba->cfg_sg_seg_cnt > LPFC_MAX_SGL_SEG_CNT - 2) | 4934 | if (phba->cfg_sg_seg_cnt > LPFC_MAX_SGL_SEG_CNT - 2) |
4912 | phba->cfg_sg_seg_cnt = LPFC_MAX_SGL_SEG_CNT - 2; | 4935 | phba->cfg_sg_seg_cnt = LPFC_MAX_SGL_SEG_CNT - 2; |
4913 | max_buf_size += (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); | ||
4914 | 4936 | ||
4915 | /* | 4937 | /* |
4916 | * Since the sg_tablesize is module parameter, the sg_dma_buf_size | 4938 | * Since lpfc_sg_seg_cnt is module parameter, the sg_dma_buf_size |
4917 | * used to create the sg_dma_buf_pool must be dynamically calculated. | 4939 | * used to create the sg_dma_buf_pool must be dynamically calculated. |
4918 | * 2 segments are added since the IOCB needs a command and response bde. | ||
4919 | * To insure that the scsi sgl does not cross a 4k page boundary only | ||
4920 | * sgl sizes of must be a power of 2. | ||
4921 | */ | 4940 | */ |
4922 | buf_size = (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) + | 4941 | |
4923 | (((phba->cfg_sg_seg_cnt * sges_per_segment) + 2) * | 4942 | if (phba->cfg_enable_bg) { |
4924 | sizeof(struct sli4_sge))); | 4943 | /* |
4925 | 4944 | * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd, | |
4926 | for (dma_buf_size = LPFC_SLI4_MIN_BUF_SIZE; | 4945 | * the FCP rsp, and a SGE for each. Sice we have no control |
4927 | dma_buf_size < max_buf_size && buf_size > dma_buf_size; | 4946 | * over how many protection data segments the SCSI Layer |
4928 | dma_buf_size = dma_buf_size << 1) | 4947 | * will hand us (ie: there could be one for every block |
4929 | ; | 4948 | * in the IO), we just allocate enough SGEs to accomidate |
4930 | if (dma_buf_size == max_buf_size) | 4949 | * our max amount and we need to limit lpfc_sg_seg_cnt to |
4931 | phba->cfg_sg_seg_cnt = (dma_buf_size - | 4950 | * minimize the risk of running out. |
4932 | sizeof(struct fcp_cmnd) - sizeof(struct fcp_rsp) - | 4951 | */ |
4933 | (2 * sizeof(struct sli4_sge))) / | 4952 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + |
4934 | sizeof(struct sli4_sge); | 4953 | sizeof(struct fcp_rsp) + max_buf_size; |
4935 | phba->cfg_sg_dma_buf_size = dma_buf_size; | 4954 | |
4955 | /* Total SGEs for scsi_sg_list and scsi_sg_prot_list */ | ||
4956 | phba->cfg_total_seg_cnt = LPFC_MAX_SGL_SEG_CNT; | ||
4957 | |||
4958 | if (phba->cfg_sg_seg_cnt > LPFC_MAX_SG_SLI4_SEG_CNT_DIF) | ||
4959 | phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SLI4_SEG_CNT_DIF; | ||
4960 | } else { | ||
4961 | /* | ||
4962 | * The scsi_buf for a regular I/O will hold the FCP cmnd, | ||
4963 | * the FCP rsp, a SGE for each, and a SGE for up to | ||
4964 | * cfg_sg_seg_cnt data segments. | ||
4965 | */ | ||
4966 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + | ||
4967 | sizeof(struct fcp_rsp) + | ||
4968 | ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge)); | ||
4969 | |||
4970 | /* Total SGEs for scsi_sg_list */ | ||
4971 | phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + 2; | ||
4972 | /* | ||
4973 | * NOTE: if (phba->cfg_sg_seg_cnt + 2) <= 256 we only need | ||
4974 | * to post 1 page for the SGL. | ||
4975 | */ | ||
4976 | } | ||
4977 | |||
4978 | /* Initialize the host templates with the updated values. */ | ||
4979 | lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt; | ||
4980 | lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt; | ||
4981 | |||
4982 | if (phba->cfg_sg_dma_buf_size <= LPFC_MIN_SG_SLI4_BUF_SZ) | ||
4983 | phba->cfg_sg_dma_buf_size = LPFC_MIN_SG_SLI4_BUF_SZ; | ||
4984 | else | ||
4985 | phba->cfg_sg_dma_buf_size = | ||
4986 | SLI4_PAGE_ALIGN(phba->cfg_sg_dma_buf_size); | ||
4987 | |||
4988 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP, | ||
4989 | "9087 sg_tablesize:%d dmabuf_size:%d total_sge:%d\n", | ||
4990 | phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size, | ||
4991 | phba->cfg_total_seg_cnt); | ||
4936 | 4992 | ||
4937 | /* Initialize buffer queue management fields */ | 4993 | /* Initialize buffer queue management fields */ |
4938 | hbq_count = lpfc_sli_hbq_count(); | 4994 | hbq_count = lpfc_sli_hbq_count(); |