diff options
author | James Smart <james.smart@emulex.com> | 2012-05-09 21:16:12 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-05-17 05:29:22 -0400 |
commit | 8a9d2e8003040d2e1cd24ac5e83bb30b68f7f488 (patch) | |
tree | a0fb34a954b174681a7af4706dee3823db4260ce /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | 587a37f6e007e97e4f88f10a51f5d0bc62eb6e0a (diff) |
[SCSI] lpfc 8.3.31: Correct handling of SLI4-port XRI resource-provisioning profile change
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 296 |
1 files changed, 172 insertions, 124 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 88f3a83dbd2e..bf0048a7a302 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -718,72 +718,162 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, | |||
718 | } | 718 | } |
719 | 719 | ||
720 | /** | 720 | /** |
721 | * lpfc_sli4_repost_scsi_sgl_list - Repsot the Scsi buffers sgl pages as block | 721 | * lpfc_sli4_post_scsi_sgl_list - Psot blocks of scsi buffer sgls from a list |
722 | * @phba: pointer to lpfc hba data structure. | 722 | * @phba: pointer to lpfc hba data structure. |
723 | * @post_sblist: pointer to the scsi buffer list. | ||
723 | * | 724 | * |
724 | * This routine walks the list of scsi buffers that have been allocated and | 725 | * This routine walks a list of scsi buffers that was passed in. It attempts |
725 | * repost them to the HBA by using SGL block post. This is needed after a | 726 | * to construct blocks of scsi buffer sgls which contains contiguous xris and |
726 | * pci_function_reset/warm_start or start. The lpfc_hba_down_post_s4 routine | 727 | * uses the non-embedded SGL block post mailbox commands to post to the port. |
727 | * is responsible for moving all scsi buffers on the lpfc_abts_scsi_sgl_list | 728 | * For single SCSI buffer sgl with non-contiguous xri, if any, it shall use |
728 | * to the lpfc_scsi_buf_list. If the repost fails, reject all scsi buffers. | 729 | * embedded SGL post mailbox command for posting. The @post_sblist passed in |
730 | * must be local list, thus no lock is needed when manipulate the list. | ||
729 | * | 731 | * |
730 | * Returns: 0 = success, non-zero failure. | 732 | * Returns: 0 = failure, non-zero number of successfully posted buffers. |
731 | **/ | 733 | **/ |
732 | int | 734 | int |
733 | lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba) | 735 | lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba, |
736 | struct list_head *post_sblist, int sb_count) | ||
734 | { | 737 | { |
735 | struct lpfc_scsi_buf *psb; | 738 | struct lpfc_scsi_buf *psb, *psb_next; |
736 | int index, status, bcnt = 0, rcnt = 0, rc = 0; | 739 | int status; |
737 | LIST_HEAD(sblist); | 740 | int post_cnt = 0, block_cnt = 0, num_posting = 0, num_posted = 0; |
738 | 741 | dma_addr_t pdma_phys_bpl1; | |
739 | for (index = 0; index < phba->sli4_hba.scsi_xri_cnt; index++) { | 742 | int last_xritag = NO_XRI; |
740 | psb = phba->sli4_hba.lpfc_scsi_psb_array[index]; | 743 | LIST_HEAD(prep_sblist); |
741 | if (psb) { | 744 | LIST_HEAD(blck_sblist); |
742 | /* Remove from SCSI buffer list */ | 745 | LIST_HEAD(scsi_sblist); |
743 | list_del(&psb->list); | 746 | |
744 | /* Add it to a local SCSI buffer list */ | 747 | /* sanity check */ |
745 | list_add_tail(&psb->list, &sblist); | 748 | if (sb_count <= 0) |
746 | if (++rcnt == LPFC_NEMBED_MBOX_SGL_CNT) { | 749 | return -EINVAL; |
747 | bcnt = rcnt; | 750 | |
748 | rcnt = 0; | 751 | list_for_each_entry_safe(psb, psb_next, post_sblist, list) { |
752 | list_del_init(&psb->list); | ||
753 | block_cnt++; | ||
754 | if ((last_xritag != NO_XRI) && | ||
755 | (psb->cur_iocbq.sli4_xritag != last_xritag + 1)) { | ||
756 | /* a hole in xri block, form a sgl posting block */ | ||
757 | list_splice_init(&prep_sblist, &blck_sblist); | ||
758 | post_cnt = block_cnt - 1; | ||
759 | /* prepare list for next posting block */ | ||
760 | list_add_tail(&psb->list, &prep_sblist); | ||
761 | block_cnt = 1; | ||
762 | } else { | ||
763 | /* prepare list for next posting block */ | ||
764 | list_add_tail(&psb->list, &prep_sblist); | ||
765 | /* enough sgls for non-embed sgl mbox command */ | ||
766 | if (block_cnt == LPFC_NEMBED_MBOX_SGL_CNT) { | ||
767 | list_splice_init(&prep_sblist, &blck_sblist); | ||
768 | post_cnt = block_cnt; | ||
769 | block_cnt = 0; | ||
749 | } | 770 | } |
750 | } else | 771 | } |
751 | /* A hole present in the XRI array, need to skip */ | 772 | num_posting++; |
752 | bcnt = rcnt; | 773 | last_xritag = psb->cur_iocbq.sli4_xritag; |
753 | 774 | ||
754 | if (index == phba->sli4_hba.scsi_xri_cnt - 1) | 775 | /* end of repost sgl list condition for SCSI buffers */ |
755 | /* End of XRI array for SCSI buffer, complete */ | 776 | if (num_posting == sb_count) { |
756 | bcnt = rcnt; | 777 | if (post_cnt == 0) { |
778 | /* last sgl posting block */ | ||
779 | list_splice_init(&prep_sblist, &blck_sblist); | ||
780 | post_cnt = block_cnt; | ||
781 | } else if (block_cnt == 1) { | ||
782 | /* last single sgl with non-contiguous xri */ | ||
783 | if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE) | ||
784 | pdma_phys_bpl1 = psb->dma_phys_bpl + | ||
785 | SGL_PAGE_SIZE; | ||
786 | else | ||
787 | pdma_phys_bpl1 = 0; | ||
788 | status = lpfc_sli4_post_sgl(phba, | ||
789 | psb->dma_phys_bpl, | ||
790 | pdma_phys_bpl1, | ||
791 | psb->cur_iocbq.sli4_xritag); | ||
792 | if (status) { | ||
793 | /* failure, put on abort scsi list */ | ||
794 | psb->exch_busy = 1; | ||
795 | } else { | ||
796 | /* success, put on SCSI buffer list */ | ||
797 | psb->exch_busy = 0; | ||
798 | psb->status = IOSTAT_SUCCESS; | ||
799 | num_posted++; | ||
800 | } | ||
801 | /* success, put on SCSI buffer sgl list */ | ||
802 | list_add_tail(&psb->list, &scsi_sblist); | ||
803 | } | ||
804 | } | ||
757 | 805 | ||
758 | /* Continue until collect up to a nembed page worth of sgls */ | 806 | /* continue until a nembed page worth of sgls */ |
759 | if (bcnt == 0) | 807 | if (post_cnt == 0) |
760 | continue; | 808 | continue; |
761 | /* Now, post the SCSI buffer list sgls as a block */ | 809 | |
762 | if (!phba->sli4_hba.extents_in_use) | 810 | /* post block of SCSI buffer list sgls */ |
763 | status = lpfc_sli4_post_scsi_sgl_block(phba, | 811 | status = lpfc_sli4_post_scsi_sgl_block(phba, &blck_sblist, |
764 | &sblist, | 812 | post_cnt); |
765 | bcnt); | 813 | |
766 | else | 814 | /* don't reset xirtag due to hole in xri block */ |
767 | status = lpfc_sli4_post_scsi_sgl_blk_ext(phba, | 815 | if (block_cnt == 0) |
768 | &sblist, | 816 | last_xritag = NO_XRI; |
769 | bcnt); | 817 | |
770 | /* Reset SCSI buffer count for next round of posting */ | 818 | /* reset SCSI buffer post count for next round of posting */ |
771 | bcnt = 0; | 819 | post_cnt = 0; |
772 | while (!list_empty(&sblist)) { | 820 | |
773 | list_remove_head(&sblist, psb, struct lpfc_scsi_buf, | 821 | /* put posted SCSI buffer-sgl posted on SCSI buffer sgl list */ |
774 | list); | 822 | while (!list_empty(&blck_sblist)) { |
823 | list_remove_head(&blck_sblist, psb, | ||
824 | struct lpfc_scsi_buf, list); | ||
775 | if (status) { | 825 | if (status) { |
776 | /* Put this back on the abort scsi list */ | 826 | /* failure, put on abort scsi list */ |
777 | psb->exch_busy = 1; | 827 | psb->exch_busy = 1; |
778 | rc++; | ||
779 | } else { | 828 | } else { |
829 | /* success, put on SCSI buffer list */ | ||
780 | psb->exch_busy = 0; | 830 | psb->exch_busy = 0; |
781 | psb->status = IOSTAT_SUCCESS; | 831 | psb->status = IOSTAT_SUCCESS; |
832 | num_posted++; | ||
782 | } | 833 | } |
783 | /* Put it back into the SCSI buffer list */ | 834 | list_add_tail(&psb->list, &scsi_sblist); |
784 | lpfc_release_scsi_buf_s4(phba, psb); | ||
785 | } | 835 | } |
786 | } | 836 | } |
837 | /* Push SCSI buffers with sgl posted to the availble list */ | ||
838 | while (!list_empty(&scsi_sblist)) { | ||
839 | list_remove_head(&scsi_sblist, psb, | ||
840 | struct lpfc_scsi_buf, list); | ||
841 | lpfc_release_scsi_buf_s4(phba, psb); | ||
842 | } | ||
843 | return num_posted; | ||
844 | } | ||
845 | |||
846 | /** | ||
847 | * lpfc_sli4_repost_scsi_sgl_list - Repsot all the allocated scsi buffer sgls | ||
848 | * @phba: pointer to lpfc hba data structure. | ||
849 | * | ||
850 | * This routine walks the list of scsi buffers that have been allocated and | ||
851 | * repost them to the port by using SGL block post. This is needed after a | ||
852 | * pci_function_reset/warm_start or start. The lpfc_hba_down_post_s4 routine | ||
853 | * is responsible for moving all scsi buffers on the lpfc_abts_scsi_sgl_list | ||
854 | * to the lpfc_scsi_buf_list. If the repost fails, reject all scsi buffers. | ||
855 | * | ||
856 | * Returns: 0 = success, non-zero failure. | ||
857 | **/ | ||
858 | int | ||
859 | lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba) | ||
860 | { | ||
861 | LIST_HEAD(post_sblist); | ||
862 | int num_posted, rc = 0; | ||
863 | |||
864 | /* get all SCSI buffers need to repost to a local list */ | ||
865 | spin_lock(&phba->scsi_buf_list_lock); | ||
866 | list_splice_init(&phba->lpfc_scsi_buf_list, &post_sblist); | ||
867 | spin_unlock(&phba->scsi_buf_list_lock); | ||
868 | |||
869 | /* post the list of scsi buffer sgls to port if available */ | ||
870 | if (!list_empty(&post_sblist)) { | ||
871 | num_posted = lpfc_sli4_post_scsi_sgl_list(phba, &post_sblist, | ||
872 | phba->sli4_hba.scsi_xri_cnt); | ||
873 | /* failed to post any scsi buffer, return error */ | ||
874 | if (num_posted == 0) | ||
875 | rc = -EIO; | ||
876 | } | ||
787 | return rc; | 877 | return rc; |
788 | } | 878 | } |
789 | 879 | ||
@@ -792,12 +882,13 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba) | |||
792 | * @vport: The virtual port for which this call being executed. | 882 | * @vport: The virtual port for which this call being executed. |
793 | * @num_to_allocate: The requested number of buffers to allocate. | 883 | * @num_to_allocate: The requested number of buffers to allocate. |
794 | * | 884 | * |
795 | * This routine allocates a scsi buffer for device with SLI-4 interface spec, | 885 | * This routine allocates scsi buffers for device with SLI-4 interface spec, |
796 | * the scsi buffer contains all the necessary information needed to initiate | 886 | * the scsi buffer contains all the necessary information needed to initiate |
797 | * a SCSI I/O. | 887 | * a SCSI I/O. After allocating up to @num_to_allocate SCSI buffers and put |
888 | * them on a list, it post them to the port by using SGL block post. | ||
798 | * | 889 | * |
799 | * Return codes: | 890 | * Return codes: |
800 | * int - number of scsi buffers that were allocated. | 891 | * int - number of scsi buffers that were allocated and posted. |
801 | * 0 = failure, less than num_to_alloc is a partial failure. | 892 | * 0 = failure, less than num_to_alloc is a partial failure. |
802 | **/ | 893 | **/ |
803 | static int | 894 | static int |
@@ -810,22 +901,21 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
810 | dma_addr_t pdma_phys_fcp_cmd; | 901 | dma_addr_t pdma_phys_fcp_cmd; |
811 | dma_addr_t pdma_phys_fcp_rsp; | 902 | dma_addr_t pdma_phys_fcp_rsp; |
812 | dma_addr_t pdma_phys_bpl, pdma_phys_bpl1; | 903 | dma_addr_t pdma_phys_bpl, pdma_phys_bpl1; |
813 | uint16_t iotag, last_xritag = NO_XRI, lxri = 0; | 904 | uint16_t iotag, lxri = 0; |
814 | int status = 0, index; | 905 | int bcnt, num_posted; |
815 | int bcnt; | 906 | LIST_HEAD(prep_sblist); |
816 | int non_sequential_xri = 0; | 907 | LIST_HEAD(post_sblist); |
817 | LIST_HEAD(sblist); | 908 | LIST_HEAD(scsi_sblist); |
818 | 909 | ||
819 | for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { | 910 | for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { |
820 | psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); | 911 | psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); |
821 | if (!psb) | 912 | if (!psb) |
822 | break; | 913 | break; |
823 | |||
824 | /* | 914 | /* |
825 | * Get memory from the pci pool to map the virt space to pci bus | 915 | * Get memory from the pci pool to map the virt space to |
826 | * space for an I/O. The DMA buffer includes space for the | 916 | * pci bus space for an I/O. The DMA buffer includes space |
827 | * struct fcp_cmnd, struct fcp_rsp and the number of bde's | 917 | * for the struct fcp_cmnd, struct fcp_rsp and the number |
828 | * necessary to support the sg_tablesize. | 918 | * of bde's necessary to support the sg_tablesize. |
829 | */ | 919 | */ |
830 | psb->data = pci_pool_alloc(phba->lpfc_scsi_dma_buf_pool, | 920 | psb->data = pci_pool_alloc(phba->lpfc_scsi_dma_buf_pool, |
831 | GFP_KERNEL, &psb->dma_handle); | 921 | GFP_KERNEL, &psb->dma_handle); |
@@ -833,8 +923,6 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
833 | kfree(psb); | 923 | kfree(psb); |
834 | break; | 924 | break; |
835 | } | 925 | } |
836 | |||
837 | /* Initialize virtual ptrs to dma_buf region. */ | ||
838 | memset(psb->data, 0, phba->cfg_sg_dma_buf_size); | 926 | memset(psb->data, 0, phba->cfg_sg_dma_buf_size); |
839 | 927 | ||
840 | /* Allocate iotag for psb->cur_iocbq. */ | 928 | /* Allocate iotag for psb->cur_iocbq. */ |
@@ -855,16 +943,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
855 | } | 943 | } |
856 | psb->cur_iocbq.sli4_lxritag = lxri; | 944 | psb->cur_iocbq.sli4_lxritag = lxri; |
857 | psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri]; | 945 | psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri]; |
858 | if (last_xritag != NO_XRI | ||
859 | && psb->cur_iocbq.sli4_xritag != (last_xritag+1)) { | ||
860 | non_sequential_xri = 1; | ||
861 | } else | ||
862 | list_add_tail(&psb->list, &sblist); | ||
863 | last_xritag = psb->cur_iocbq.sli4_xritag; | ||
864 | |||
865 | index = phba->sli4_hba.scsi_xri_cnt++; | ||
866 | psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP; | 946 | psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP; |
867 | |||
868 | psb->fcp_bpl = psb->data; | 947 | psb->fcp_bpl = psb->data; |
869 | psb->fcp_cmnd = (psb->data + phba->cfg_sg_dma_buf_size) | 948 | psb->fcp_cmnd = (psb->data + phba->cfg_sg_dma_buf_size) |
870 | - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); | 949 | - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); |
@@ -880,9 +959,9 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
880 | pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd); | 959 | pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd); |
881 | 960 | ||
882 | /* | 961 | /* |
883 | * The first two bdes are the FCP_CMD and FCP_RSP. The balance | 962 | * The first two bdes are the FCP_CMD and FCP_RSP. |
884 | * are sg list bdes. Initialize the first two and leave the | 963 | * The balance are sg list bdes. Initialize the |
885 | * rest for queuecommand. | 964 | * first two and leave the rest for queuecommand. |
886 | */ | 965 | */ |
887 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd)); | 966 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd)); |
888 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd)); | 967 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd)); |
@@ -917,62 +996,31 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
917 | iocb->ulpBdeCount = 1; | 996 | iocb->ulpBdeCount = 1; |
918 | iocb->ulpLe = 1; | 997 | iocb->ulpLe = 1; |
919 | iocb->ulpClass = CLASS3; | 998 | iocb->ulpClass = CLASS3; |
920 | psb->cur_iocbq.context1 = psb; | 999 | psb->cur_iocbq.context1 = psb; |
921 | if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE) | 1000 | if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE) |
922 | pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE; | 1001 | pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE; |
923 | else | 1002 | else |
924 | pdma_phys_bpl1 = 0; | 1003 | pdma_phys_bpl1 = 0; |
925 | psb->dma_phys_bpl = pdma_phys_bpl; | 1004 | psb->dma_phys_bpl = pdma_phys_bpl; |
926 | phba->sli4_hba.lpfc_scsi_psb_array[index] = psb; | 1005 | |
927 | if (non_sequential_xri) { | 1006 | /* add the scsi buffer to a post list */ |
928 | status = lpfc_sli4_post_sgl(phba, pdma_phys_bpl, | 1007 | list_add_tail(&psb->list, &post_sblist); |
929 | pdma_phys_bpl1, | 1008 | spin_lock_irq(&phba->scsi_buf_list_lock); |
930 | psb->cur_iocbq.sli4_xritag); | 1009 | phba->sli4_hba.scsi_xri_cnt++; |
931 | if (status) { | 1010 | spin_unlock_irq(&phba->scsi_buf_list_lock); |
932 | /* Put this back on the abort scsi list */ | ||
933 | psb->exch_busy = 1; | ||
934 | } else { | ||
935 | psb->exch_busy = 0; | ||
936 | psb->status = IOSTAT_SUCCESS; | ||
937 | } | ||
938 | /* Put it back into the SCSI buffer list */ | ||
939 | lpfc_release_scsi_buf_s4(phba, psb); | ||
940 | break; | ||
941 | } | ||
942 | } | ||
943 | if (bcnt) { | ||
944 | if (!phba->sli4_hba.extents_in_use) | ||
945 | status = lpfc_sli4_post_scsi_sgl_block(phba, | ||
946 | &sblist, | ||
947 | bcnt); | ||
948 | else | ||
949 | status = lpfc_sli4_post_scsi_sgl_blk_ext(phba, | ||
950 | &sblist, | ||
951 | bcnt); | ||
952 | |||
953 | if (status) { | ||
954 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | ||
955 | "3021 SCSI SGL post error %d\n", | ||
956 | status); | ||
957 | bcnt = 0; | ||
958 | } | ||
959 | /* Reset SCSI buffer count for next round of posting */ | ||
960 | while (!list_empty(&sblist)) { | ||
961 | list_remove_head(&sblist, psb, struct lpfc_scsi_buf, | ||
962 | list); | ||
963 | if (status) { | ||
964 | /* Put this back on the abort scsi list */ | ||
965 | psb->exch_busy = 1; | ||
966 | } else { | ||
967 | psb->exch_busy = 0; | ||
968 | psb->status = IOSTAT_SUCCESS; | ||
969 | } | ||
970 | /* Put it back into the SCSI buffer list */ | ||
971 | lpfc_release_scsi_buf_s4(phba, psb); | ||
972 | } | ||
973 | } | 1011 | } |
1012 | lpfc_printf_log(phba, KERN_INFO, LOG_BG, | ||
1013 | "3021 Allocate %d out of %d requested new SCSI " | ||
1014 | "buffers\n", bcnt, num_to_alloc); | ||
1015 | |||
1016 | /* post the list of scsi buffer sgls to port if available */ | ||
1017 | if (!list_empty(&post_sblist)) | ||
1018 | num_posted = lpfc_sli4_post_scsi_sgl_list(phba, | ||
1019 | &post_sblist, bcnt); | ||
1020 | else | ||
1021 | num_posted = 0; | ||
974 | 1022 | ||
975 | return bcnt + non_sequential_xri; | 1023 | return num_posted; |
976 | } | 1024 | } |
977 | 1025 | ||
978 | /** | 1026 | /** |