diff options
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 35 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 14 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 183 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 273 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 79 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 397 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 68 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 176 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mem.c | 29 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 36 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 698 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 25 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_version.h | 2 |
14 files changed, 1522 insertions, 495 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 8d718964f28..74f4d18842c 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -63,6 +63,11 @@ struct lpfc_dma_pool { uint32_t current_count; }; +struct hbq_dmabuf { + struct lpfc_dmabuf dbuf; + uint32_t tag; +}; + /* Priority bit. Set value to exceed low water mark in lpfc_mem. */ #define MEM_PRI 0x100 @@ -276,8 +281,25 @@ struct lpfc_vport { }; + +struct hbq_s { + uint16_t entry_count; /* Current number of HBQ slots */ + uint32_t next_hbqPutIdx; /* Index to next HBQ slot to use */ + uint32_t hbqPutIdx; /* HBQ slot to use */ + uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */ +}; + +#define MAX_HBQS 16 + struct lpfc_hba { struct lpfc_sli sli; + uint32_t sli_rev; /* SLI2 or SLI3 */ + uint32_t sli3_options; /* Mask of enabled SLI3 options */ +#define LPFC_SLI3_ENABLED 0x01 +#define LPFC_SLI3_HBQ_ENABLED 0x02 +#define LPFC_SLI3_INB_ENABLED 0x04 + uint32_t iocb_cmd_size; + uint32_t iocb_rsp_size; enum hba_state link_state; uint32_t link_flag; /* link state flags */ @@ -286,8 +308,6 @@ struct lpfc_hba { /* INIT_LINK mailbox command */ #define LS_IGNORE_ERATT 0x80000 /* intr handler should ignore ERATT */ - uint32_t pgpOffset; /* PGP offset within host memory */ - struct lpfc_sli2_slim *slim2p; struct lpfc_dmabuf hbqslimp; @@ -371,6 +391,12 @@ struct lpfc_hba { wait_queue_head_t *work_wait; struct task_struct *worker_thread; + struct hbq_dmabuf *hbq_buffer_pool; + uint32_t hbq_buffer_count; + uint32_t hbq_buff_count; /* Current hbq buffers */ + uint32_t hbq_count; /* Count of configured HBQs */ + struct hbq_s hbqs[MAX_HBQS]; /* local copy of hbq indicies */ + unsigned long pci_bar0_map; /* Physical address for PCI BAR0 */ unsigned long pci_bar2_map; /* Physical address for PCI BAR2 */ void __iomem *slim_memmap_p; /* Kernel memory mapped address for @@ -385,6 +411,10 @@ struct lpfc_hba { reg */ void __iomem *HCregaddr; /* virtual address for host ctl reg */ + struct lpfc_hgp __iomem *host_gp; /* Host side get/put pointers */ + uint32_t __iomem *hbq_put; /* Address in SLIM to HBQ put ptrs */ + uint32_t __iomem *hbq_get; /* Address in SLIM to HBQ get ptrs */ + int brd_no; /* FC board number */ char SerialNumber[32]; /* adapter Serial Number */ @@ -425,6 +455,7 @@ struct lpfc_hba { /* pci_mem_pools */ struct pci_pool *lpfc_scsi_dma_buf_pool; struct pci_pool *lpfc_mbuf_pool; + struct pci_pool *lpfc_hbq_pool; struct lpfc_dma_pool lpfc_mbuf_safety_pool; mempool_t *mbox_mem_pool; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 0081cffd928..77693072705 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -138,6 +138,10 @@ void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *); LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); int lpfc_mbox_tmo_val(struct lpfc_hba *, int); +void lpfc_config_hbq(struct lpfc_hba *, struct lpfc_hbq_init *, uint32_t , + LPFC_MBOXQ_t *); +struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t); + int lpfc_mem_alloc(struct lpfc_hba *); void lpfc_mem_free(struct lpfc_hba *); @@ -172,6 +176,12 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, struct lpfc_sli_ring *, dma_addr_t); +int lpfc_sli_hbqbuf_fill_hbq(struct lpfc_hba *); +void lpfc_sli_hbqbuf_free(struct lpfc_hba *, void *, dma_addr_t); +void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *); +struct hbq_dmabuf *lpfc_sli_hbqbuf_find(struct lpfc_hba *, uint32_t); +void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *); +int lpfc_sli_hbq_size(void); int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_iocbq *); int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, @@ -198,6 +208,9 @@ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb); +void *lpfc_hbq_alloc(struct lpfc_hba *, int, dma_addr_t *); +void lpfc_hbq_free(struct lpfc_hba *, void *, dma_addr_t); + void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *); void __lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t); void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t); @@ -213,6 +226,7 @@ void lpfc_free_sysfs_attr(struct lpfc_vport *); extern struct class_device_attribute *lpfc_hba_attrs[]; extern struct scsi_host_template lpfc_template; extern struct fc_function_template lpfc_transport_functions; +extern int lpfc_sli_mode; void lpfc_get_hba_sym_node_name(struct lpfc_hba *phba, uint8_t *symbp); void lpfc_terminate_rport_io(struct fc_rport *); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index dc25a53524c..e8ed5d7ccf9 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -58,25 +58,66 @@ static char *lpfc_release_version = LPFC_DRIVER_VERSION; /* * lpfc_ct_unsol_event */ +static void +lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, + struct lpfc_dmabuf *mp, uint32_t size) +{ + if (!mp) { + printk(KERN_ERR "%s (%d): Unsolited CT, no buffer, " + "piocbq = %p, status = x%x, mp = %p, size = %d\n", + __FUNCTION__, __LINE__, + piocbq, piocbq->iocb.ulpStatus, mp, size); + } + + printk(KERN_ERR "%s (%d): Ignoring unsolicted CT piocbq = %p, " + "buffer = %p, size = %d, status = x%x\n", + __FUNCTION__, __LINE__, + piocbq, mp, size, + piocbq->iocb.ulpStatus); +} + +static void +lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, + struct hbq_dmabuf *sp, uint32_t size) +{ + struct lpfc_dmabuf *mp = NULL; + + mp = sp ? &sp->dbuf : NULL; + if (!mp) { + printk(KERN_ERR "%s (%d): Unsolited CT, no " + "HBQ buffer, piocbq = %p, status = x%x\n", + __FUNCTION__, __LINE__, + piocbq, piocbq->iocb.ulpStatus); + } else { + lpfc_ct_unsol_buffer(phba, piocbq, mp, size); + printk(KERN_ERR "%s (%d): Ignoring unsolicted CT " + "piocbq = %p, buffer = %p, size = %d, " + "status = x%x\n", + __FUNCTION__, __LINE__, + piocbq, mp, size, piocbq->iocb.ulpStatus); + } +} + void lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *piocbq) { - - struct lpfc_iocbq *next_piocbq; - struct lpfc_dmabuf *pmbuf = NULL; - struct lpfc_dmabuf *matp = NULL, *next_matp; - uint32_t ctx = 0, size = 0, cnt = 0; + struct lpfc_dmabuf *mp = NULL; + struct hbq_dmabuf *sp = NULL; IOCB_t *icmd = &piocbq->iocb; - IOCB_t *save_icmd = icmd; - int i, go_exit = 0; - struct list_head head; + int i; + struct lpfc_iocbq *iocbq; + dma_addr_t paddr; + uint32_t size; if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && - ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { + ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { /* Not enough posted buffers; Try posting more buffers */ phba->fc_stat.NoRcvBuf++; - lpfc_post_buffer(phba, pring, 0, 1); + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) + lpfc_sli_hbqbuf_fill_hbq(phba); + else + lpfc_post_buffer(phba, pring, 0, 1); return; } @@ -86,62 +127,62 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (icmd->ulpBdeCount == 0) return; - INIT_LIST_HEAD(&head); - list_add_tail(&head, &piocbq->list); - - list_for_each_entry_safe(piocbq, next_piocbq, &head, list) { - icmd = &piocbq->iocb; - if (ctx == 0) - ctx = (uint32_t) (icmd->ulpContext); - if (icmd->ulpBdeCount == 0) - continue; - - for (i = 0; i < icmd->ulpBdeCount; i++) { - matp = lpfc_sli_ringpostbuf_get(phba, pring, - getPaddr(icmd->un. - cont64[i]. - addrHigh, - icmd->un. - cont64[i]. - addrLow)); - if (!matp) { - /* Insert lpfc log message here */ - lpfc_post_buffer(phba, pring, cnt, 1); - go_exit = 1; - goto ct_unsol_event_exit_piocbq; + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { + list_for_each_entry(iocbq, &piocbq->list, list) { + icmd = &iocbq->iocb; + if (icmd->ulpBdeCount == 0) { + printk(KERN_ERR "%s (%d): Unsolited CT, no " + "BDE, iocbq = %p, status = x%x\n", + __FUNCTION__, __LINE__, + iocbq, iocbq->iocb.ulpStatus); + continue; } - /* Typically for Unsolicited CT requests */ - if (!pmbuf) { - pmbuf = matp; - INIT_LIST_HEAD(&pmbuf->list); - } else - list_add_tail(&matp->list, &pmbuf->list); + size = icmd->un.cont64[0].tus.f.bdeSize; + sp = lpfc_sli_hbqbuf_find(phba, icmd->un.ulpWord[3]); + if (sp) + phba->hbq_buff_count--; + lpfc_ct_ignore_hbq_buffer(phba, iocbq, sp, size); + lpfc_sli_free_hbq(phba, sp); + if (icmd->ulpBdeCount == 2) { + sp = lpfc_sli_hbqbuf_find(phba, + icmd->un.ulpWord[15]); + if (sp) + phba->hbq_buff_count--; + lpfc_ct_ignore_hbq_buffer(phba, iocbq, sp, + size); + lpfc_sli_free_hbq(phba, sp); + } - size += icmd->un.cont64[i].tus.f.bdeSize; - cnt++; } + lpfc_sli_hbqbuf_fill_hbq(phba); + } else { + struct lpfc_iocbq *next; + + list_for_each_entry_safe(iocbq, next, &piocbq->list, list) { + icmd = &iocbq->iocb; + if (icmd->ulpBdeCount == 0) { + printk(KERN_ERR "%s (%d): Unsolited CT, no " + "BDE, iocbq = %p, status = x%x\n", + __FUNCTION__, __LINE__, + iocbq, iocbq->iocb.ulpStatus); + continue; + } - icmd->ulpBdeCount = 0; - } - - lpfc_post_buffer(phba, pring, cnt, 1); - if (save_icmd->ulpStatus) { - go_exit = 1; - } - -ct_unsol_event_exit_piocbq: - list_del(&head); - if (pmbuf) { - list_for_each_entry_safe(matp, next_matp, &pmbuf->list, list) { - lpfc_mbuf_free(phba, matp->virt, matp->phys); - list_del(&matp->list); - kfree(matp); + for (i = 0; i < icmd->ulpBdeCount; i++) { + paddr = getPaddr(icmd->un.cont64[i].addrHigh, + icmd->un.cont64[i].addrLow); + mp = lpfc_sli_ringpostbuf_get(phba, pring, + paddr); + size = icmd->un.cont64[i].tus.f.bdeSize; + lpfc_ct_unsol_buffer(phba, piocbq, mp, size); + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } + list_del(&iocbq->list); + lpfc_sli_release_iocbq(phba, iocbq); } - lpfc_mbuf_free(phba, pmbuf->virt, pmbuf->phys); - kfree(pmbuf); } - return; } static void @@ -364,9 +405,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) vport->fc_flag, vport->fc_rscn_id_cnt); } else { - lpfc_printf_log(phba, - KERN_INFO, - LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0239 Skip x%x NameServer " "Rsp Data: x%x x%x x%x\n", phba->brd_no, @@ -717,12 +756,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp = lpfc_findnode_did(vport, FDMI_DID); if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { /* FDMI rsp failed */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_DISCOVERY, - "%d:0220 FDMI rsp failed Data: x%x\n", - phba->brd_no, - be16_to_cpu(fdmi_cmd)); + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, + "%d:0220 FDMI rsp failed Data: x%x\n", + phba->brd_no, be16_to_cpu(fdmi_cmd)); } switch (be16_to_cpu(fdmi_cmd)) { @@ -791,9 +827,7 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) INIT_LIST_HEAD(&bmp->list); /* FDMI request */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0218 FDMI Request Data: x%x x%x x%x\n", phba->brd_no, vport->fc_flag, vport->port_state, cmdcode); @@ -1120,12 +1154,9 @@ fdmi_cmd_free_mp: kfree(mp); fdmi_cmd_exit: /* Issue FDMI request failed */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0244 Issue FDMI request failed Data: x%x\n", - phba->brd_no, - cmdcode); + phba->brd_no, cmdcode); return 1; } diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 0af33bead30..d48247b3b65 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -45,9 +45,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; - LPFC_MBOXQ_t *mbox; uint32_t ha_copy; - int rc; if (vport->port_state >= LPFC_VPORT_READY || phba->link_state == LPFC_LINK_DOWN) @@ -76,20 +74,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) spin_unlock_irq(shost->host_lock); if (phba->link_state != LPFC_CLEAR_LA) { - if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) { - phba->link_state = LPFC_CLEAR_LA; - lpfc_clear_la(phba, mbox); - mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la; - mbox->vport = vport; - printk(KERN_ERR "%s (%d): do clear_la\n", - __FUNCTION__, __LINE__); - rc = lpfc_sli_issue_mbox(phba, mbox, - (MBX_NOWAIT | MBX_STOP_IOCB)); - if (rc == MBX_NOT_FINISHED) { - mempool_free(mbox, phba->mbox_mem_pool); - phba->link_state = LPFC_HBA_ERROR; - } - } + lpfc_issue_clear_la(phba, vport); } return 1; @@ -153,8 +138,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, /* Allocate buffer for Buffer ptr list */ pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); if (pbuflist) - pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, - &pbuflist->phys); + pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, + &pbuflist->phys); if (pbuflist == 0 || pbuflist->virt == 0) { lpfc_sli_release_iocbq(phba, elsiocb); lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); @@ -289,6 +274,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, vport->port_state = LPFC_FABRIC_CFG_LINK; lpfc_config_link(phba, mbox); mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + mbox->vport = vport; rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); if (rc == MBX_NOT_FINISHED) @@ -364,6 +350,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_config_link(phba, mbox); mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + mbox->vport = vport; rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); if (rc == MBX_NOT_FINISHED) { @@ -714,8 +701,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp = &rspiocb->iocb; ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); - if (!ndlp) + + if (!ndlp) { goto out; + } /* Since ndlp can be freed in the disc state machine, note if this node * is being used during discovery. @@ -1110,9 +1099,8 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* If we get here, there is nothing left to wait for */ if (vport->port_state < LPFC_VPORT_READY && phba->link_state != LPFC_CLEAR_LA) { - if (vport->port_type == LPFC_PHYSICAL_PORT) { + if (vport->port_type == LPFC_PHYSICAL_PORT) lpfc_issue_clear_la(phba, vport); - } } else { lpfc_rscn_disc(vport); } @@ -1420,6 +1408,27 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) return 0; } +static void +lpfc_end_rscn(struct lpfc_vport *vport) +{ + struct Scsi_Host *shost = lpfc_shost_from_vport(vport); + + if (vport->fc_flag & FC_RSCN_MODE) { + /* + * Check to see if more RSCNs came in while we were + * processing this one. + */ + if (vport->fc_rscn_id_cnt || + (vport->fc_flag & FC_RSCN_DISCOVERY) != 0) + lpfc_els_handle_rscn(vport); + else { + spin_lock_irq(shost->host_lock); + vport->fc_flag &= ~FC_RSCN_MODE; + spin_unlock_irq(shost->host_lock); + } + } +} + void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) { @@ -1449,24 +1458,7 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) vport->fc_flag &= ~FC_NDISC_ACTIVE; spin_unlock_irq(shost->host_lock); lpfc_can_disctmo(vport); - if (vport->fc_flag & FC_RSCN_MODE) { - /* - * Check to see if more RSCNs - * came in while we were - * processing this one. - */ - if (!vport->fc_rscn_id_cnt && - !(vport->fc_flag & - FC_RSCN_DISCOVERY)) { - spin_lock_irq(shost->host_lock); - vport->fc_flag &= ~FC_RSCN_MODE; - spin_unlock_irq( - shost->host_lock); - } - else { - lpfc_els_handle_rscn(vport); - } - } + lpfc_end_rscn(vport); } } } @@ -1689,6 +1681,9 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, retry = 0; } + if ((vport->load_flag & FC_UNLOADING) != 0) + retry = 0; + if (retry) { /* Retry ELS command <elsCmd> to remote NPORT <did> */ @@ -2141,9 +2136,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, cmdsize = sizeof (uint32_t) + sizeof (PRLI); elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, - ndlp->nlp_DID, - (ELS_CMD_ACC | - (ELS_CMD_PRLI & ~ELS_RSP_MASK))); + ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK))); if (!elsiocb) return 1; @@ -2361,8 +2354,12 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport) for (i = 0; i < vport->fc_rscn_id_cnt; i++) { mp = vport->fc_rscn_id_list[i]; - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) + lpfc_sli_hbqbuf_free(phba, mp->virt, mp->phys); + else { + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } vport->fc_rscn_id_list[i] = NULL; } spin_lock_irq(shost->host_lock); @@ -2486,9 +2483,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, cmd &= ELS_CMD_MASK; /* RSCN received */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0214 RSCN received Data: x%x x%x x%x x%x\n", phba->brd_no, vport->fc_flag, payload_len, *lp, vport->fc_rscn_id_cnt); @@ -2581,9 +2576,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) lpfc_set_disctmo(vport); /* RSCN processed */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n", phba->brd_no, vport->fc_flag, 0, vport->fc_rscn_id_cnt, @@ -2683,6 +2676,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, phba->cfg_link_speed); mbox->mb.un.varInitLnk.lipsr_AL_PA = 0; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + mbox->vport = vport; rc = lpfc_sli_issue_mbox (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); lpfc_set_loopback_flag(phba); @@ -2837,10 +2831,8 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; phba->fc_stat.elsXmitACC++; - - if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { + if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) lpfc_els_free_iocb(phba, elsiocb); - } return; } @@ -3015,9 +3007,7 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, fp = (FARP *) lp; /* FARP-REQ received from DID <did> */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_ELS, + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0601 FARP-REQ received from DID x%x\n", phba->brd_no, did); @@ -3077,12 +3067,9 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, cmd = *lp++; /* FARP-RSP received from DID <did> */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_ELS, + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0600 FARP-RSP received from DID x%x\n", phba->brd_no, did); - /* ACCEPT the Farp resp request */ lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); @@ -3102,8 +3089,9 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, struct lpfc_hba *phba = vport->phba; /* FAN received */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n", - phba->brd_no); + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, + "%d:0265 FAN received\n", + phba->brd_no); icmd = &cmdiocb->iocb; did = icmd->un.elsreq64.remoteID; @@ -3332,79 +3320,40 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) return; } -void -lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, - struct lpfc_iocbq *elsiocb) +static void +lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + struct lpfc_vport *vport, struct lpfc_dmabuf *mp, + struct lpfc_iocbq *elsiocb) { - struct lpfc_sli *psli; struct lpfc_nodelist *ndlp; - struct lpfc_dmabuf *mp = NULL; - uint32_t *lp; - IOCB_t *icmd; struct ls_rjt stat; + uint32_t *lp; uint32_t cmd, did, newnode, rjt_err = 0; - uint32_t drop_cmd = 0; /* by default do NOT drop received cmd */ - struct lpfc_vport *vport = NULL; - - psli = &phba->sli; - icmd = &elsiocb->iocb; + IOCB_t *icmd = &elsiocb->iocb; - if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && - ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { - phba->fc_stat.NoRcvBuf++; - /* Not enough posted buffers; Try posting more buffers */ - lpfc_post_buffer(phba, pring, 0, 1); - return; - } - - /* If there are no BDEs associated with this IOCB, - * there is nothing to do. - */ - if (icmd->ulpBdeCount == 0) - return; - - /* type of ELS cmd is first 32bit word in packet */ - mp = lpfc_sli_ringpostbuf_get(phba, pring, - getPaddr(icmd->un.cont64[0].addrHigh, - icmd->un.cont64[0].addrLow)); - if (mp == 0) { - drop_cmd = 1; + if (!vport || !mp) goto dropit; - } - - vport = phba->pport; newnode = 0; lp = (uint32_t *) mp->virt; cmd = *lp++; - lpfc_post_buffer(phba, &psli->ring[LPFC_ELS_RING], 1, 1); + if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) + lpfc_post_buffer(phba, pring, 1, 1); - if (icmd->ulpStatus) { - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - drop_cmd = 1; + if (icmd->ulpStatus) goto dropit; - } /* Check to see if link went down during discovery */ - if (lpfc_els_chk_latt(vport)) { - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - drop_cmd = 1; + if (lpfc_els_chk_latt(vport)) goto dropit; - } did = icmd->un.rcvels.remoteID; ndlp = lpfc_findnode_did(vport, did); if (!ndlp) { /* Cannot find existing Fabric ndlp, so allocate a new one */ ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); - if (!ndlp) { - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); - drop_cmd = 1; + if (!ndlp) goto dropit; - } lpfc_nlp_init(vport, ndlp, did); newnode = 1; @@ -3428,7 +3377,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0112 ELS command x%x received from NPORT x%x " "Data: x%x\n", phba->brd_no, cmd, did, - vport->port_state); + vport->port_state); switch (cmd) { case ELS_CMD_PLOGI: @@ -3537,8 +3486,9 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* Unknown ELS command <elsCmd> received from NPORT <did> */ lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d:0115 Unknown ELS command x%x received from " - "NPORT x%x\n", phba->brd_no, cmd, did); + "%d:0115 Unknown ELS command x%x " + "received from NPORT x%x\n", + phba->brd_no, cmd, did); if (newnode) lpfc_drop_node(vport, ndlp); break; @@ -3553,20 +3503,89 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp); } + return; + +dropit: + lpfc_printf_log(phba, KERN_ERR, LOG_ELS, + "%d:0111 Dropping received ELS cmd " + "Data: x%x x%x x%x\n", + phba->brd_no, + icmd->ulpStatus, icmd->un.ulpWord[4], + icmd->ulpTimeout); + phba->fc_stat.elsRcvDrop++; +} + + +void +lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + struct lpfc_iocbq *elsiocb) +{ + struct lpfc_vport *vport = phba->pport; + struct lpfc_dmabuf *mp = NULL; + IOCB_t *icmd = &elsiocb->iocb; + struct hbq_dmabuf *sp = NULL; + dma_addr_t paddr; + + if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && + ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { + phba->fc_stat.NoRcvBuf++; + /* Not enough posted buffers; Try posting more buffers */ + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) + lpfc_sli_hbqbuf_fill_hbq(phba); + else + lpfc_post_buffer(phba, pring, 0, 1); + return; + } + + /* If there are no BDEs associated with this IOCB, + * there is nothing to do. + */ + if (icmd->ulpBdeCount == 0) + return; + + /* type of ELS cmd is first 32bit word in packet */ + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { + paddr = getPaddr(icmd->un.cont64[0].addrHigh, + icmd->un.cont64[0].addrLow); + sp = lpfc_sli_hbqbuf_find(phba, icmd->un.ulpWord[3]); + if (sp) + phba->hbq_buff_count--; + mp = sp ? &sp->dbuf : NULL; + } else { + paddr = getPaddr(icmd->un.cont64[0].addrHigh, + icmd->un.cont64[0].addrLow); + mp = lpfc_sli_ringpostbuf_get(phba, pring, paddr); + } + + lpfc_els_unsol_buffer(phba, pring, vport, mp, elsiocb); + lpfc_nlp_put(elsiocb->context1); elsiocb->context1 = NULL; if (elsiocb->context2) { - lpfc_mbuf_free(phba, mp->virt, mp->phys); - kfree(mp); + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) + lpfc_sli_free_hbq(phba, sp); + else { + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } } -dropit: - /* check if need to drop received ELS cmd */ - if (drop_cmd == 1) { - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d:0111 Dropping received ELS cmd " - "Data: x%x x%x x%x\n", phba->brd_no, - icmd->ulpStatus, icmd->un.ulpWord[4], - icmd->ulpTimeout); - phba->fc_stat.elsRcvDrop++; + + /* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */ + if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) != 0 && + icmd->ulpBdeCount == 2) { + sp = lpfc_sli_hbqbuf_find(phba, icmd->un.ulpWord[15]); + if (sp) + phba->hbq_buff_count--; + mp = sp ? &sp->dbuf : NULL; + lpfc_els_unsol_buffer(phba, pring, vport, mp, elsiocb); + /* free mp if we are done with it */ + if (elsiocb->context2) { + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) + lpfc_sli_free_hbq(phba, sp); + else { + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } + } } } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index dee875ee616..20b2a4905da 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -232,9 +232,9 @@ static void lpfc_work_done(struct lpfc_hba *phba) { struct lpfc_sli_ring *pring; - int i; uint32_t ha_copy, control, work_port_events; struct lpfc_vport *vport; + int i; spin_lock_irq(&phba->hbalock); ha_copy = phba->work_ha; @@ -303,9 +303,9 @@ check_work_wait_done(struct lpfc_hba *phba) struct lpfc_vport *vport = phba->pport; int rc = 0; - if (!vport) return 0; + spin_lock_irq(&phba->hbalock); if (phba->work_ha || @@ -354,6 +354,7 @@ lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2, uint32_t evt) { struct lpfc_work_evt *evtp; + unsigned long flags; /* * All Mailbox completions and LPFC_ELS_RING rcv ring IOCB events will @@ -367,11 +368,11 @@ lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2, evtp->evt_arg2 = arg2; evtp->evt = evt; - spin_lock_irq(&phba->hbalock); + spin_lock_irqsave(&phba->hbalock, flags); list_add_tail(&evtp->evt_listp, &phba->work_list); if (phba->work_wait) wake_up(phba->work_wait); - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->hbalock, flags); return 1; } @@ -401,6 +402,7 @@ lpfc_linkdown(struct lpfc_hba *phba) mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (mb) { lpfc_unreg_did(phba, 0xffffffff, mb); + mb->vport = vport; mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB)) == MBX_NOT_FINISHED) { @@ -433,6 +435,7 @@ lpfc_linkdown(struct lpfc_hba *phba) if (mb) { lpfc_config_link(phba, mb); mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl; + mb->vport = vport; if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB)) == MBX_NOT_FINISHED) { @@ -550,15 +553,11 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) spin_unlock_irq(shost->host_lock); } - printk(KERN_ERR "%s (%d): vport ready\n", - __FUNCTION__, __LINE__); vport->port_state = LPFC_VPORT_READY; out: /* Device Discovery completes */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_DISCOVERY, + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d:0225 Device Discovery completes\n", phba->brd_no); @@ -632,8 +631,6 @@ out: phba->brd_no, vport->port_state); lpfc_clear_la(phba, pmb); - printk(KERN_ERR "%s (%d): do clear_la\n", - __FUNCTION__, __LINE__); pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la; pmb->vport = vport; rc = lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)); @@ -643,8 +640,6 @@ out: psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; - printk(KERN_ERR "%s (%d): vport ready\n", - __FUNCTION__, __LINE__); vport->port_state = LPFC_VPORT_READY; } return; @@ -702,8 +697,6 @@ out: struct lpfc_sli_ring *next_ring = &psli->ring[psli->next_ring]; lpfc_clear_la(phba, pmb); - printk(KERN_ERR "%s (%d): do clear_la\n", - __FUNCTION__, __LINE__); pmb->mbox_cmpl = lpfc_mbx_cmpl_clear_la; pmb->vport = vport; if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)) @@ -713,8 +706,6 @@ out: extra_ring->flag &= ~LPFC_STOP_IOCB_EVENT; fcp_ring->flag &= ~LPFC_STOP_IOCB_EVENT; next_ring->flag &= ~LPFC_STOP_IOCB_EVENT; - printk(KERN_ERR "%s (%d): vport ready\n", - __FUNCTION__, __LINE__); vport->port_state = LPFC_VPORT_READY; } } else { @@ -875,12 +866,9 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Check for error */ if (mb->mbxStatus) { - lpfc_printf_log(phba, - KERN_INFO, - LOG_LINK_EVENT, + lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, "%d:1307 READ_LA mbox error x%x state x%x\n", - phba->brd_no, - mb->mbxStatus, vport->port_state); + phba->brd_no, mb->mbxStatus, vport->port_state); lpfc_mbx_issue_link_down(phba); phba->link_state = LPFC_HBA_ERROR; goto lpfc_mbx_cmpl_read_la_free_mbuf; @@ -955,7 +943,6 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) struct lpfc_dmabuf *mp = (struct lpfc_ |