aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2013-01-03 15:44:00 -0500
committerJames Bottomley <JBottomley@Parallels.com>2013-01-29 19:32:41 -0500
commit962bc51b04b2725639c47c49404943516ac32b11 (patch)
treedb534ab9510f851ac34f9e26b0d813c8a7db9b42 /drivers/scsi/lpfc/lpfc_sli.c
parent8b455cf351bba1b9e46d6a1350888be9f6a289d2 (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.c188
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:
4939static void 4956static void
4940lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) 4957lpfc_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 */
12119static void __iomem *
12120lpfc_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;