diff options
author | James Smart <james.smart@emulex.com> | 2010-06-08 18:31:54 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-27 13:01:38 -0400 |
commit | d7c479929b6804f4e9d5fb5f721aba31622f3d97 (patch) | |
tree | e849efe2d961fd7e1a8d8c9410f6c68ab5a6c03c | |
parent | dbb6b3ab10464aa11df74c0d0a14e869a8c6fd1b (diff) |
[SCSI] lpfc 8.3.14: SCSI and SLI API fixes
- Fixed accounting of allocated SCSI buffers when post sgl fails.
- Restrict scsi buffer allocation based on LUN count (sdev_cnt).
- Create __lpfc_sli_free_rpi that doesn't take out the hbalock.
- Modify lpfc_sli_free_rpi to call __lpfc_sli_free_rpi.
- Call __lpfc_sli_free_rpi in lpfc_cleanup_pending_mbox.
- Do not swap the strings returned in mailbox commands and do
not swap byte aligned data in VPD.
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 20 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 14 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 34 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 1 |
8 files changed, 62 insertions, 11 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index fcfc495d1e0d..bb40fcbe17c5 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -815,6 +815,7 @@ struct lpfc_hba { | |||
815 | #define HBA_MENLO_SUPPORT 0x1 /* HBA supports menlo commands */ | 815 | #define HBA_MENLO_SUPPORT 0x1 /* HBA supports menlo commands */ |
816 | uint32_t iocb_cnt; | 816 | uint32_t iocb_cnt; |
817 | uint32_t iocb_max; | 817 | uint32_t iocb_max; |
818 | atomic_t sdev_cnt; | ||
818 | }; | 819 | }; |
819 | 820 | ||
820 | static inline struct Scsi_Host * | 821 | static inline struct Scsi_Host * |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 361f4e7e23e4..03f4ddc18572 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -191,6 +191,7 @@ irqreturn_t lpfc_sli4_sp_intr_handler(int, void *); | |||
191 | irqreturn_t lpfc_sli4_fp_intr_handler(int, void *); | 191 | irqreturn_t lpfc_sli4_fp_intr_handler(int, void *); |
192 | 192 | ||
193 | void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *); | 193 | void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *); |
194 | void lpfc_sli4_swap_str(struct lpfc_hba *, LPFC_MBOXQ_t *); | ||
194 | void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *); | 195 | void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *); |
195 | void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *); | 196 | void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *); |
196 | void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *); | 197 | void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *); |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 7cd5c47a66ea..9fcad20491ef 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -3845,6 +3845,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
3845 | mempool_free(mbox, phba->mbox_mem_pool); | 3845 | mempool_free(mbox, phba->mbox_mem_pool); |
3846 | } | 3846 | } |
3847 | lpfc_no_rpi(phba, ndlp); | 3847 | lpfc_no_rpi(phba, ndlp); |
3848 | |||
3848 | ndlp->nlp_rpi = 0; | 3849 | ndlp->nlp_rpi = 0; |
3849 | ndlp->nlp_flag &= ~NLP_RPI_VALID; | 3850 | ndlp->nlp_flag &= ~NLP_RPI_VALID; |
3850 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 3851 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 08db674ec580..fb06933f8e6c 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -4919,6 +4919,7 @@ lpfc_create_shost(struct lpfc_hba *phba) | |||
4919 | phba->fc_altov = FF_DEF_ALTOV; | 4919 | phba->fc_altov = FF_DEF_ALTOV; |
4920 | phba->fc_arbtov = FF_DEF_ARBTOV; | 4920 | phba->fc_arbtov = FF_DEF_ARBTOV; |
4921 | 4921 | ||
4922 | atomic_set(&phba->sdev_cnt, 0); | ||
4922 | vport = lpfc_create_port(phba, phba->brd_no, &phba->pcidev->dev); | 4923 | vport = lpfc_create_port(phba, phba->brd_no, &phba->pcidev->dev); |
4923 | if (!vport) | 4924 | if (!vport) |
4924 | return -ENODEV; | 4925 | return -ENODEV; |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 196371fae242..cb5d93b41b50 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -955,6 +955,26 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
955 | return; | 955 | return; |
956 | } | 956 | } |
957 | 957 | ||
958 | void | ||
959 | lpfc_sli4_swap_str(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | ||
960 | { | ||
961 | MAILBOX_t *mb = &pmb->u.mb; | ||
962 | struct lpfc_mqe *mqe; | ||
963 | |||
964 | switch (mb->mbxCommand) { | ||
965 | case MBX_READ_REV: | ||
966 | mqe = &pmb->u.mqe; | ||
967 | lpfc_sli_pcimem_bcopy(mqe->un.read_rev.fw_name, | ||
968 | mqe->un.read_rev.fw_name, 16); | ||
969 | lpfc_sli_pcimem_bcopy(mqe->un.read_rev.ulp_fw_name, | ||
970 | mqe->un.read_rev.ulp_fw_name, 16); | ||
971 | break; | ||
972 | default: | ||
973 | break; | ||
974 | } | ||
975 | return; | ||
976 | } | ||
977 | |||
958 | /** | 978 | /** |
959 | * lpfc_build_hbq_profile2 - Set up the HBQ Selection Profile 2 | 979 | * lpfc_build_hbq_profile2 - Set up the HBQ Selection Profile 2 |
960 | * @hbqmb: pointer to the HBQ configuration data structure in mailbox command. | 980 | * @hbqmb: pointer to the HBQ configuration data structure in mailbox command. |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f68753ea941f..7b66b71a14fe 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -747,7 +747,6 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
747 | int status = 0, index; | 747 | int status = 0, index; |
748 | int bcnt; | 748 | int bcnt; |
749 | int non_sequential_xri = 0; | 749 | int non_sequential_xri = 0; |
750 | int rc = 0; | ||
751 | LIST_HEAD(sblist); | 750 | LIST_HEAD(sblist); |
752 | 751 | ||
753 | for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { | 752 | for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { |
@@ -860,7 +859,6 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
860 | if (status) { | 859 | if (status) { |
861 | /* Put this back on the abort scsi list */ | 860 | /* Put this back on the abort scsi list */ |
862 | psb->exch_busy = 1; | 861 | psb->exch_busy = 1; |
863 | rc++; | ||
864 | } else { | 862 | } else { |
865 | psb->exch_busy = 0; | 863 | psb->exch_busy = 0; |
866 | psb->status = IOSTAT_SUCCESS; | 864 | psb->status = IOSTAT_SUCCESS; |
@@ -879,7 +877,6 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
879 | if (status) { | 877 | if (status) { |
880 | /* Put this back on the abort scsi list */ | 878 | /* Put this back on the abort scsi list */ |
881 | psb->exch_busy = 1; | 879 | psb->exch_busy = 1; |
882 | rc++; | ||
883 | } else { | 880 | } else { |
884 | psb->exch_busy = 0; | 881 | psb->exch_busy = 0; |
885 | psb->status = IOSTAT_SUCCESS; | 882 | psb->status = IOSTAT_SUCCESS; |
@@ -889,7 +886,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
889 | } | 886 | } |
890 | } | 887 | } |
891 | 888 | ||
892 | return bcnt + non_sequential_xri - rc; | 889 | return bcnt + non_sequential_xri; |
893 | } | 890 | } |
894 | 891 | ||
895 | /** | 892 | /** |
@@ -3572,11 +3569,13 @@ lpfc_slave_alloc(struct scsi_device *sdev) | |||
3572 | uint32_t total = 0; | 3569 | uint32_t total = 0; |
3573 | uint32_t num_to_alloc = 0; | 3570 | uint32_t num_to_alloc = 0; |
3574 | int num_allocated = 0; | 3571 | int num_allocated = 0; |
3572 | uint32_t sdev_cnt; | ||
3575 | 3573 | ||
3576 | if (!rport || fc_remote_port_chkready(rport)) | 3574 | if (!rport || fc_remote_port_chkready(rport)) |
3577 | return -ENXIO; | 3575 | return -ENXIO; |
3578 | 3576 | ||
3579 | sdev->hostdata = rport->dd_data; | 3577 | sdev->hostdata = rport->dd_data; |
3578 | sdev_cnt = atomic_inc_return(&phba->sdev_cnt); | ||
3580 | 3579 | ||
3581 | /* | 3580 | /* |
3582 | * Populate the cmds_per_lun count scsi_bufs into this host's globally | 3581 | * Populate the cmds_per_lun count scsi_bufs into this host's globally |
@@ -3588,6 +3587,10 @@ lpfc_slave_alloc(struct scsi_device *sdev) | |||
3588 | total = phba->total_scsi_bufs; | 3587 | total = phba->total_scsi_bufs; |
3589 | num_to_alloc = vport->cfg_lun_queue_depth + 2; | 3588 | num_to_alloc = vport->cfg_lun_queue_depth + 2; |
3590 | 3589 | ||
3590 | /* If allocated buffers are enough do nothing */ | ||
3591 | if ((sdev_cnt * (vport->cfg_lun_queue_depth + 2)) < total) | ||
3592 | return 0; | ||
3593 | |||
3591 | /* Allow some exchanges to be available always to complete discovery */ | 3594 | /* Allow some exchanges to be available always to complete discovery */ |
3592 | if (total >= phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) { | 3595 | if (total >= phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) { |
3593 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, | 3596 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, |
@@ -3669,6 +3672,9 @@ lpfc_slave_configure(struct scsi_device *sdev) | |||
3669 | static void | 3672 | static void |
3670 | lpfc_slave_destroy(struct scsi_device *sdev) | 3673 | lpfc_slave_destroy(struct scsi_device *sdev) |
3671 | { | 3674 | { |
3675 | struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata; | ||
3676 | struct lpfc_hba *phba = vport->phba; | ||
3677 | atomic_dec(&phba->sdev_cnt); | ||
3672 | sdev->hostdata = NULL; | 3678 | sdev->hostdata = NULL; |
3673 | return; | 3679 | return; |
3674 | } | 3680 | } |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f38c05dc5635..7ddf52682271 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -4236,7 +4236,8 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, | |||
4236 | if (mqe->un.read_rev.avail_vpd_len < *vpd_size) | 4236 | if (mqe->un.read_rev.avail_vpd_len < *vpd_size) |
4237 | *vpd_size = mqe->un.read_rev.avail_vpd_len; | 4237 | *vpd_size = mqe->un.read_rev.avail_vpd_len; |
4238 | 4238 | ||
4239 | lpfc_sli_pcimem_bcopy(dmabuf->virt, vpd, *vpd_size); | 4239 | memcpy(vpd, dmabuf->virt, *vpd_size); |
4240 | |||
4240 | dma_free_coherent(&phba->pcidev->dev, dma_size, | 4241 | dma_free_coherent(&phba->pcidev->dev, dma_size, |
4241 | dmabuf->virt, dmabuf->phys); | 4242 | dmabuf->virt, dmabuf->phys); |
4242 | kfree(dmabuf); | 4243 | kfree(dmabuf); |
@@ -5305,7 +5306,8 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
5305 | if (mcqe_status != MB_CQE_STATUS_SUCCESS) { | 5306 | if (mcqe_status != MB_CQE_STATUS_SUCCESS) { |
5306 | bf_set(lpfc_mqe_status, mb, LPFC_MBX_ERROR_RANGE | mcqe_status); | 5307 | bf_set(lpfc_mqe_status, mb, LPFC_MBX_ERROR_RANGE | mcqe_status); |
5307 | rc = MBXERR_ERROR; | 5308 | rc = MBXERR_ERROR; |
5308 | } | 5309 | } else |
5310 | lpfc_sli4_swap_str(phba, mboxq); | ||
5309 | 5311 | ||
5310 | lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, | 5312 | lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, |
5311 | "(%d):0356 Mailbox cmd x%x (x%x) Status x%x " | 5313 | "(%d):0356 Mailbox cmd x%x (x%x) Status x%x " |
@@ -7790,9 +7792,10 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, | |||
7790 | * if LPFC_MBX_WAKE flag is set the mailbox is completed | 7792 | * if LPFC_MBX_WAKE flag is set the mailbox is completed |
7791 | * else do not free the resources. | 7793 | * else do not free the resources. |
7792 | */ | 7794 | */ |
7793 | if (pmboxq->mbox_flag & LPFC_MBX_WAKE) | 7795 | if (pmboxq->mbox_flag & LPFC_MBX_WAKE) { |
7794 | retval = MBX_SUCCESS; | 7796 | retval = MBX_SUCCESS; |
7795 | else { | 7797 | lpfc_sli4_swap_str(phba, pmboxq); |
7798 | } else { | ||
7796 | retval = MBX_TIMEOUT; | 7799 | retval = MBX_TIMEOUT; |
7797 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 7800 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
7798 | } | 7801 | } |
@@ -11975,12 +11978,26 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
11975 | * available rpis maintained by the driver. | 11978 | * available rpis maintained by the driver. |
11976 | **/ | 11979 | **/ |
11977 | void | 11980 | void |
11981 | __lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) | ||
11982 | { | ||
11983 | if (test_and_clear_bit(rpi, phba->sli4_hba.rpi_bmask)) { | ||
11984 | phba->sli4_hba.rpi_count--; | ||
11985 | phba->sli4_hba.max_cfg_param.rpi_used--; | ||
11986 | } | ||
11987 | } | ||
11988 | |||
11989 | /** | ||
11990 | * lpfc_sli4_free_rpi - Release an rpi for reuse. | ||
11991 | * @phba: pointer to lpfc hba data structure. | ||
11992 | * | ||
11993 | * This routine is invoked to release an rpi to the pool of | ||
11994 | * available rpis maintained by the driver. | ||
11995 | **/ | ||
11996 | void | ||
11978 | lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) | 11997 | lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) |
11979 | { | 11998 | { |
11980 | spin_lock_irq(&phba->hbalock); | 11999 | spin_lock_irq(&phba->hbalock); |
11981 | clear_bit(rpi, phba->sli4_hba.rpi_bmask); | 12000 | __lpfc_sli4_free_rpi(phba, rpi); |
11982 | phba->sli4_hba.rpi_count--; | ||
11983 | phba->sli4_hba.max_cfg_param.rpi_used--; | ||
11984 | spin_unlock_irq(&phba->hbalock); | 12001 | spin_unlock_irq(&phba->hbalock); |
11985 | } | 12002 | } |
11986 | 12003 | ||
@@ -12751,6 +12768,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) | |||
12751 | continue; | 12768 | continue; |
12752 | 12769 | ||
12753 | if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) { | 12770 | if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) { |
12771 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
12772 | __lpfc_sli4_free_rpi(phba, | ||
12773 | mb->u.mb.un.varRegLogin.rpi); | ||
12754 | mp = (struct lpfc_dmabuf *) (mb->context1); | 12774 | mp = (struct lpfc_dmabuf *) (mb->context1); |
12755 | if (mp) { | 12775 | if (mp) { |
12756 | __lpfc_mbuf_free(phba, mp->virt, mp->phys); | 12776 | __lpfc_mbuf_free(phba, mp->virt, mp->phys); |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 7686c1a9a634..c916079fbb35 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -528,6 +528,7 @@ int lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *); | |||
528 | struct lpfc_rpi_hdr *lpfc_sli4_create_rpi_hdr(struct lpfc_hba *); | 528 | struct lpfc_rpi_hdr *lpfc_sli4_create_rpi_hdr(struct lpfc_hba *); |
529 | void lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *); | 529 | void lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *); |
530 | int lpfc_sli4_alloc_rpi(struct lpfc_hba *); | 530 | int lpfc_sli4_alloc_rpi(struct lpfc_hba *); |
531 | void __lpfc_sli4_free_rpi(struct lpfc_hba *, int); | ||
531 | void lpfc_sli4_free_rpi(struct lpfc_hba *, int); | 532 | void lpfc_sli4_free_rpi(struct lpfc_hba *, int); |
532 | void lpfc_sli4_remove_rpis(struct lpfc_hba *); | 533 | void lpfc_sli4_remove_rpis(struct lpfc_hba *); |
533 | void lpfc_sli4_async_event_proc(struct lpfc_hba *); | 534 | void lpfc_sli4_async_event_proc(struct lpfc_hba *); |