diff options
author | James Smart <james.smart@emulex.com> | 2013-01-03 15:44:00 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-01-29 19:32:41 -0500 |
commit | 962bc51b04b2725639c47c49404943516ac32b11 (patch) | |
tree | db534ab9510f851ac34f9e26b0d813c8a7db9b42 /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 8b455cf351bba1b9e46d6a1350888be9f6a289d2 (diff) |
[SCSI] lpfc 8.3.37: Provide support for FCoE protocol dual-chute (ULP) operation
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 188 |
1 files changed, 177 insertions, 11 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c997b919b6fe..0988b320d317 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -124,10 +124,17 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) | |||
124 | 124 | ||
125 | /* Ring Doorbell */ | 125 | /* Ring Doorbell */ |
126 | doorbell.word0 = 0; | 126 | doorbell.word0 = 0; |
127 | bf_set(lpfc_wq_doorbell_num_posted, &doorbell, 1); | 127 | if (q->db_format == LPFC_DB_LIST_FORMAT) { |
128 | bf_set(lpfc_wq_doorbell_index, &doorbell, host_index); | 128 | bf_set(lpfc_wq_db_list_fm_num_posted, &doorbell, 1); |
129 | bf_set(lpfc_wq_doorbell_id, &doorbell, q->queue_id); | 129 | bf_set(lpfc_wq_db_list_fm_index, &doorbell, host_index); |
130 | writel(doorbell.word0, q->phba->sli4_hba.WQDBregaddr); | 130 | bf_set(lpfc_wq_db_list_fm_id, &doorbell, q->queue_id); |
131 | } else if (q->db_format == LPFC_DB_RING_FORMAT) { | ||
132 | bf_set(lpfc_wq_db_ring_fm_num_posted, &doorbell, 1); | ||
133 | bf_set(lpfc_wq_db_ring_fm_id, &doorbell, q->queue_id); | ||
134 | } else { | ||
135 | return -EINVAL; | ||
136 | } | ||
137 | writel(doorbell.word0, q->db_regaddr); | ||
131 | 138 | ||
132 | return 0; | 139 | return 0; |
133 | } | 140 | } |
@@ -456,10 +463,20 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq, | |||
456 | /* Ring The Header Receive Queue Doorbell */ | 463 | /* Ring The Header Receive Queue Doorbell */ |
457 | if (!(hq->host_index % hq->entry_repost)) { | 464 | if (!(hq->host_index % hq->entry_repost)) { |
458 | doorbell.word0 = 0; | 465 | doorbell.word0 = 0; |
459 | bf_set(lpfc_rq_doorbell_num_posted, &doorbell, | 466 | if (hq->db_format == LPFC_DB_RING_FORMAT) { |
460 | hq->entry_repost); | 467 | bf_set(lpfc_rq_db_ring_fm_num_posted, &doorbell, |
461 | bf_set(lpfc_rq_doorbell_id, &doorbell, hq->queue_id); | 468 | hq->entry_repost); |
462 | writel(doorbell.word0, hq->phba->sli4_hba.RQDBregaddr); | 469 | bf_set(lpfc_rq_db_ring_fm_id, &doorbell, hq->queue_id); |
470 | } else if (hq->db_format == LPFC_DB_LIST_FORMAT) { | ||
471 | bf_set(lpfc_rq_db_list_fm_num_posted, &doorbell, | ||
472 | hq->entry_repost); | ||
473 | bf_set(lpfc_rq_db_list_fm_index, &doorbell, | ||
474 | hq->host_index); | ||
475 | bf_set(lpfc_rq_db_list_fm_id, &doorbell, hq->queue_id); | ||
476 | } else { | ||
477 | return -EINVAL; | ||
478 | } | ||
479 | writel(doorbell.word0, hq->db_regaddr); | ||
463 | } | 480 | } |
464 | return put_index; | 481 | return put_index; |
465 | } | 482 | } |
@@ -4939,7 +4956,7 @@ out_free_mboxq: | |||
4939 | static void | 4956 | static void |
4940 | lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) | 4957 | lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) |
4941 | { | 4958 | { |
4942 | uint8_t fcp_eqidx; | 4959 | int fcp_eqidx; |
4943 | 4960 | ||
4944 | lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM); | 4961 | lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM); |
4945 | lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM); | 4962 | lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM); |
@@ -11867,7 +11884,7 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id) | |||
11867 | struct lpfc_eqe *eqe; | 11884 | struct lpfc_eqe *eqe; |
11868 | unsigned long iflag; | 11885 | unsigned long iflag; |
11869 | int ecount = 0; | 11886 | int ecount = 0; |
11870 | uint32_t fcp_eqidx; | 11887 | int fcp_eqidx; |
11871 | 11888 | ||
11872 | /* Get the driver's phba structure from the dev_id */ | 11889 | /* Get the driver's phba structure from the dev_id */ |
11873 | fcp_eq_hdl = (struct lpfc_fcp_eq_hdl *)dev_id; | 11890 | fcp_eq_hdl = (struct lpfc_fcp_eq_hdl *)dev_id; |
@@ -11969,7 +11986,7 @@ lpfc_sli4_intr_handler(int irq, void *dev_id) | |||
11969 | struct lpfc_hba *phba; | 11986 | struct lpfc_hba *phba; |
11970 | irqreturn_t hba_irq_rc; | 11987 | irqreturn_t hba_irq_rc; |
11971 | bool hba_handled = false; | 11988 | bool hba_handled = false; |
11972 | uint32_t fcp_eqidx; | 11989 | int fcp_eqidx; |
11973 | 11990 | ||
11974 | /* Get the driver's phba structure from the dev_id */ | 11991 | /* Get the driver's phba structure from the dev_id */ |
11975 | phba = (struct lpfc_hba *)dev_id; | 11992 | phba = (struct lpfc_hba *)dev_id; |
@@ -12091,6 +12108,54 @@ out_fail: | |||
12091 | } | 12108 | } |
12092 | 12109 | ||
12093 | /** | 12110 | /** |
12111 | * lpfc_dual_chute_pci_bar_map - Map pci base address register to host memory | ||
12112 | * @phba: HBA structure that indicates port to create a queue on. | ||
12113 | * @pci_barset: PCI BAR set flag. | ||
12114 | * | ||
12115 | * This function shall perform iomap of the specified PCI BAR address to host | ||
12116 | * memory address if not already done so and return it. The returned host | ||
12117 | * memory address can be NULL. | ||
12118 | */ | ||
12119 | static void __iomem * | ||
12120 | lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset) | ||
12121 | { | ||
12122 | struct pci_dev *pdev; | ||
12123 | unsigned long bar_map, bar_map_len; | ||
12124 | |||
12125 | if (!phba->pcidev) | ||
12126 | return NULL; | ||
12127 | else | ||
12128 | pdev = phba->pcidev; | ||
12129 | |||
12130 | switch (pci_barset) { | ||
12131 | case WQ_PCI_BAR_0_AND_1: | ||
12132 | if (!phba->pci_bar0_memmap_p) { | ||
12133 | bar_map = pci_resource_start(pdev, PCI_64BIT_BAR0); | ||
12134 | bar_map_len = pci_resource_len(pdev, PCI_64BIT_BAR0); | ||
12135 | phba->pci_bar0_memmap_p = ioremap(bar_map, bar_map_len); | ||
12136 | } | ||
12137 | return phba->pci_bar0_memmap_p; | ||
12138 | case WQ_PCI_BAR_2_AND_3: | ||
12139 | if (!phba->pci_bar2_memmap_p) { | ||
12140 | bar_map = pci_resource_start(pdev, PCI_64BIT_BAR2); | ||
12141 | bar_map_len = pci_resource_len(pdev, PCI_64BIT_BAR2); | ||
12142 | phba->pci_bar2_memmap_p = ioremap(bar_map, bar_map_len); | ||
12143 | } | ||
12144 | return phba->pci_bar2_memmap_p; | ||
12145 | case WQ_PCI_BAR_4_AND_5: | ||
12146 | if (!phba->pci_bar4_memmap_p) { | ||
12147 | bar_map = pci_resource_start(pdev, PCI_64BIT_BAR4); | ||
12148 | bar_map_len = pci_resource_len(pdev, PCI_64BIT_BAR4); | ||
12149 | phba->pci_bar4_memmap_p = ioremap(bar_map, bar_map_len); | ||
12150 | } | ||
12151 | return phba->pci_bar4_memmap_p; | ||
12152 | default: | ||
12153 | break; | ||
12154 | } | ||
12155 | return NULL; | ||
12156 | } | ||
12157 | |||
12158 | /** | ||
12094 | * lpfc_modify_fcp_eq_delay - Modify Delay Multiplier on FCP EQs | 12159 | * lpfc_modify_fcp_eq_delay - Modify Delay Multiplier on FCP EQs |
12095 | * @phba: HBA structure that indicates port to create a queue on. | 12160 | * @phba: HBA structure that indicates port to create a queue on. |
12096 | * @startq: The starting FCP EQ to modify | 12161 | * @startq: The starting FCP EQ to modify |
@@ -12667,6 +12732,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, | |||
12667 | union lpfc_sli4_cfg_shdr *shdr; | 12732 | union lpfc_sli4_cfg_shdr *shdr; |
12668 | uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; | 12733 | uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; |
12669 | struct dma_address *page; | 12734 | struct dma_address *page; |
12735 | void __iomem *bar_memmap_p; | ||
12736 | uint32_t db_offset; | ||
12737 | uint16_t pci_barset; | ||
12670 | 12738 | ||
12671 | /* sanity check on queue memory */ | 12739 | /* sanity check on queue memory */ |
12672 | if (!wq || !cq) | 12740 | if (!wq || !cq) |
@@ -12690,6 +12758,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, | |||
12690 | cq->queue_id); | 12758 | cq->queue_id); |
12691 | bf_set(lpfc_mbox_hdr_version, &shdr->request, | 12759 | bf_set(lpfc_mbox_hdr_version, &shdr->request, |
12692 | phba->sli4_hba.pc_sli4_params.wqv); | 12760 | phba->sli4_hba.pc_sli4_params.wqv); |
12761 | |||
12693 | if (phba->sli4_hba.pc_sli4_params.wqv == LPFC_Q_CREATE_VERSION_1) { | 12762 | if (phba->sli4_hba.pc_sli4_params.wqv == LPFC_Q_CREATE_VERSION_1) { |
12694 | bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1, | 12763 | bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1, |
12695 | wq->entry_count); | 12764 | wq->entry_count); |
@@ -12717,6 +12786,10 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, | |||
12717 | page[dmabuf->buffer_tag].addr_lo = putPaddrLow(dmabuf->phys); | 12786 | page[dmabuf->buffer_tag].addr_lo = putPaddrLow(dmabuf->phys); |
12718 | page[dmabuf->buffer_tag].addr_hi = putPaddrHigh(dmabuf->phys); | 12787 | page[dmabuf->buffer_tag].addr_hi = putPaddrHigh(dmabuf->phys); |
12719 | } | 12788 | } |
12789 | |||
12790 | if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) | ||
12791 | bf_set(lpfc_mbx_wq_create_dua, &wq_create->u.request, 1); | ||
12792 | |||
12720 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | 12793 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); |
12721 | /* The IOCTL status is embedded in the mailbox subheader. */ | 12794 | /* The IOCTL status is embedded in the mailbox subheader. */ |
12722 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | 12795 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); |
@@ -12734,6 +12807,47 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, | |||
12734 | status = -ENXIO; | 12807 | status = -ENXIO; |
12735 | goto out; | 12808 | goto out; |
12736 | } | 12809 | } |
12810 | if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) { | ||
12811 | wq->db_format = bf_get(lpfc_mbx_wq_create_db_format, | ||
12812 | &wq_create->u.response); | ||
12813 | if ((wq->db_format != LPFC_DB_LIST_FORMAT) && | ||
12814 | (wq->db_format != LPFC_DB_RING_FORMAT)) { | ||
12815 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
12816 | "3265 WQ[%d] doorbell format not " | ||
12817 | "supported: x%x\n", wq->queue_id, | ||
12818 | wq->db_format); | ||
12819 | status = -EINVAL; | ||
12820 | goto out; | ||
12821 | } | ||
12822 | pci_barset = bf_get(lpfc_mbx_wq_create_bar_set, | ||
12823 | &wq_create->u.response); | ||
12824 | bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset); | ||
12825 | if (!bar_memmap_p) { | ||
12826 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
12827 | "3263 WQ[%d] failed to memmap pci " | ||
12828 | "barset:x%x\n", wq->queue_id, | ||
12829 | pci_barset); | ||
12830 | status = -ENOMEM; | ||
12831 | goto out; | ||
12832 | } | ||
12833 | db_offset = wq_create->u.response.doorbell_offset; | ||
12834 | if ((db_offset != LPFC_ULP0_WQ_DOORBELL) && | ||
12835 | (db_offset != LPFC_ULP1_WQ_DOORBELL)) { | ||
12836 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
12837 | "3252 WQ[%d] doorbell offset not " | ||
12838 | "supported: x%x\n", wq->queue_id, | ||
12839 | db_offset); | ||
12840 | status = -EINVAL; | ||
12841 | goto out; | ||
12842 | } | ||
12843 | wq->db_regaddr = bar_memmap_p + db_offset; | ||
12844 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
12845 | "3264 WQ[%d]: barset:x%x, offset:x%x\n", | ||
12846 | wq->queue_id, pci_barset, db_offset); | ||
12847 | } else { | ||
12848 | wq->db_format = LPFC_DB_LIST_FORMAT; | ||
12849 | wq->db_regaddr = phba->sli4_hba.WQDBregaddr; | ||
12850 | } | ||
12737 | wq->type = LPFC_WQ; | 12851 | wq->type = LPFC_WQ; |
12738 | wq->assoc_qid = cq->queue_id; | 12852 | wq->assoc_qid = cq->queue_id; |
12739 | wq->subtype = subtype; | 12853 | wq->subtype = subtype; |
@@ -12810,6 +12924,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
12810 | uint32_t shdr_status, shdr_add_status; | 12924 | uint32_t shdr_status, shdr_add_status; |
12811 | union lpfc_sli4_cfg_shdr *shdr; | 12925 | union lpfc_sli4_cfg_shdr *shdr; |
12812 | uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; | 12926 | uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; |
12927 | void __iomem *bar_memmap_p; | ||
12928 | uint32_t db_offset; | ||
12929 | uint16_t pci_barset; | ||
12813 | 12930 | ||
12814 | /* sanity check on queue memory */ | 12931 | /* sanity check on queue memory */ |
12815 | if (!hrq || !drq || !cq) | 12932 | if (!hrq || !drq || !cq) |
@@ -12888,6 +13005,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
12888 | rq_create->u.request.page[dmabuf->buffer_tag].addr_hi = | 13005 | rq_create->u.request.page[dmabuf->buffer_tag].addr_hi = |
12889 | putPaddrHigh(dmabuf->phys); | 13006 | putPaddrHigh(dmabuf->phys); |
12890 | } | 13007 | } |
13008 | if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) | ||
13009 | bf_set(lpfc_mbx_rq_create_dua, &rq_create->u.request, 1); | ||
13010 | |||
12891 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | 13011 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); |
12892 | /* The IOCTL status is embedded in the mailbox subheader. */ | 13012 | /* The IOCTL status is embedded in the mailbox subheader. */ |
12893 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | 13013 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); |
@@ -12905,6 +13025,50 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
12905 | status = -ENXIO; | 13025 | status = -ENXIO; |
12906 | goto out; | 13026 | goto out; |
12907 | } | 13027 | } |
13028 | |||
13029 | if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) { | ||
13030 | hrq->db_format = bf_get(lpfc_mbx_rq_create_db_format, | ||
13031 | &rq_create->u.response); | ||
13032 | if ((hrq->db_format != LPFC_DB_LIST_FORMAT) && | ||
13033 | (hrq->db_format != LPFC_DB_RING_FORMAT)) { | ||
13034 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
13035 | "3262 RQ [%d] doorbell format not " | ||
13036 | "supported: x%x\n", hrq->queue_id, | ||
13037 | hrq->db_format); | ||
13038 | status = -EINVAL; | ||
13039 | goto out; | ||
13040 | } | ||
13041 | |||
13042 | pci_barset = bf_get(lpfc_mbx_rq_create_bar_set, | ||
13043 | &rq_create->u.response); | ||
13044 | bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset); | ||
13045 | if (!bar_memmap_p) { | ||
13046 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
13047 | "3269 RQ[%d] failed to memmap pci " | ||
13048 | "barset:x%x\n", hrq->queue_id, | ||
13049 | pci_barset); | ||
13050 | status = -ENOMEM; | ||
13051 | goto out; | ||
13052 | } | ||
13053 | |||
13054 | db_offset = rq_create->u.response.doorbell_offset; | ||
13055 | if ((db_offset != LPFC_ULP0_RQ_DOORBELL) && | ||
13056 | (db_offset != LPFC_ULP1_RQ_DOORBELL)) { | ||
13057 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
13058 | "3270 RQ[%d] doorbell offset not " | ||
13059 | "supported: x%x\n", hrq->queue_id, | ||
13060 | db_offset); | ||
13061 | status = -EINVAL; | ||
13062 | goto out; | ||
13063 | } | ||
13064 | hrq->db_regaddr = bar_memmap_p + db_offset; | ||
13065 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
13066 | "3266 RQ[qid:%d]: barset:x%x, offset:x%x\n", | ||
13067 | hrq->queue_id, pci_barset, db_offset); | ||
13068 | } else { | ||
13069 | hrq->db_format = LPFC_DB_RING_FORMAT; | ||
13070 | hrq->db_regaddr = phba->sli4_hba.RQDBregaddr; | ||
13071 | } | ||
12908 | hrq->type = LPFC_HRQ; | 13072 | hrq->type = LPFC_HRQ; |
12909 | hrq->assoc_qid = cq->queue_id; | 13073 | hrq->assoc_qid = cq->queue_id; |
12910 | hrq->subtype = subtype; | 13074 | hrq->subtype = subtype; |
@@ -12970,6 +13134,8 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
12970 | rq_create->u.request.page[dmabuf->buffer_tag].addr_hi = | 13134 | rq_create->u.request.page[dmabuf->buffer_tag].addr_hi = |
12971 | putPaddrHigh(dmabuf->phys); | 13135 | putPaddrHigh(dmabuf->phys); |
12972 | } | 13136 | } |
13137 | if (phba->sli4_hba.fw_func_mode & LPFC_DUA_MODE) | ||
13138 | bf_set(lpfc_mbx_rq_create_dua, &rq_create->u.request, 1); | ||
12973 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | 13139 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); |
12974 | /* The IOCTL status is embedded in the mailbox subheader. */ | 13140 | /* The IOCTL status is embedded in the mailbox subheader. */ |
12975 | shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr; | 13141 | shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr; |