Commit ed957684 authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc: NPIV: add SLI-3 interface

NPIV support is only available via new adapter interface extensions,
termed SLI-3. This interface changes some of the basic behaviors such
as command and response ring element sizes and data structures, as
well as a change in buffer posting.  Note: the new firmware extensions
are found only on our mid-range and enterprise 4Gig adapters - so NPIV
support is available only on these newer adapters. The latest firmware
can be downloaded from the Emulex support page.
Signed-off-by: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 2e0fef85
...@@ -63,6 +63,11 @@ struct lpfc_dma_pool { ...@@ -63,6 +63,11 @@ struct lpfc_dma_pool {
uint32_t current_count; 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. */ /* Priority bit. Set value to exceed low water mark in lpfc_mem. */
#define MEM_PRI 0x100 #define MEM_PRI 0x100
...@@ -276,8 +281,25 @@ struct lpfc_vport { ...@@ -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_hba {
struct lpfc_sli sli; 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; enum hba_state link_state;
uint32_t link_flag; /* link state flags */ uint32_t link_flag; /* link state flags */
...@@ -286,8 +308,6 @@ struct lpfc_hba { ...@@ -286,8 +308,6 @@ struct lpfc_hba {
/* INIT_LINK mailbox command */ /* INIT_LINK mailbox command */
#define LS_IGNORE_ERATT 0x80000 /* intr handler should ignore ERATT */ #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_sli2_slim *slim2p;
struct lpfc_dmabuf hbqslimp; struct lpfc_dmabuf hbqslimp;
...@@ -371,6 +391,12 @@ struct lpfc_hba { ...@@ -371,6 +391,12 @@ struct lpfc_hba {
wait_queue_head_t *work_wait; wait_queue_head_t *work_wait;
struct task_struct *worker_thread; 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_bar0_map; /* Physical address for PCI BAR0 */
unsigned long pci_bar2_map; /* Physical address for PCI BAR2 */ unsigned long pci_bar2_map; /* Physical address for PCI BAR2 */
void __iomem *slim_memmap_p; /* Kernel memory mapped address for void __iomem *slim_memmap_p; /* Kernel memory mapped address for
...@@ -385,6 +411,10 @@ struct lpfc_hba { ...@@ -385,6 +411,10 @@ struct lpfc_hba {
reg */ reg */
void __iomem *HCregaddr; /* virtual address for host ctl 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 */ int brd_no; /* FC board number */
char SerialNumber[32]; /* adapter Serial Number */ char SerialNumber[32]; /* adapter Serial Number */
...@@ -425,6 +455,7 @@ struct lpfc_hba { ...@@ -425,6 +455,7 @@ struct lpfc_hba {
/* pci_mem_pools */ /* pci_mem_pools */
struct pci_pool *lpfc_scsi_dma_buf_pool; struct pci_pool *lpfc_scsi_dma_buf_pool;
struct pci_pool *lpfc_mbuf_pool; struct pci_pool *lpfc_mbuf_pool;
struct pci_pool *lpfc_hbq_pool;
struct lpfc_dma_pool lpfc_mbuf_safety_pool; struct lpfc_dma_pool lpfc_mbuf_safety_pool;
mempool_t *mbox_mem_pool; mempool_t *mbox_mem_pool;
......
...@@ -138,6 +138,10 @@ void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *); ...@@ -138,6 +138,10 @@ void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
int lpfc_mbox_tmo_val(struct lpfc_hba *, int); 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 *); int lpfc_mem_alloc(struct lpfc_hba *);
void lpfc_mem_free(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 *, ...@@ -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_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
struct lpfc_sli_ring *, struct lpfc_sli_ring *,
dma_addr_t); 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 *, int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *); struct lpfc_iocbq *);
int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, 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, ...@@ -198,6 +208,9 @@ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba,
struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb); 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_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);
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 *); ...@@ -213,6 +226,7 @@ void lpfc_free_sysfs_attr(struct lpfc_vport *);
extern struct class_device_attribute *lpfc_hba_attrs[]; extern struct class_device_attribute *lpfc_hba_attrs[];
extern struct scsi_host_template lpfc_template; extern struct scsi_host_template lpfc_template;
extern struct fc_function_template lpfc_transport_functions; 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_get_hba_sym_node_name(struct lpfc_hba *phba, uint8_t *symbp);
void lpfc_terminate_rport_io(struct fc_rport *); void lpfc_terminate_rport_io(struct fc_rport *);
......
...@@ -58,25 +58,66 @@ static char *lpfc_release_version = LPFC_DRIVER_VERSION; ...@@ -58,25 +58,66 @@ static char *lpfc_release_version = LPFC_DRIVER_VERSION;
/* /*
* lpfc_ct_unsol_event * 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 void
lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocbq) struct lpfc_iocbq *piocbq)
{ {
struct lpfc_dmabuf *mp = NULL;
struct lpfc_iocbq *next_piocbq; struct hbq_dmabuf *sp = NULL;
struct lpfc_dmabuf *pmbuf = NULL;
struct lpfc_dmabuf *matp = NULL, *next_matp;
uint32_t ctx = 0, size = 0, cnt = 0;
IOCB_t *icmd = &piocbq->iocb; IOCB_t *icmd = &piocbq->iocb;
IOCB_t *save_icmd = icmd; int i;
int i, go_exit = 0; struct lpfc_iocbq *iocbq;
struct list_head head; dma_addr_t paddr;
uint32_t size;
if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && 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 */ /* Not enough posted buffers; Try posting more buffers */
phba->fc_stat.NoRcvBuf++; 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; return;
} }
...@@ -86,62 +127,62 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -86,62 +127,62 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
if (icmd->ulpBdeCount == 0) if (icmd->ulpBdeCount == 0)
return; return;
INIT_LIST_HEAD(&head); if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
list_add_tail(&head, &piocbq->list); list_for_each_entry(iocbq, &piocbq->list, list) {
icmd = &iocbq->iocb;
list_for_each_entry_safe(piocbq, next_piocbq, &head, list) { if (icmd->ulpBdeCount == 0) {
icmd = &piocbq->iocb; printk(KERN_ERR "%s (%d): Unsolited CT, no "
if (ctx == 0) "BDE, iocbq = %p, status = x%x\n",
ctx = (uint32_t) (icmd->ulpContext); __FUNCTION__, __LINE__,
if (icmd->ulpBdeCount == 0) iocbq, iocbq->iocb.ulpStatus);
continue; 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;
} }
/* Typically for Unsolicited CT requests */ size = icmd->un.cont64[0].tus.f.bdeSize;
if (!pmbuf) { sp = lpfc_sli_hbqbuf_find(phba, icmd->un.ulpWord[3]);
pmbuf = matp; if (sp)
INIT_LIST_HEAD(&pmbuf->list); phba->hbq_buff_count--;
} else lpfc_ct_ignore_hbq_buffer(phba, iocbq, sp, size);
list_add_tail(&matp->list, &pmbuf->list); 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; for (i = 0; i < icmd->ulpBdeCount; i++) {
} paddr = getPaddr(icmd->un.cont64[i].addrHigh,
icmd->un.cont64[i].addrLow);
lpfc_post_buffer(phba, pring, cnt, 1); mp = lpfc_sli_ringpostbuf_get(phba, pring,
if (save_icmd->ulpStatus) { paddr);
go_exit = 1; size = icmd->un.cont64[i].tus.f.bdeSize;
} lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
ct_unsol_event_exit_piocbq: kfree(mp);
list_del(&head); }
if (pmbuf) { list_del(&iocbq->list);
list_for_each_entry_safe(matp, next_matp, &pmbuf->list, list) { lpfc_sli_release_iocbq(phba, iocbq);
lpfc_mbuf_free(phba, matp->virt, matp->phys);
list_del(&matp->list);
kfree(matp);
} }
lpfc_mbuf_free(phba, pmbuf->virt, pmbuf->phys);
kfree(pmbuf);
} }
return;
} }
static void static void
...@@ -364,9 +405,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) ...@@ -364,9 +405,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
vport->fc_flag, vport->fc_flag,
vport->fc_rscn_id_cnt); vport->fc_rscn_id_cnt);
} else { } else {
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
KERN_INFO,
LOG_DISCOVERY,
"%d:0239 Skip x%x NameServer " "%d:0239 Skip x%x NameServer "
"Rsp Data: x%x x%x x%x\n", "Rsp Data: x%x x%x x%x\n",
phba->brd_no, phba->brd_no,
...@@ -717,12 +756,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -717,12 +756,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
ndlp = lpfc_findnode_did(vport, FDMI_DID); ndlp = lpfc_findnode_did(vport, FDMI_DID);
if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
/* FDMI rsp failed */ /* FDMI rsp failed */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
KERN_INFO, "%d:0220 FDMI rsp failed Data: x%x\n",
LOG_DISCOVERY, phba->brd_no, be16_to_cpu(fdmi_cmd));
"%d:0220 FDMI rsp failed Data: x%x\n",
phba->brd_no,
be16_to_cpu(fdmi_cmd));
} }
switch (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) ...@@ -791,9 +827,7 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
INIT_LIST_HEAD(&bmp->list); INIT_LIST_HEAD(&bmp->list);
/* FDMI request */ /* FDMI request */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
KERN_INFO,
LOG_DISCOVERY,
"%d:0218 FDMI Request Data: x%x x%x x%x\n", "%d:0218 FDMI Request Data: x%x x%x x%x\n",
phba->brd_no, phba->brd_no,
vport->fc_flag, vport->port_state, cmdcode); vport->fc_flag, vport->port_state, cmdcode);
...@@ -1120,12 +1154,9 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) ...@@ -1120,12 +1154,9 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
kfree(mp); kfree(mp);
fdmi_cmd_exit: fdmi_cmd_exit:
/* Issue FDMI request failed */ /* Issue FDMI request failed */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
KERN_INFO,
LOG_DISCOVERY,
"%d:0244 Issue FDMI request failed Data: x%x\n", "%d:0244 Issue FDMI request failed Data: x%x\n",
phba->brd_no, phba->brd_no, cmdcode);
cmdcode);
return 1; return 1;
} }
......
...@@ -45,9 +45,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) ...@@ -45,9 +45,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
LPFC_MBOXQ_t *mbox;
uint32_t ha_copy; uint32_t ha_copy;
int rc;
if (vport->port_state >= LPFC_VPORT_READY || if (vport->port_state >= LPFC_VPORT_READY ||
phba->link_state == LPFC_LINK_DOWN) phba->link_state == LPFC_LINK_DOWN)
...@@ -76,20 +74,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) ...@@ -76,20 +74,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport)
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
if (phba->link_state != LPFC_CLEAR_LA) { if (phba->link_state != LPFC_CLEAR_LA) {
if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) { lpfc_issue_clear_la(phba, vport);
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;
}
}
} }
return 1; return 1;
...@@ -153,8 +138,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, ...@@ -153,8 +138,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
/* Allocate buffer for Buffer ptr list */ /* Allocate buffer for Buffer ptr list */
pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
if (pbuflist) if (pbuflist)
pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
&pbuflist->phys); &pbuflist->phys);
if (pbuflist == 0 || pbuflist->virt == 0) { if (pbuflist == 0 || pbuflist->virt == 0) {
lpfc_sli_release_iocbq(phba, elsiocb); lpfc_sli_release_iocbq(phba, elsiocb);
lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); 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, ...@@ -289,6 +274,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
vport->port_state = LPFC_FABRIC_CFG_LINK; vport->port_state = LPFC_FABRIC_CFG_LINK;
lpfc_config_link(phba, mbox); lpfc_config_link(phba, mbox);
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
if (rc == MBX_NOT_FINISHED) if (rc == MBX_NOT_FINISHED)
...@@ -364,6 +350,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -364,6 +350,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_config_link(phba, mbox); lpfc_config_link(phba, mbox);
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, mbox, rc = lpfc_sli_issue_mbox(phba, mbox,
MBX_NOWAIT | MBX_STOP_IOCB); MBX_NOWAIT | MBX_STOP_IOCB);
if (rc == MBX_NOT_FINISHED) { if (rc == MBX_NOT_FINISHED) {
...@@ -714,8 +701,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -714,8 +701,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
irsp = &rspiocb->iocb; irsp = &rspiocb->iocb;
ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
if (!ndlp)
if (!ndlp) {
goto out; goto out;
}
/* Since ndlp can be freed in the disc state machine, note if this node /* Since ndlp can be freed in the disc state machine, note if this node
* is being used during discovery. * is being used during discovery.
...@@ -1110,9 +1099,8 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -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 we get here, there is nothing left to wait for */
if (vport->port_state < LPFC_VPORT_READY && if (vport->port_state < LPFC_VPORT_READY &&
phba->link_state != LPFC_CLEAR_LA) { 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); lpfc_issue_clear_la(phba, vport);
}
} else { } else {
lpfc_rscn_disc(vport); lpfc_rscn_disc(vport);
} }
...@@ -1420,6 +1408,27 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) ...@@ -1420,6 +1408,27 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
return 0; 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 void
lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) 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) ...@@ -1449,24 +1458,7 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
vport->fc_flag &= ~FC_NDISC_ACTIVE; vport->fc_flag &= ~FC_NDISC_ACTIVE;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
lpfc_can_disctmo(vport); lpfc_can_disctmo(vport);
if (vport->fc_flag & FC_RSCN_MODE) { lpfc_end_rscn(vport);
/*
* 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);
}
}
} }
} }
} }
...@@ -1689,6 +1681,9 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -1689,6 +1681,9 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
retry = 0; retry = 0;
} }
if ((vport->load_flag & FC_UNLOADING) != 0)
retry = 0;
if (retry) { if (retry) {
/* Retry ELS command <elsCmd> to remote NPORT <did> */ /* 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, ...@@ -2141,9 +2136,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
cmdsize = sizeof (uint32_t) + sizeof (PRLI); cmdsize = sizeof (uint32_t) + sizeof (PRLI);
elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
ndlp->nlp_DID, ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
(ELS_CMD_ACC |
(ELS_CMD_PRLI & ~ELS_RSP_MASK)));
if (!elsiocb) if (!elsiocb)
return 1; return 1;
...@@ -2361,8 +2354,12 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport) ...@@ -2361,8 +2354,12 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport)
for (i = 0; i < vport->fc_rscn_id_cnt; i++) { for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
mp = vport->fc_rscn_id_list[i]; mp = vport->fc_rscn_id_list[i];
lpfc_mbuf_free(phba, mp->virt, mp->phys); if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
kfree(mp); 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; vport->fc_rscn_id_list[i] = NULL;
} }
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
...@@ -2486,9 +2483,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -2486,9 +2483,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
cmd &= ELS_CMD_MASK; cmd &= ELS_CMD_MASK;
/* RSCN received */ /* RSCN received */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
KERN_INFO,
LOG_DISCOVERY,
"%d:0214 RSCN received Data: x%x x%x x%x x%x\n", "%d:0214 RSCN received Data: x%x x%x x%x x%x\n",
phba->brd_no, vport->fc_flag, payload_len, *lp, phba->brd_no, vport->fc_flag, payload_len, *lp,
vport->fc_rscn_id_cnt); vport->fc_rscn_id_cnt);
...@@ -2581,9 +2576,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) ...@@ -2581,9 +2576,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
lpfc_set_disctmo(vport); lpfc_set_disctmo(vport);
/* RSCN processed */ /* RSCN processed */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
KERN_INFO,
LOG_DISCOVERY,
"%d:0215 RSCN processed Data: x%x x%x x%x x%x\n", "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n",
phba->brd_no, phba->brd_no,
vport->fc_flag, 0, vport->fc_rscn_id_cnt, 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, ...@@ -2683,6 +2676,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
phba->cfg_link_speed); phba->cfg_link_speed);
mbox->mb.un.varInitLnk.lipsr_AL_PA = 0; mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
rc = lpfc_sli_issue_mbox rc = lpfc_sli_issue_mbox
(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
lpfc_set_loopback_flag(phba); lpfc_set_loopback_flag(phba);
...@@ -2837,10 +2831,8 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -2837,10 +2831,8 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
phba->fc_stat.elsXmitACC++; 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); lpfc_els_free_iocb(phba, elsiocb);
}
return; return;
} }
...@@ -3015,9 +3007,7 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3015,9 +3007,7 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
fp = (FARP *) lp; fp = (FARP *) lp;
/* FARP-REQ received from DID <did> */ /* FARP-REQ received from DID <did> */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
KERN_INFO,
LOG_ELS,
"%d:0601 FARP-REQ received from DID x%x\n", "%d:0601 FARP-REQ received from DID x%x\n",
phba->brd_no, did); phba->brd_no, did);
...@@ -3077,12 +3067,9 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3077,12 +3067,9 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
cmd = *lp++; cmd = *lp++;
/* FARP-RSP received from DID <did> */ /* FARP-RSP received from DID <did> */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
KERN_INFO,
LOG_ELS,
"%d:0600 FARP-RSP received from DID x%x\n", "%d:0600 FARP-RSP received from DID x%x\n",
phba->brd_no, did); phba->brd_no, did);
/* ACCEPT the Farp resp request */ /* ACCEPT the Farp resp request */
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); 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, ...@@ -3102,8 +3089,9 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
/* FAN received */ /* FAN received */
lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n", lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
phba->brd_no); "%d:0265 FAN received\n",
phba->brd_no);
icmd = &cmdiocb->iocb; icmd = &cmdiocb->iocb;
did = icmd->un.elsreq64.remoteID; did = icmd->un.elsreq64.remoteID;
...@@ -3332,79 +3320,40 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) ...@@ -3332,79 +3320,40 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
return; return;
} }
void static void
lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *elsiocb) struct lpfc_vport *vport, struct lpfc_dmabuf *mp,
struct lpfc_iocbq *elsiocb)
{ {
struct lpfc_sli *psli;
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp;
struct lpfc_dmabuf *mp = NULL;
uint32_t *lp;
IOCB_t *icmd;
struct ls_rjt stat; struct ls_rjt stat;
uint32_t *lp;
uint32_t cmd, did, newnode, rjt_err = 0; uint32_t cmd, did, newnode, rjt_err = 0;
uint32_t drop_cmd = 0; /* by default do NOT drop received cmd */ IOCB_t *icmd = &elsiocb->iocb;
struct lpfc_vport *vport = NULL;
psli = &phba->sli;
icmd = &elsiocb->iocb;
if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && if (!vport || !mp)
((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;
goto dropit; goto dropit;
}
vport = phba->pport;
newnode = 0; newnode = 0;
lp = (uint32_t *) mp->virt; lp = (uint32_t *) mp->virt;
cmd = *lp++; 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) { if (icmd->ulpStatus)
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
drop_cmd = 1;
goto dropit; goto dropit;
}
/* Check to see if link went down during discovery */ /* Check to see if link went down during discovery */
if (lpfc_els_chk_latt(vport)) { if (lpfc_els_chk_latt(vport))
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
drop_cmd = 1;
goto dropit; goto dropit;
}
did = icmd->un.rcvels.remoteID; did = icmd->un.rcvels.remoteID;
ndlp = lpfc_findnode_did(vport, did); ndlp = lpfc_findnode_did(vport, did);
if (!ndlp) { if (!ndlp) {
/* Cannot find existing Fabric ndlp, so allocate a new one */ /* Cannot find existing Fabric ndlp, so allocate a new one */
ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
if (!ndlp) { if (!ndlp)
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
drop_cmd = 1;
goto dropit; goto dropit;
}
lpfc_nlp_init(vport, ndlp, did); lpfc_nlp_init(vport, ndlp, did);
newnode = 1; newnode = 1;
...@@ -3428,7 +3377,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -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, lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
"%d:0112 ELS command x%x received from NPORT x%x " "%d:0112 ELS command x%x received from NPORT x%x "
"Data: x%x\n", phba->brd_no, cmd, did, "Data: x%x\n", phba->brd_no, cmd, did,
vport->port_state); vport->port_state);
switch (cmd) { switch (cmd) {
case ELS_CMD_PLOGI: case ELS_CMD_PLOGI:
...@@ -3537,8 +3486,9 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -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> */ /* Unknown ELS command <elsCmd> received from NPORT <did> */
lpfc_printf_log(phba, KERN_ERR, LOG_ELS, lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
"%d:0115 Unknown ELS command x%x received from " "%d:0115 Unknown ELS command x%x "
"NPORT x%x\n", phba->brd_no, cmd, did); "received from NPORT x%x\n",
phba->brd_no, cmd, did);
if (newnode) if (newnode)
lpfc_drop_node(vport, ndlp); lpfc_drop_node(vport, ndlp);
break; break;
...@@ -3553,20 +3503,89 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -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); 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); lpfc_nlp_put(elsiocb->context1);
elsiocb->context1 = NULL; elsiocb->context1 = NULL;
if (elsiocb->context2) { if (elsiocb->context2) {
lpfc_mbuf_free(phba, mp->virt, mp->phys); if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
kfree(mp); 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 */ /* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */
if (drop_cmd == 1) { if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) != 0 &&
lpfc_printf_log(phba, KERN_ERR, LOG_ELS, icmd->ulpBdeCount == 2) {
"%d:0111 Dropping received ELS cmd " sp = lpfc_sli_hbqbuf_find(phba, icmd->un.ulpWord[15]);
"Data: x%x x%x x%x\n", phba->brd_no, if (sp)
icmd->ulpStatus, icmd->un.ulpWord[4], phba->hbq_buff_count--;
icmd->ulpTimeout); mp = sp ? &sp->dbuf : NULL;
phba->fc_stat.elsRcvDrop++; 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);
}
}
} }
} }
...@@ -232,9 +232,9 @@ static void ...@@ -232,9 +232,9 @@ static void
lpfc_work_done(struct lpfc_hba *phba) lpfc_work_done(struct lpfc_hba *phba)
{ {
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
int i;
uint32_t ha_copy, control, work_port_events; uint32_t ha_copy, control, work_port_events;
struct lpfc_vport *vport; struct lpfc_vport *vport;
int i;
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
ha_copy = phba->work_ha; ha_copy = phba->work_ha;
...@@ -303,9 +303,9 @@ check_work_wait_done(struct lpfc_hba *phba) ...@@ -303,9 +303,9 @@ check_work_wait_done(struct lpfc_hba *phba)
struct lpfc_vport *vport = phba->pport; struct lpfc_vport *vport = phba->pport;
int rc = 0; int rc = 0;
if (!vport) if (!vport)
return 0; return 0;
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
if (phba->work_ha || if (phba->work_ha ||
...@@ -354,6 +354,7 @@ lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2, ...@@ -354,6 +354,7 @@ lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2,
uint32_t evt) uint32_t evt)
{ {
struct lpfc_work_evt *evtp; struct lpfc_work_evt *evtp;
unsigned long flags;
/* /*
* All Mailbox completions and LPFC_ELS_RING rcv ring IOCB events will * 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, ...@@ -367,11 +368,11 @@ lpfc_workq_post_event(struct lpfc_hba *phba, void *arg1, void *arg2,
evtp->evt_arg2 = arg2; evtp->evt_arg2 = arg2;
evtp->evt = evt; evtp->evt = evt;
spin_lock_irq(&phba->hbalock); spin_lock_irqsave(&phba->hbalock, flags);
list_add_tail(&evtp->evt_listp, &phba->work_list); list_add_tail(&evtp->evt_listp, &phba->work_list);
if (phba->work_wait) if (phba->work_wait)
wake_up(phba->work_wait); wake_up(phba->work_wait);
spin_unlock_irq(&phba->hbalock); spin_unlock_irqrestore(&phba->hbalock, flags);
return 1; return 1;
} }
...@@ -401,6 +402,7 @@ lpfc_linkdown(struct lpfc_hba *phba) ...@@ -401,6 +402,7 @@ lpfc_linkdown(struct lpfc_hba *phba)
mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mb) { if (mb) {
lpfc_unreg_did(phba, 0xffffffff, mb); lpfc_unreg_did(phba, 0xffffffff, mb);
mb->vport = vport;
mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB)) if (lpfc_sli_issue_mbox(phba, mb, (MBX_NOWAIT | MBX_STOP_IOCB))
== MBX_NOT_FINISHED) { == MBX_NOT_FINISHED) {
...@@ -433,6 +435,7 @@ lpfc_linkdown(struct lpfc_hba *phba) ...@@ -433,6 +435,7 @@ lpfc_linkdown(struct lpfc_hba *phba)
if (mb) { if (mb) {
lpfc_config_link(phba, mb); lpfc_config_link(phba, mb);
mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl; mb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
mb->vport = vport;
if (lpfc_sli_issue_mbox(phba, mb, if (lpfc_sli_issue_mbox(phba, mb,
(MBX_NOWAIT | MBX_STOP_IOCB)) (MBX_NOWAIT | MBX_STOP_IOCB))
== MBX_NOT_FINISHED) { == MBX_NOT_FINISHED) {
...@@ -550,15 +553,11 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -550,15 +553,11 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
printk(KERN_ERR "%s (%d): vport ready\n",
__FUNCTION__, __LINE__);
vport->port_state = LPFC_VPORT_READY; vport->port_state = LPFC_VPORT_READY;
out: out:
/* Device Discovery completes */ /* Device Discovery completes */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
KERN_INFO,
LOG_DISCOVERY,
"%d:0225 Device Discovery completes\n", "%d:0225 Device Discovery completes\n",
phba->brd_no); phba->brd_no);
...@@ -632,8 +631,6 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -632,8 +631,6 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
phba->brd_no, vport->port_state); phba->brd_no, vport->port_state);
lpfc_clear_la(phba, pmb); 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->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
pmb->vport = vport; pmb->vport = vport;
rc = lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)); rc = lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
...@@ -643,8 +640,6 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -643,8 +640,6 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->fcp_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; 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; vport->port_state = LPFC_VPORT_READY;
} }
return; return;
...@@ -702,8 +697,6 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -702,8 +697,6 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct lpfc_sli_ring *next_ring = &psli->ring[psli->next_ring]; struct lpfc_sli_ring *next_ring = &psli->ring[psli->next_ring];
lpfc_clear_la(phba, pmb); 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->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
pmb->vport = vport; pmb->vport = vport;
if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)) if (lpfc_sli_issue_mbox(phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB))
...@@ -713,8 +706,6 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -713,8 +706,6 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
extra_ring->flag &= ~LPFC_STOP_IOCB_EVENT; extra_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
fcp_ring->flag &= ~LPFC_STOP_IOCB_EVENT; fcp_ring->flag &= ~LPFC_STOP_IOCB_EVENT;
next_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; vport->port_state = LPFC_VPORT_READY;
} }
} else { } else {
...@@ -875,12 +866,9 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -875,12 +866,9 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
/* Check for error */ /* Check for error */
if (mb->mbxStatus) { if (mb->mbxStatus) {
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
KERN_INFO,
LOG_LINK_EVENT,
"%d:1307 READ_LA mbox error x%x state x%x\n", "%d:1307 READ_LA mbox error x%x state x%x\n",
phba->brd_no, phba->brd_no, mb->mbxStatus, vport->port_state);
mb->mbxStatus, vport->port_state);
lpfc_mbx_issue_link_down(phba); lpfc_mbx_issue_link_down(phba);
phba->link_state = LPFC_HBA_ERROR; phba->link_state = LPFC_HBA_ERROR;
goto lpfc_mbx_cmpl_read_la_free_mbuf; 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) ...@@ -955,7 +943,6 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) pmb->context1;
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
pmb->context1 = NULL; pmb->context1 = NULL;
/* Good status, call state machine */ /* Good status, call state machine */
...@@ -1553,6 +1540,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -1553,6 +1540,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox) { if (mbox) {
lpfc_unreg_login(phba, ndlp->nlp_rpi, mbox); lpfc_unreg_login(phba, ndlp->nlp_rpi, mbox);
mbox->vport = vport;
mbox->mbox_cmpl=lpfc_sli_def_mbox_cmpl; mbox->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
rc = lpfc_sli_issue_mbox rc = lpfc_sli_issue_mbox
(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
...@@ -1925,8 +1913,6 @@ lpfc_disc_start(struct lpfc_vport *vport) ...@@ -1925,8 +1913,6 @@ lpfc_disc_start(struct lpfc_vport *vport)
if (vport->port_state < LPFC_VPORT_READY && !clear_la_pending) { if (vport->port_state < LPFC_VPORT_READY && !clear_la_pending) {
if (vport->port_type == LPFC_PHYSICAL_PORT) { if (vport->port_type == LPFC_PHYSICAL_PORT) {
/* If we get here, there is nothing to ADISC */ /* If we get here, there is nothing to ADISC */
printk(KERN_ERR "%s (%d): do clear_la\n",
__FUNCTION__, __LINE__);
lpfc_issue_clear_la(phba, vport); lpfc_issue_clear_la(phba, vport);
} else if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) { } else if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
...@@ -1940,8 +1926,6 @@ lpfc_disc_start(struct lpfc_vport *vport) ...@@ -1940,8 +1926,6 @@ lpfc_disc_start(struct lpfc_vport *vport)
vport->fc_flag &= ~FC_NDISC_ACTIVE; vport->fc_flag &= ~FC_NDISC_ACTIVE;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
printk(KERN_ERR "%s (%d): vport ready\n",
__FUNCTION__, __LINE__);
vport->port_state = LPFC_VPORT_READY; vport->port_state = LPFC_VPORT_READY;
} }
} else { } else {
...@@ -2095,13 +2079,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2095,13 +2079,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
if (!(vport->fc_flag & FC_DISC_TMO)) if (!(vport->fc_flag & FC_DISC_TMO))
return; return;
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_DISC_TMO; vport->fc_flag &= ~FC_DISC_TMO;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
printk(KERN_ERR "%s (%d): link_state = %d, port_state = %d\n",
__FUNCTION__, __LINE__, phba->link_state, vport->port_state);
switch (vport->port_state) { switch (vport->port_state) {
case LPFC_LOCAL_CFG_LINK: case LPFC_LOCAL_CFG_LINK:
...@@ -2109,9 +2090,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2109,9 +2090,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
* FAN * FAN
*/ */
/* FAN timeout */ /* FAN timeout */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY,
KERN_WARNING,
LOG_DISCOVERY,
"%d:0221 FAN timeout\n", "%d:0221 FAN timeout\n",
phba->brd_no); phba->brd_no);
...@@ -2138,9 +2117,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2138,9 +2117,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
case LPFC_FLOGI: case LPFC_FLOGI:
/* port_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */ /* port_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
/* Initial FLOGI timeout */ /* Initial FLOGI timeout */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
KERN_ERR,
LOG_DISCOVERY,
"%d:0222 Initial FLOGI timeout\n", "%d:0222 Initial FLOGI timeout\n",
phba->brd_no); phba->brd_no);
...@@ -2203,8 +2180,6 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2203,8 +2180,6 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
phba->link_state = LPFC_CLEAR_LA; phba->link_state = LPFC_CLEAR_LA;
lpfc_clear_la(phba, clearlambox); lpfc_clear_la(phba, clearlambox);
printk(KERN_ERR "%s (%d): do clear_la\n",
__FUNCTION__, __LINE__);
clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la; clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
clearlambox->vport = vport; clearlambox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, clearlambox, rc = lpfc_sli_issue_mbox(phba, clearlambox,
...@@ -2230,6 +2205,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2230,6 +2205,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
lpfc_init_link(phba, initlinkmbox, phba->cfg_topology, lpfc_init_link(phba, initlinkmbox, phba->cfg_topology,
phba->cfg_link_speed); phba->cfg_link_speed);
initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0; initlinkmbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
initlinkmbox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, initlinkmbox, rc = lpfc_sli_issue_mbox(phba, initlinkmbox,
(MBX_NOWAIT | MBX_STOP_IOCB)); (MBX_NOWAIT | MBX_STOP_IOCB));
lpfc_set_loopback_flag(phba); lpfc_set_loopback_flag(phba);
...@@ -2240,9 +2216,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2240,9 +2216,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
case LPFC_DISC_AUTH: case LPFC_DISC_AUTH:
/* Node Authentication timeout */ /* Node Authentication timeout */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
KERN_ERR,
LOG_DISCOVERY,
"%d:0227 Node Authentication timeout\n", "%d:0227 Node Authentication timeout\n",
phba->brd_no); phba->brd_no);
lpfc_disc_flush_list(vport); lpfc_disc_flush_list(vport);
...@@ -2259,8 +2233,6 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2259,8 +2233,6 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
} }
phba->link_state = LPFC_CLEAR_LA; phba->link_state = LPFC_CLEAR_LA;
lpfc_clear_la(phba, clearlambox); lpfc_clear_la(phba, clearlambox);
printk(KERN_ERR "%s (%d): do clear_la\n",
__FUNCTION__, __LINE__);
clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la; clearlambox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
clearlambox->vport = vport; clearlambox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, clearlambox, rc = lpfc_sli_issue_mbox(phba, clearlambox,
...@@ -2273,9 +2245,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2273,9 +2245,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
case LPFC_VPORT_READY: case LPFC_VPORT_READY:
if (vport->fc_flag & FC_RSCN_MODE) { if (vport->fc_flag & FC_RSCN_MODE) {
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
KERN_ERR,
LOG_DISCOVERY,
"%d:0231 RSCN timeout Data: x%x x%x\n", "%d:0231 RSCN timeout Data: x%x x%x\n",
phba->brd_no, phba->brd_no,
vport->fc_ns_retry, LPFC_MAX_NS_RETRY); vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
...@@ -2291,13 +2261,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2291,13 +2261,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
case LPFC_STATE_UNKNOWN: case LPFC_STATE_UNKNOWN:
case LPFC_NS_REG: case LPFC_NS_REG:
case LPFC_BUILD_DISC_LIST: case LPFC_BUILD_DISC_LIST:
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
KERN_ERR,
LOG_DISCOVERY,
"%d:0229 Unexpected discovery timeout, vport " "%d:0229 Unexpected discovery timeout, vport "
"State x%x\n", "State x%x\n",
vport->port_state, vport->port_state, phba->brd_no);
phba->brd_no);
break; break;
} }
...@@ -2305,9 +2272,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2305,9 +2272,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
switch (phba->link_state) { switch (phba->link_state) {
case LPFC_CLEAR_LA: case LPFC_CLEAR_LA:
/* CLEAR LA timeout */ /* CLEAR LA timeout */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
KERN_ERR,
LOG_DISCOVERY,
"%d:0228 CLEAR LA timeout\n", "%d:0228 CLEAR LA timeout\n",
phba->brd_no); phba->brd_no);
clrlaerr = 1; clrlaerr = 1;
...@@ -2320,9 +2285,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2320,9 +2285,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
case LPFC_LINK_DOWN: case LPFC_LINK_DOWN:
case LPFC_LINK_UP: case LPFC_LINK_UP:
case LPFC_HBA_ERROR: case LPFC_HBA_ERROR:
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
KERN_ERR,
LOG_DISCOVERY,
"%d:0230 Unexpected timeout, hba link " "%d:0230 Unexpected timeout, hba link "
"state x%x\n", "state x%x\n",
phba->brd_no, phba->link_state); phba->brd_no, phba->link_state);
...@@ -2335,8 +2298,6 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) ...@@ -2335,8 +2298,6 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
psli->ring[(psli->fcp_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; 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; vport->port_state = LPFC_VPORT_READY;
} }
......
...@@ -59,6 +59,11 @@ ...@@ -59,6 +59,11 @@
#define SLI2_IOCB_CMD_R3XTRA_ENTRIES 24 #define SLI2_IOCB_CMD_R3XTRA_ENTRIES 24
#define SLI2_IOCB_RSP_R3XTRA_ENTRIES 32 #define SLI2_IOCB_RSP_R3XTRA_ENTRIES 32
#define SLI2_IOCB_CMD_SIZE 32
#define SLI2_IOCB_RSP_SIZE 32
#define SLI3_IOCB_CMD_SIZE 128
#define SLI3_IOCB_RSP_SIZE 64
/* Common Transport structures and definitions */ /* Common Transport structures and definitions */
union CtRevisionId { union CtRevisionId {
...@@ -1255,6 +1260,7 @@ typedef struct { /* FireFly BIU registers */ ...@@ -1255,6 +1260,7 @@ typedef struct { /* FireFly BIU registers */
#define MBX_CONFIG_FARP 0x25 #define MBX_CONFIG_FARP 0x25
#define MBX_BEACON 0x2A #define MBX_BEACON 0x2A
#define MBX_CONFIG_HBQ 0x7C
#define MBX_LOAD_AREA 0x81 #define MBX_LOAD_AREA 0x81
#define MBX_RUN_BIU_DIAG64 0x84 #define MBX_RUN_BIU_DIAG64 0x84
#define MBX_CONFIG_PORT 0x88 #define MBX_CONFIG_PORT 0x88
...@@ -1334,6 +1340,10 @@ typedef struct { /* FireFly BIU registers */ ...@@ -1334,6 +1340,10 @@ typedef struct { /* FireFly BIU registers */
#define CMD_FCP_TRECEIVE64_CX 0xA1 #define CMD_FCP_TRECEIVE64_CX 0xA1
#define CMD_FCP_TRSP64_CX 0xA3 #define CMD_FCP_TRSP64_CX 0xA3
#define CMD_IOCB_RCV_SEQ64_CX 0xB5
#define CMD_IOCB_RCV_ELS64_CX 0xB7
#define CMD_IOCB_RCV_CONT64_CX 0xBB
#define CMD_GEN_REQUEST64_CR 0xC2 #define CMD_GEN_REQUEST64_CR 0xC2
#define CMD_GEN_REQUEST64_CX 0xC3 #define CMD_GEN_REQUEST64_CX 0xC3
...@@ -1560,6 +1570,7 @@ typedef struct { ...@@ -1560,6 +1570,7 @@ typedef struct {
#define FLAGS_TOPOLOGY_MODE_PT_PT 0x02 /* Attempt pt-pt only */ #define FLAGS_TOPOLOGY_MODE_PT_PT 0x02 /* Attempt pt-pt only */
#define FLAGS_TOPOLOGY_MODE_LOOP 0x04 /* Attempt loop only */ #define FLAGS_TOPOLOGY_MODE_LOOP 0x04 /* Attempt loop only */
#define FLAGS_TOPOLOGY_MODE_PT_LOOP 0x06 /* Attempt pt-pt then loop */ #define FLAGS_TOPOLOGY_MODE_PT_LOOP 0x06 /* Attempt pt-pt then loop */
#define FLAGS_UNREG_LOGIN_ALL 0x08 /* UNREG_LOGIN all on link down */
#define FLAGS_LIRP_LILP 0x80 /* LIRP / LILP is disabled */ #define FLAGS_LIRP_LILP 0x80 /* LIRP / LILP is disabled */
#define FLAGS_TOPOLOGY_FAILOVER 0x0400 /* Bit 10 */ #define FLAGS_TOPOLOGY_FAILOVER 0x0400 /* Bit 10 */
...@@ -1817,6 +1828,13 @@ typedef struct { ...@@ -1817,6 +1828,13 @@ typedef struct {
structure */ structure */
struct ulp_bde64 sp64; struct ulp_bde64 sp64;
} un; } un;
#ifdef __BIG_ENDIAN_BITFIELD
uint16_t rsvd3;
uint16_t vpi;
#else /* __LITTLE_ENDIAN_BITFIELD */
uint16_t vpi;
uint16_t rsvd3;
#endif
} READ_SPARM_VAR; } READ_SPARM_VAR;
/* Structure for MB Command READ_STATUS (14) */ /* Structure for MB Command READ_STATUS (14) */
...@@ -1917,11 +1935,17 @@ typedef struct { ...@@ -1917,11 +1935,17 @@ typedef struct {
#ifdef __BIG_ENDIAN_BITFIELD #ifdef __BIG_ENDIAN_BITFIELD
uint32_t cv:1; uint32_t cv:1;
uint32_t rr:1; uint32_t rr:1;
uint32_t rsvd1:29; uint32_t rsvd2:2;
uint32_t v3req:1;
uint32_t v3rsp:1;
uint32_t rsvd1:25;
uint32_t rv:1; uint32_t rv:1;
#else /* __LITTLE_ENDIAN_BITFIELD */ #else /* __LITTLE_ENDIAN_BITFIELD */
uint32_t rv:1; uint32_t rv:1;
uint32_t rsvd1:29; uint32_t rsvd1:25;
uint32_t v3rsp:1;
uint32_t v3req:1;
uint32_t rsvd2:2;
uint32_t rr:1; uint32_t rr:1;
uint32_t cv:1; uint32_t cv:1;
#endif #endif
...@@ -1971,8 +1995,8 @@ typedef struct { ...@@ -1971,8 +1995,8 @@ typedef struct {
uint8_t sli1FwName[16]; uint8_t sli1FwName[16];
uint32_t sli2FwRev; uint32_t sli2FwRev;
uint8_t sli2FwName[16]; uint8_t sli2FwName[16];
uint32_t rsvd2; uint32_t sli3Feat;
uint32_t RandomData[7]; uint32_t RandomData[6];
} READ_REV_VAR; } READ_REV_VAR;
/* Structure for MB Command READ_LINK_STAT (18) */ /* Structure for MB Command READ_LINK_STAT (18) */
...@@ -2012,6 +2036,14 @@ typedef struct { ...@@ -2012,6 +2036,14 @@ typedef struct {
struct ulp_bde64 sp64; struct ulp_bde64 sp64;
} un; } un;
#ifdef __BIG_ENDIAN_BITFIELD
uint16_t rsvd6;
uint16_t vpi;
#else /* __LITTLE_ENDIAN_BITFIELD */
uint16_t vpi;
uint16_t rsvd6;
#endif
} REG_LOGIN_VAR; } REG_LOGIN_VAR;
/* Word 30 contents for REG_LOGIN */ /* Word 30 contents for REG_LOGIN */
...@@ -2036,9 +2068,21 @@ typedef struct { ...@@ -2036,9 +2068,21 @@ typedef struct {
#ifdef __BIG_ENDIAN_BITFIELD #ifdef __BIG_ENDIAN_BITFIELD
uint16_t rsvd1; uint16_t rsvd1;
uint16_t rpi; uint16_t rpi;
uint32_t rsvd2;
uint32_t rsvd3;
uint32_t rsvd4;
uint32_t rsvd5;
uint16_t rsvd6;
uint16_t vpi;
#else /* __LITTLE_ENDIAN_BITFIELD */ #else /* __LITTLE_ENDIAN_BITFIELD */
uint16_t rpi; uint16_t rpi;
uint16_t rsvd1; uint16_t rsvd1;
uint32_t rsvd2;
uint32_t rsvd3;
uint32_t rsvd4;
uint32_t rsvd5;
uint16_t vpi;
uint16_t rsvd6;
#endif #endif
} UNREG_LOGIN_VAR; } UNREG_LOGIN_VAR;
...@@ -2046,6 +2090,17 @@ typedef struct { ...@@ -2046,6 +2090,17 @@ typedef struct {
typedef struct { typedef struct {
uint32_t did; uint32_t did;
uint32_t rsvd2;
uint32_t rsvd3;
uint32_t rsvd4;
uint32_t rsvd5;
#ifdef __BIG_ENDIAN_BITFIELD
uint16_t rsvd6;
uint16_t vpi;
#else
uint16_t vpi;
uint16_t rsvd6;
#endif
} UNREG_D_ID_VAR; } UNREG_D_ID_VAR;
/* Structure for MB Command READ_LA (21) */ /* Structure for MB Command READ_LA (21) */
...@@ -2177,13 +2232,240 @@ typedef struct { ...@@ -2177,13 +2232,240 @@ typedef struct {
#define DMP_RSP_OFFSET 0x14 /* word 5 contains first word of rsp */ #define DMP_RSP_OFFSET 0x14 /* word 5 contains first word of rsp */
#define DMP_RSP_SIZE 0x6C /* maximum of 27 words of rsp data */ #define DMP_RSP_SIZE 0x6C /* maximum of 27 words of rsp data */
struct hbq_mask {
#ifdef __BIG_ENDIAN_BITFIELD
uint8_t tmatch;
uint8_t tmask;
uint8_t rctlmatch;
uint8_t rctlmask;
#else /* __LITTLE_ENDIAN */
uint8_t rctlmask;
uint8_t rctlmatch;
uint8_t tmask;
uint8_t tmatch;
#endif
};
/* Structure for MB Command CONFIG_HBQ (7c) */
struct config_hbq_var {
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t rsvd1 :7;
uint32_t recvNotify :1; /* Receive Notification */
uint32_t numMask :8; /* # Mask Entries */
uint32_t profile :8; /* Selection Profile */
uint32_t rsvd2 :8;
#else /* __LITTLE_ENDIAN */
uint32_t rsvd2 :8;
uint32_t profile :8; /* Selection Profile */
uint32_t numMask :8; /* # Mask Entries */
uint32_t recvNotify :1; /* Receive Notification */
uint32_t rsvd1 :7;
#endif
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t hbqId :16;
uint32_t rsvd3 :12;
uint32_t ringMask :4;
#else /* __LITTLE_ENDIAN */
uint32_t ringMask :4;
uint32_t rsvd3 :12;
uint32_t hbqId :16;
#endif
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t entry_count :16;
uint32_t rsvd4 :8;
uint32_t headerLen :8;
#else /* __LITTLE_ENDIAN */
uint32_t headerLen :8;
uint32_t rsvd4 :8;
uint32_t entry_count :16;
#endif
uint32_t hbqaddrLow;
uint32_t hbqaddrHigh;
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t rsvd5 :31;
uint32_t logEntry :1;
#else /* __LITTLE_ENDIAN */
uint32_t logEntry :1;
uint32_t rsvd5 :31;
#endif
uint32_t rsvd6; /* w7 */
uint32_t rsvd7; /* w8 */
uint32_t rsvd8; /* w9 */
struct hbq_mask hbqMasks[6];
union {
uint32_t allprofiles[12];
struct {
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t seqlenoff :16;
uint32_t maxlen :16;
#else /* __LITTLE_ENDIAN */
uint32_t maxlen :16;
uint32_t seqlenoff :16;
#endif
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t rsvd1 :28;
uint32_t seqlenbcnt :4;
#else /* __LITTLE_ENDIAN */
uint32_t seqlenbcnt :4;
uint32_t rsvd1 :28;
#endif
uint32_t rsvd[10];
} profile2;
struct {
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t seqlenoff :16;
uint32_t maxlen :16;
#else /* __LITTLE_ENDIAN */
uint32_t maxlen :16;
uint32_t seqlenoff :16;
#endif
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t cmdcodeoff :28;
uint32_t rsvd1 :12;
uint32_t seqlenbcnt :4;
#else /* __LITTLE_ENDIAN */
uint32_t seqlenbcnt :4;
uint32_t rsvd1 :12;
uint32_t cmdcodeoff :28;
#endif
uint32_t cmdmatch[8];
uint32_t rsvd[2];
} profile3;
struct {
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t seqlenoff :16;
uint32_t maxlen :16;
#else /* __LITTLE_ENDIAN */
uint32_t maxlen :16;
uint32_t seqlenoff :16;
#endif
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t cmdcodeoff :28;
uint32_t rsvd1 :12;
uint32_t seqlenbcnt :4;
#else /* __LITTLE_ENDIAN */
uint32_t seqlenbcnt :4;
uint32_t rsvd1 :12;
uint32_t cmdcodeoff :28;
#endif
uint32_t cmdmatch[8];
uint32_t rsvd[2];
} profile5;
} profiles;
};
/* Structure for MB Command CONFIG_PORT (0x88) */ /* Structure for MB Command CONFIG_PORT (0x88) */
typedef struct { typedef struct {
uint32_t pcbLen; #ifdef __BIG_ENDIAN_BITFIELD
uint32_t cBE : 1;
uint32_t cET : 1;
uint32_t cHpcb : 1;
uint32_t cMA : 1;
uint32_t sli_mode : 4;
uint32_t pcbLen : 24; /* bit 23:0 of memory based port
* config block */
#else /* __LITTLE_ENDIAN */
uint32_t pcbLen : 24; /* bit 23:0 of memory based port
* config block */
uint32_t sli_mode : 4;
uint32_t cMA : 1;
uint32_t cHpcb : 1;
uint32_t cET : 1;
uint32_t cBE : 1;
#endif
uint32_t pcbLow; /* bit 31:0 of memory based port config block */ uint32_t pcbLow; /* bit 31:0 of memory based port config block */
uint32_t pcbHigh; /* bit 63:32 of memory based port config block */ uint32_t pcbHigh; /* bit 63:32 of memory based port config block */
uint32_t hbainit[5]; uint32_t hbainit[6];
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t rsvd : 24; /* Reserved */
uint32_t cmv : 1; /* Configure Max VPIs */
uint32_t ccrp : 1; /* Config Command Ring Polling */
uint32_t csah : 1; /* Configure Synchronous Abort Handling */
uint32_t chbs : 1; /* Cofigure Host Backing store */
uint32_t cinb : 1; /* Enable Interrupt Notification Block */
uint32_t cerbm : 1; /* Configure Enhanced Receive Buf Mgmt */
uint32_t cmx : 1; /* Configure Max XRIs */
uint32_t cmr : 1; /* Configure Max RPIs */
#else /* __LITTLE_ENDIAN */
uint32_t cmr : 1; /* Configure Max RPIs */
uint32_t cmx : 1; /* Configure Max XRIs */
uint32_t cerbm : 1; /* Configure Enhanced Receive Buf Mgmt */
uint32_t cinb : 1; /* Enable Interrupt Notification Block */
uint32_t chbs : 1; /* Cofigure Host Backing store */
uint32_t csah : 1; /* Configure Synchronous Abort Handling */
uint32_t ccrp : 1; /* Config Command Ring Polling */
uint32_t cmv : 1; /* Configure Max VPIs */
uint32_t rsvd : 24; /* Reserved */
#endif
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t rsvd2 : 24; /* Reserved */
uint32_t gmv : 1; /* Grant Max VPIs */
uint32_t gcrp : 1; /* Grant Command Ring Polling */
uint32_t gsah : 1; /* Grant Synchronous Abort Handling */
uint32_t ghbs : 1; /* Grant Host Backing Store */
uint32_t ginb : 1; /* Grant Interrupt Notification Block */
uint32_t gerbm : 1; /* Grant ERBM Request */
uint32_t gmx : 1; /* Grant Max XRIs */
uint32_t gmr : 1; /* Grant Max RPIs */
#else /* __LITTLE_ENDIAN */
uint32_t gmr : 1; /* Grant Max RPIs */
uint32_t gmx : 1; /* Grant Max XRIs */
uint32_t gerbm : 1; /* Grant ERBM Request */
uint32_t ginb : 1; /* Grant Interrupt Notification Block */
uint32_t ghbs : 1; /* Grant Host Backing Store */
uint32_t gsah : 1; /* Grant Synchronous Abort Handling */
uint32_t gcrp : 1; /* Grant Command Ring Polling */
uint32_t gmv : 1; /* Grant Max VPIs */
uint32_t rsvd2 : 24; /* Reserved */
#endif
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t max_rpi : 16; /* Max RPIs Port should configure */
uint32_t max_xri : 16; /* Max XRIs Port should configure */
#else /* __LITTLE_ENDIAN */
uint32_t max_xri : 16; /* Max XRIs Port should configure */
uint32_t max_rpi : 16; /* Max RPIs Port should configure */
#endif
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t max_hbq : 16; /* Max HBQs Host expect to configure */
uint32_t rsvd3 : 16; /* Max HBQs Host expect to configure */
#else /* __LITTLE_ENDIAN */
uint32_t rsvd3 : 16; /* Max HBQs Host expect to configure */
uint32_t max_hbq : 16; /* Max HBQs Host expect to configure */
#endif
uint32_t rsvd4; /* Reserved */
#ifdef __BIG_ENDIAN_BITFIELD
uint32_t rsvd5 : 16; /* Reserved */
uint32_t max_vpi : 16; /* Max number of virt N-Ports */
#else /* __LITTLE_ENDIAN */
uint32_t max_vpi : 16; /* Max number of virt N-Ports */
uint32_t rsvd5 : 16; /* Reserved */
#endif
} CONFIG_PORT_VAR; } CONFIG_PORT_VAR;
/* SLI-2 Port Control Block */ /* SLI-2 Port Control Block */
...@@ -2261,33 +2543,38 @@ typedef struct { ...@@ -2261,33 +2543,38 @@ typedef struct {
#define MAILBOX_CMD_SIZE (MAILBOX_CMD_WSIZE * sizeof(uint32_t)) #define MAILBOX_CMD_SIZE (MAILBOX_CMD_WSIZE * sizeof(uint32_t))
typedef union { typedef union {
uint32_t varWords[MAILBOX_CMD_WSIZE - 1]; uint32_t varWords[MAILBOX_CMD_WSIZE - 1]; /* first word is type/
LOAD_SM_VAR varLdSM; /* cmd = 1 (LOAD_SM) */ * feature/max ring number
READ_NV_VAR varRDnvp; /* cmd = 2 (READ_NVPARMS) */ */
WRITE_NV_VAR varWTnvp; /* cmd = 3 (WRITE_NVPARMS) */ LOAD_SM_VAR varLdSM; /* cmd = 1 (LOAD_SM) */
READ_NV_VAR varRDnvp; /* cmd = 2 (READ_NVPARMS) */
WRITE_NV_VAR varWTnvp; /* cmd = 3 (WRITE_NVPARMS) */
BIU_DIAG_VAR varBIUdiag; /* cmd = 4 (RUN_BIU_DIAG) */ BIU_DIAG_VAR varBIUdiag; /* cmd = 4 (RUN_BIU_DIAG) */
INIT_LINK_VAR varInitLnk; /* cmd = 5 (INIT_LINK) */ INIT_LINK_VAR varInitLnk; /* cmd = 5 (INIT_LINK) */
DOWN_LINK_VAR varDwnLnk; /* cmd = 6 (DOWN_LINK) */ DOWN_LINK_VAR varDwnLnk; /* cmd = 6 (DOWN_LINK) */
CONFIG_LINK varCfgLnk; /* cmd = 7 (CONFIG_LINK) */ CONFIG_LINK varCfgLnk; /* cmd = 7 (CONFIG_LINK) */
PART_SLIM_VAR varSlim; /* cmd = 8 (PART_SLIM) */ PART_SLIM_VAR varSlim; /* cmd = 8 (PART_SLIM) */
CONFIG_RING_VAR varCfgRing; /* cmd = 9 (CONFIG_RING) */ CONFIG_RING_VAR varCfgRing; /* cmd = 9 (CONFIG_RING) */
RESET_RING_VAR varRstRing; /* cmd = 10 (RESET_RING) */ RESET_RING_VAR varRstRing; /* cmd = 10 (RESET_RING) */
READ_CONFIG_VAR varRdConfig; /* cmd = 11 (READ_CONFIG) */ READ_CONFIG_VAR varRdConfig; /* cmd = 11 (READ_CONFIG) */
READ_RCONF_VAR varRdRConfig; /* cmd = 12 (READ_RCONFIG) */ READ_RCONF_VAR varRdRConfig; /* cmd = 12 (READ_RCONFIG) */
READ_SPARM_VAR varRdSparm; /* cmd = 13 (READ_SPARM(64)) */ READ_SPARM_VAR varRdSparm; /* cmd = 13 (READ_SPARM(64)) */
READ_STATUS_VAR varRdStatus; /* cmd = 14 (READ_STATUS) */ READ_STATUS_VAR varRdStatus; /* cmd = 14 (READ_STATUS) */
READ_RPI_VAR varRdRPI; /* cmd = 15 (READ_RPI(64)) */ READ_RPI_VAR varRdRPI; /* cmd = 15 (READ_RPI(64)) */
READ_XRI_VAR varRdXRI; /* cmd = 16 (READ_XRI) */ READ_XRI_VAR varRdXRI; /* cmd = 16 (READ_XRI) */
READ_REV_VAR varRdRev; /* cmd = 17 (READ_REV) */ READ_REV_VAR varRdRev; /* cmd = 17 (READ_REV) */
READ_LNK_VAR varRdLnk; /* cmd = 18 (READ_LNK_STAT) */ READ_LNK_VAR varRdLnk; /* cmd = 18 (READ_LNK_STAT) */
REG_LOGIN_VAR varRegLogin; /* cmd = 19 (REG_LOGIN(64)) */ REG_LOGIN_VAR varRegLogin; /* cmd = 19 (REG_LOGIN(64)) */
UNREG_LOGIN_VAR varUnregLogin; /* cmd = 20 (UNREG_LOGIN) */ UNREG_LOGIN_VAR varUnregLogin; /* cmd = 20 (UNREG_LOGIN) */
READ_LA_VAR varReadLA; /* cmd = 21 (READ_LA(64)) */ READ_LA_VAR varReadLA; /* cmd = 21 (READ_LA(64)) */
CLEAR_LA_VAR varClearLA; /* cmd = 22 (CLEAR_LA) */ CLEAR_LA_VAR varClearLA; /* cmd = 22 (CLEAR_LA) */
DUMP_VAR varDmp; /* Warm Start DUMP mbx cmd */ DUMP_VAR varDmp; /* Warm Start DUMP mbx cmd */
UNREG_D_ID_VAR varUnregDID; /* cmd = 0x23 (UNREG_D_ID) */ UNREG_D_ID_VAR varUnregDID; /* cmd = 0x23 (UNREG_D_ID) */
CONFIG_FARP_VAR varCfgFarp; /* cmd = 0x25 (CONFIG_FARP) NEW_FEATURE */ CONFIG_FARP_VAR varCfgFarp; /* cmd = 0x25 (CONFIG_FARP)
CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT) */ * NEW_FEATURE
*/
struct config_hbq_var varCfgHbq;/* cmd = 0x7c (CONFIG_HBQ) */
CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT) */
} MAILVARIANTS; } MAILVARIANTS;
/* /*
...@@ -2304,16 +2591,30 @@ struct lpfc_pgp { ...@@ -2304,16 +2591,30 @@ struct lpfc_pgp {
__le32 rspPutInx; __le32 rspPutInx;
}; };
typedef struct _SLI2_DESC { struct sli2_desc {
struct lpfc_hgp host[MAX_RINGS];
uint32_t unused1[16]; uint32_t unused1[16];
struct lpfc_hgp host[MAX_RINGS];
struct lpfc_pgp port[MAX_RINGS];
};
struct sli3_desc {
struct lpfc_hgp host[MAX_RINGS];
uint32_t reserved[8];
uint32_t hbq_put[16];
};
struct sli3_pgp {
struct lpfc_pgp port[MAX_RINGS]; struct lpfc_pgp port[MAX_RINGS];
} SLI2_DESC; uint32_t hbq_get[16];
};
typedef union { typedef union {
SLI2_DESC s2; struct sli2_desc s2;
struct sli3_desc s3;
struct sli3_pgp s3_pgp;
} SLI_VAR; } SLI_VAR;
typedef struct { typedef struct {
#ifdef __BIG_ENDIAN_BITFIELD #ifdef __BIG_ENDIAN_BITFIELD
uint16_t mbxStatus; uint16_t mbxStatus;
...@@ -2617,6 +2918,23 @@ typedef struct { ...@@ -2617,6 +2918,23 @@ typedef struct {
uint32_t fcpt_Length; /* transfer ready for IWRITE */ uint32_t fcpt_Length; /* transfer ready for IWRITE */
} FCPT_FIELDS64; } FCPT_FIELDS64;
/* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7)
or CMD_IOCB_RCV_SEQ64_CX (0xB5) */
struct rcv_sli3 {
uint32_t word8Rsvd;
#ifdef __BIG_ENDIAN_BITFIELD
uint16_t vpi;
uint16_t word9Rsvd;
#else /* __LITTLE_ENDIAN */
uint16_t word9Rsvd;
uint16_t vpi;
#endif
uint32_t word10Rsvd;
uint32_t acc_len; /* accumulated length */
struct ulp_bde64 bde2;
};
typedef struct _IOCB { /* IOCB structure */ typedef struct _IOCB { /* IOCB structure */
union { union {
GENERIC_RSP grsp; /* Generic response */ GENERIC_RSP grsp; /* Generic response */
...@@ -2631,8 +2949,8 @@ typedef struct _IOCB { /* IOCB structure */ ...@@ -2631,8 +2949,8 @@ typedef struct _IOCB { /* IOCB structure */
/* SLI-2 structures */ /* SLI-2 structures */
struct ulp_bde64 cont64[2]; /* up to 2 64 bit continuation struct ulp_bde64 cont64[2]; /* up to 2 64 bit continuation
bde_64s */ * bde_64s */
ELS_REQUEST64 elsreq64; /* ELS_REQUEST template */ ELS_REQUEST64 elsreq64; /* ELS_REQUEST template */
GEN_REQUEST64 genreq64; /* GEN_REQUEST template */ GEN_REQUEST64 genreq64; /* GEN_REQUEST template */
RCV_ELS_REQ64 rcvels64; /* RCV_ELS_REQ template */ RCV_ELS_REQ64 rcvels64; /* RCV_ELS_REQ template */
...@@ -2693,7 +3011,16 @@ typedef struct _IOCB { /* IOCB structure */ ...@@ -2693,7 +3011,16 @@ typedef struct _IOCB { /* IOCB structure */
uint32_t ulpXS:1; uint32_t ulpXS:1;
uint32_t ulpTimeout:8; uint32_t ulpTimeout:8;
#endif #endif
union {
struct rcv_sli3 rcvsli3; /* words 8 - 15 */
uint32_t sli3Words[24]; /* 96 extra bytes for SLI-3 */
} unsli3;
#define ulpCt_h ulpXS
#define ulpCt_l ulpFCP2Rcvy
#define IOCB_FCP 1 /* IOCB is used for FCP ELS cmds-ulpRsvByte */
#define IOCB_IP 2 /* IOCB is used for IP ELS cmds */
#define PARM_UNUSED 0 /* PU field (Word 4) not used */ #define PARM_UNUSED 0 /* PU field (Word 4) not used */
#define PARM_REL_OFF 1 /* PU field (Word 4) = R. O. */ #define PARM_REL_OFF 1 /* PU field (Word 4) = R. O. */
#define PARM_READ_CHECK 2 /* PU field (Word 4) = Data Transfer Length */ #define PARM_READ_CHECK 2 /* PU field (Word 4) = Data Transfer Length */
...@@ -2724,21 +3051,33 @@ typedef struct _IOCB { /* IOCB structure */ ...@@ -2724,21 +3051,33 @@ typedef struct _IOCB { /* IOCB structure */
} IOCB_t; } IOCB_t;
/* Structure used for a single HBQ entry */
struct lpfc_hbq_entry {
struct ulp_bde64 bde;
uint32_t buffer_tag;
};
#define SLI1_SLIM_SIZE (4 * 1024) #define SLI1_SLIM_SIZE (4 * 1024)
/* Up to 498 IOCBs will fit into 16k /* Up to 498 IOCBs will fit into 16k
* 256 (MAILBOX_t) + 140 (PCB_t) + ( 32 (IOCB_t) * 498 ) = < 16384 * 256 (MAILBOX_t) + 140 (PCB_t) + ( 32 (IOCB_t) * 498 ) = < 16384
*/ */
#define SLI2_SLIM_SIZE (16 * 1024) #define SLI2_SLIM_SIZE (64 * 1024)
/* Maximum IOCBs that will fit in SLI2 slim */ /* Maximum IOCBs that will fit in SLI2 slim */
#define MAX_SLI2_IOCB 498 #define MAX_SLI2_IOCB 498
#define MAX_SLIM_IOCB_SIZE (SLI2_SLIM_SIZE - \
(sizeof(MAILBOX_t) + sizeof(PCB_t)))
/* HBQ entries are 4 words each = 4k */
#define LPFC_TOTAL_HBQ_SIZE (sizeof(struct lpfc_hbq_entry) * \
lpfc_sli_hbq_count())
struct lpfc_sli2_slim { struct lpfc_sli2_slim {
MAILBOX_t mbx; MAILBOX_t mbx;
PCB_t pcb; PCB_t pcb;
IOCB_t IOCBs[MAX_SLI2_IOCB]; IOCB_t IOCBs[MAX_SLIM_IOCB_SIZE];
}; };
/* /*
......
...@@ -49,6 +49,12 @@ static int lpfc_post_rcv_buf(struct lpfc_hba *); ...@@ -49,6 +49,12 @@ static int lpfc_post_rcv_buf(struct lpfc_hba *);
static struct scsi_transport_template *lpfc_transport_template = NULL; static struct scsi_transport_template *lpfc_transport_template = NULL;
static DEFINE_IDR(lpfc_hba_index); static DEFINE_IDR(lpfc_hba_index);
int lpfc_sli_mode = 0;
module_param(lpfc_sli_mode, int, 0);
MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"
" 0 - auto (SLI-3 if supported),"
" 2 - select SLI-2 even on SLI-3 capable HBAs,"
" 3 - select SLI-3");
/************************************************************************/ /************************************************************************/
...@@ -102,9 +108,7 @@ lpfc_config_port_prep(struct lpfc_hba *phba) ...@@ -102,9 +108,7 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) { if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
KERN_ERR,
LOG_MBOX,
"%d:0324 Config Port initialization " "%d:0324 Config Port initialization "
"error, mbxCmd x%x READ_NVPARM, " "error, mbxCmd x%x READ_NVPARM, "
"mbxStatus x%x\n", "mbxStatus x%x\n",
...@@ -123,9 +127,7 @@ lpfc_config_port_prep(struct lpfc_hba *phba) ...@@ -123,9 +127,7 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
lpfc_read_rev(phba, pmb); lpfc_read_rev(phba, pmb);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) { if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
KERN_ERR,
LOG_INIT,
"%d:0439 Adapter failed to init, mbxCmd x%x " "%d:0439 Adapter failed to init, mbxCmd x%x "
"READ_REV, mbxStatus x%x\n", "READ_REV, mbxStatus x%x\n",
phba->brd_no, phba->brd_no,
...@@ -148,6 +150,9 @@ lpfc_config_port_prep(struct lpfc_hba *phba) ...@@ -148,6 +150,9 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
return -ERESTART; return -ERESTART;
} }
if (phba->sli_rev == 3 && !mb->un.varRdRev.v3rsp)
return -EINVAL;
/* Save information as VPD data */ /* Save information as VPD data */
vp->rev.rBit = 1; vp->rev.rBit = 1;
vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev; vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
...@@ -236,10 +241,9 @@ lpfc_config_port_post(struct lpfc_hba *phba) ...@@ -236,10 +241,9 @@ lpfc_config_port_post(struct lpfc_hba *phba)
/* Get login parameters for NID. */ /* Get login parameters for NID. */
lpfc_read_sparam(phba, pmb); lpfc_read_sparam(phba, pmb);
pmb->vport = vport;
if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
KERN_ERR,
LOG_INIT,
"%d:0448 Adapter failed init, mbxCmd x%x " "%d:0448 Adapter failed init, mbxCmd x%x "
"READ_SPARM mbxStatus x%x\n", "READ_SPARM mbxStatus x%x\n",
phba->brd_no, phba->brd_no,
...@@ -296,10 +300,9 @@ lpfc_config_port_post(struct lpfc_hba *phba) ...@@ -296,10 +300,9 @@ lpfc_config_port_post(struct lpfc_hba *phba)
} }
lpfc_read_config(phba, pmb); lpfc_read_config(phba, pmb);
pmb->vport = vport;
if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
KERN_ERR,
LOG_INIT,
"%d:0453 Adapter failed to init, mbxCmd x%x " "%d:0453 Adapter failed to init, mbxCmd x%x "
"READ_CONFIG, mbxStatus x%x\n", "READ_CONFIG, mbxStatus x%x\n",
phba->brd_no, phba->brd_no,
...@@ -331,9 +334,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) ...@@ -331,9 +334,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
|| ((phba->cfg_link_speed == LINK_SPEED_10G) || ((phba->cfg_link_speed == LINK_SPEED_10G)
&& !(phba->lmt & LMT_10Gb))) { && !(phba->lmt & LMT_10Gb))) {
/* Reset link speed to auto */ /* Reset link speed to auto */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT,
KERN_WARNING,
LOG_LINK_EVENT,
"%d:1302 Invalid speed for this board: " "%d:1302 Invalid speed for this board: "
"Reset link speed to auto: x%x\n", "Reset link speed to auto: x%x\n",
phba->brd_no, phba->brd_no,
...@@ -352,7 +353,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) ...@@ -352,7 +353,8 @@ lpfc_config_port_post(struct lpfc_hba *phba)
psli->ring[psli->next_ring].flag |= LPFC_STOP_IOCB_EVENT; psli->ring[psli->next_ring].flag |= LPFC_STOP_IOCB_EVENT;
/* Post receive buffers for desired rings */ /* Post receive buffers for desired rings */
lpfc_post_rcv_buf(phba); if (phba->sli_rev != 3)
lpfc_post_rcv_buf(phba);
/* Enable appropriate host interrupts */ /* Enable appropriate host interrupts */
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
...@@ -383,12 +385,11 @@ lpfc_config_port_post(struct lpfc_hba *phba) ...@@ -383,12 +385,11 @@ lpfc_config_port_post(struct lpfc_hba *phba)
lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
pmb->vport = vport;
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
lpfc_set_loopback_flag(phba); lpfc_set_loopback_flag(phba);
if (rc != MBX_SUCCESS) { if (rc != MBX_SUCCESS) {
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
KERN_ERR,
LOG_INIT,
"%d:0454 Adapter failed to init, mbxCmd x%x " "%d:0454 Adapter failed to init, mbxCmd x%x "
"INIT_LINK, mbxStatus x%x\n", "INIT_LINK, mbxStatus x%x\n",
phba->brd_no, phba->brd_no,
...@@ -630,9 +631,7 @@ lpfc_handle_latt(struct lpfc_hba *phba) ...@@ -630,9 +631,7 @@ lpfc_handle_latt(struct lpfc_hba *phba)
/* The other case is an error from issue_mbox */ /* The other case is an error from issue_mbox */
if (rc == -ENOMEM) if (rc == -ENOMEM)
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
KERN_WARNING,
LOG_MBOX,
"%d:0300 READ_LA: no buffers\n", "%d:0300 READ_LA: no buffers\n",
phba->brd_no); phba->brd_no);
...@@ -658,9 +657,7 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len) ...@@ -658,9 +657,7 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
return 0; return 0;
/* Vital Product */ /* Vital Product */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
KERN_INFO,
LOG_INIT,
"%d:0455 Vital Product Data: x%x x%x x%x x%x\n", "%d:0455 Vital Product Data: x%x x%x x%x x%x\n",
phba->brd_no, phba->brd_no,
(uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2], (uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2],
...@@ -1221,9 +1218,7 @@ lpfc_online(struct lpfc_hba *phba) ...@@ -1221,9 +1218,7 @@ lpfc_online(struct lpfc_hba *phba)
if (!(vport->fc_flag & FC_OFFLINE_MODE)) if (!(vport->fc_flag & FC_OFFLINE_MODE))
return 0; return 0;
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
KERN_WARNING,
LOG_INIT,
"%d:0458 Bring Adapter online\n", "%d:0458 Bring Adapter online\n",
phba->brd_no); phba->brd_no);
...@@ -1633,13 +1628,22 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) ...@@ -1633,13 +1628,22 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
memset(phba->slim2p, 0, SLI2_SLIM_SIZE); memset(phba->slim2p, 0, SLI2_SLIM_SIZE);
phba->hbqslimp.virt = dma_alloc_coherent(&phba->pcidev->dev,
lpfc_sli_hbq_size(),
&phba->hbqslimp.phys,
GFP_KERNEL);
if (!phba->hbqslimp.virt)
goto out_free_slim;
memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size());
/* Initialize the SLI Layer to run with lpfc HBAs. */ /* Initialize the SLI Layer to run with lpfc HBAs. */
lpfc_sli_setup(phba); lpfc_sli_setup(phba);
lpfc_sli_queue_setup(phba); lpfc_sli_queue_setup(phba);
error = lpfc_mem_alloc(phba); error = lpfc_mem_alloc(phba);
if (error) if (error)
goto out_free_slim; goto out_free_hbqslimp;
/* Initialize and populate the iocb list per host. */ /* Initialize and populate the iocb list per host. */
INIT_LIST_HEAD(&phba->lpfc_iocb_list); INIT_LIST_HEAD(&phba->lpfc_iocb_list);
...@@ -1753,6 +1757,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) ...@@ -1753,6 +1757,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
phba->total_iocbq_bufs--; phba->total_iocbq_bufs--;
} }
lpfc_mem_free(phba); lpfc_mem_free(phba);
out_free_hbqslimp:
dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
phba->hbqslimp.phys);
out_free_slim: out_free_slim:
dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, phba->slim2p, dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, phba->slim2p,
phba->slim2p_mapping); phba->slim2p_mapping);
...@@ -1811,6 +1818,9 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -1811,6 +1818,9 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
lpfc_scsi_free(phba); lpfc_scsi_free(phba);
lpfc_mem_free(phba); lpfc_mem_free(phba);
dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
phba->hbqslimp.phys);
/* Free resources associated with SLI2 interface */ /* Free resources associated with SLI2 interface */
dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
phba->slim2p, phba->slim2p_mapping); phba->slim2p, phba->slim2p_mapping);
......
...@@ -232,6 +232,7 @@ lpfc_init_link(struct lpfc_hba * phba, ...@@ -232,6 +232,7 @@ lpfc_init_link(struct lpfc_hba * phba,
mb->mbxCommand = (volatile uint8_t)MBX_INIT_LINK; mb->mbxCommand = (volatile uint8_t)MBX_INIT_LINK;
mb->mbxOwner = OWN_HOST; mb->mbxOwner = OWN_HOST;
mb->un.varInitLnk.fabric_AL_PA = phba->fc_pref_ALPA; mb->un.varInitLnk.fabric_AL_PA = phba->fc_pref_ALPA;
mb->un.varInitLnk.link_flags |= FLAGS_UNREG_LOGIN_ALL;
return; return;
} }
...@@ -418,6 +419,10 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba) ...@@ -418,6 +419,10 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
for (i = 0; i < psli->num_rings; i++) { for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i]; pring = &psli->ring[i];
pring->sizeCiocb = phba->sli_rev == 3 ? SLI3_IOCB_CMD_SIZE:
SLI2_IOCB_CMD_SIZE;
pring->sizeRiocb = phba->sli_rev == 3 ? SLI3_IOCB_RSP_SIZE:
SLI2_IOCB_RSP_SIZE;
/* A ring MUST have both cmd and rsp entries defined to be /* A ring MUST have both cmd and rsp entries defined to be
valid */ valid */
if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) { if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) {
...@@ -432,8 +437,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba) ...@@ -432,8 +437,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
continue; continue;
} }
/* Command ring setup for ring */ /* Command ring setup for ring */
pring->cmdringaddr = pring->cmdringaddr = (void *)&phba->slim2p->IOCBs[iocbCnt];
(void *)&phba->slim2p->IOCBs[iocbCnt];
pcbp->rdsc[i].cmdEntries = pring->numCiocb; pcbp->rdsc[i].cmdEntries = pring->numCiocb;
offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] - offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
...@@ -444,8 +448,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba) ...@@ -444,8 +448,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
iocbCnt += pring->numCiocb; iocbCnt += pring->numCiocb;
/* Response ring setup for ring */ /* Response ring setup for ring */
pring->rspringaddr = pring->rspringaddr = (void *)&phba->slim2p->IOCBs[iocbCnt];
(void *)&phba->slim2p->IOCBs[iocbCnt];
pcbp->rdsc[i].rspEntries = pring->numRiocb; pcbp->rdsc[i].rspEntries = pring->numRiocb;
offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] - offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
...@@ -463,11 +466,103 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -463,11 +466,103 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
MAILBOX_t *mb = &pmb->mb; MAILBOX_t *mb = &pmb->mb;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
mb->un.varRdRev.cv = 1; mb->un.varRdRev.cv = 1;
mb->un.varRdRev.v3req = 1; /* Request SLI3 info */
mb->mbxCommand = MBX_READ_REV; mb->mbxCommand = MBX_READ_REV;
mb->mbxOwner = OWN_HOST; mb->mbxOwner = OWN_HOST;
return; return;
} }
static void
lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
struct lpfc_hbq_init *hbq_desc)
{
hbqmb->profiles.profile2.seqlenbcnt = hbq_desc->seqlenbcnt;
hbqmb->profiles.profile2.maxlen = hbq_desc->maxlen;
hbqmb->profiles.profile2.seqlenoff = hbq_desc->seqlenoff;
}
static void
lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
struct lpfc_hbq_init *hbq_desc)
{
hbqmb->profiles.profile3.seqlenbcnt = hbq_desc->seqlenbcnt;
hbqmb->profiles.profile3.maxlen = hbq_desc->maxlen;
hbqmb->profiles.profile3.cmdcodeoff = hbq_desc->cmdcodeoff;
hbqmb->profiles.profile3.seqlenoff = hbq_desc->seqlenoff;
memcpy(&hbqmb->profiles.profile3.cmdmatch, hbq_desc->cmdmatch,
sizeof(hbqmb->profiles.profile3.cmdmatch));
}
static void
lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
struct lpfc_hbq_init *hbq_desc)
{
hbqmb->profiles.profile5.seqlenbcnt = hbq_desc->seqlenbcnt;
hbqmb->profiles.profile5.maxlen = hbq_desc->maxlen;
hbqmb->profiles.profile5.cmdcodeoff = hbq_desc->cmdcodeoff;
hbqmb->profiles.profile5.seqlenoff = hbq_desc->seqlenoff;
memcpy(&hbqmb->profiles.profile5.cmdmatch, hbq_desc->cmdmatch,
sizeof(hbqmb->profiles.profile5.cmdmatch));
}
void
lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc,
uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb)
{
int i;
MAILBOX_t *mb = &pmb->mb;
struct config_hbq_var *hbqmb = &mb->un.varCfgHbq;
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
hbqmb->entry_count = hbq_desc->entry_count; /* # entries in HBQ */
hbqmb->recvNotify = hbq_desc->rn; /* Receive
* Notification */
hbqmb->numMask = hbq_desc->mask_count; /* # R_CTL/TYPE masks
* # in words 0-19 */
hbqmb->profile = hbq_desc->profile; /* Selection profile:
* 0 = all,
* 7 = logentry */
hbqmb->ringMask = hbq_desc->ring_mask; /* Binds HBQ to a ring
* e.g. Ring0=b0001,
* ring2=b0100 */
hbqmb->headerLen = hbq_desc->headerLen; /* 0 if not profile 4
* or 5 */
hbqmb->logEntry = hbq_desc->logEntry; /* Set to 1 if this
* HBQ will be used
* for LogEntry
* buffers */
hbqmb->hbqaddrLow = putPaddrLow(phba->hbqslimp.phys) +
hbq_entry_index * sizeof(struct lpfc_hbq_entry);
hbqmb->hbqaddrHigh = putPaddrHigh(phba->hbqslimp.phys);
mb->mbxCommand = MBX_CONFIG_HBQ;
mb->mbxOwner = OWN_HOST;
/* Copy info for profiles 2,3,5. Other
* profiles this area is reserved
*/
if (hbq_desc->profile == 2)
lpfc_build_hbq_profile2(hbqmb, hbq_desc);
else if (hbq_desc->profile == 3)
lpfc_build_hbq_profile3(hbqmb, hbq_desc);
else if (hbq_desc->profile == 5)
lpfc_build_hbq_profile5(hbqmb, hbq_desc);
/* Return if no rctl / type masks for this HBQ */
if (!hbq_desc->mask_count)
return;
/* Otherwise we setup specific rctl / type masks for this HBQ */
for (i = 0; i < hbq_desc->mask_count; i++) {
hbqmb->hbqMasks[i].tmatch = hbq_desc->hbqMasks[i].tmatch;
hbqmb->hbqMasks[i].tmask = hbq_desc->hbqMasks[i].tmask;
hbqmb->hbqMasks[i].rctlmatch = hbq_desc->hbqMasks[i].rctlmatch;
hbqmb->hbqMasks[i].rctlmask = hbq_desc->hbqMasks[i].rctlmask;
}
return;
}
void void
lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
{ {
...@@ -512,13 +607,14 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) ...@@ -512,13 +607,14 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
void void
lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{ {
MAILBOX_t __iomem *mb_slim = (MAILBOX_t __iomem *) phba->MBslimaddr;
MAILBOX_t *mb = &pmb->mb; MAILBOX_t *mb = &pmb->mb;
dma_addr_t pdma_addr; dma_addr_t pdma_addr;
uint32_t bar_low, bar_high; uint32_t bar_low, bar_high;
size_t offset; size_t offset;
struct lpfc_hgp hgp; struct lpfc_hgp hgp;
void __iomem *to_slim;
int i; int i;
uint32_t pgp_offset;
memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
mb->mbxCommand = MBX_CONFIG_PORT; mb->mbxCommand = MBX_CONFIG_PORT;
...@@ -531,12 +627,21 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -531,12 +627,21 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr); mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr); mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
/* If HBA supports SLI=3 ask for it */
mb->un.varCfgPort.sli_mode = phba->sli_rev;
if (phba->sli_rev == 3) {
mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */
}
/* Now setup pcb */ /* Now setup pcb */
phba->slim2p->pcb.type = TYPE_NATIVE_SLI2; phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2; phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
/* Setup Mailbox pointers */ /* Setup Mailbox pointers */
phba->slim2p->pcb.mailBoxSize = sizeof(MAILBOX_t); phba->slim2p->pcb.mailBoxSize = offsetof(MAILBOX_t, us) +
sizeof(struct sli2_desc);
offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p; offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
pdma_addr = phba->slim2p_mapping + offset; pdma_addr = phba->slim2p_mapping + offset;
phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr); phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
...@@ -564,29 +669,70 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -564,29 +669,70 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low); pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low);
pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high); pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high);
/*
* Set up HGP - Port Memory
*
* The port expects the host get/put pointers to reside in memory
* following the "non-diagnostic" mode mailbox (32 words, 0x80 bytes)
* area of SLIM. In SLI-2 mode, there's an additional 16 reserved
* words (0x40 bytes). This area is not reserved if HBQs are
* configured in SLI-3.
*
* CR0Put - SLI2(no HBQs) = 0xc0, With HBQs = 0x80
* RR0Get 0xc4 0x84
* CR1Put 0xc8 0x88
* RR1Get 0xcc 0x8c
* CR2Put 0xd0 0x90
* RR2Get 0xd4 0x94
* CR3Put 0xd8 0x98
* RR3Get 0xdc 0x9c
*
* Reserved 0xa0-0xbf
* If HBQs configured:
* HBQ 0 Put ptr 0xc0
* HBQ 1 Put ptr 0xc4
* HBQ 2 Put ptr 0xc8
* ......
* HBQ(M-1)Put Pointer 0xc0+(M-1)*4
*
*/
if (phba->sli_rev == 3) {
phba->host_gp = &mb_slim->us.s3.host[0];
phba->hbq_put = &mb_slim->us.s3.hbq_put[0];
} else {
phba->host_gp = &mb_slim->us.s2.host[0];
phba->hbq_put = NULL;
}
/* mask off BAR0's flag bits 0 - 3 */ /* mask off BAR0's flag bits 0 - 3 */
phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) + phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
(SLIMOFF*sizeof(uint32_t)); (void __iomem *) phba->host_gp -
(void __iomem *)phba->MBslimaddr;
if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64) if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
phba->slim2p->pcb.hgpAddrHigh = bar_high; phba->slim2p->pcb.hgpAddrHigh = bar_high;
else else
phba->slim2p->pcb.hgpAddrHigh = 0; phba->slim2p->pcb.hgpAddrHigh = 0;
/* write HGP data to SLIM at the required longword offset */ /* write HGP data to SLIM at the required longword offset */
memset(&hgp, 0, sizeof(struct lpfc_hgp)); memset(&hgp, 0, sizeof(struct lpfc_hgp));
to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
for (i=0; i < phba->sli.num_rings; i++) { for (i=0; i < phba->sli.num_rings; i++) {
lpfc_memcpy_to_slim(to_slim, &hgp, sizeof(struct lpfc_hgp)); lpfc_memcpy_to_slim(phba->host_gp + i, &hgp,
to_slim += sizeof (struct lpfc_hgp); sizeof(*phba->host_gp));
} }
/* Setup Port Group ring pointer */ /* Setup Port Group ring pointer */
offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port - if (phba->sli_rev == 3)
(uint8_t *)phba->slim2p; pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s3_pgp.port -
pdma_addr = phba->slim2p_mapping + offset; (uint8_t *)phba->slim2p;
else
pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
(uint8_t *)phba->slim2p;
pdma_addr = phba->slim2p_mapping + pgp_offset;
phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr); phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr); phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
phba->hbq_get = &phba->slim2p->mbx.us.s3_pgp.hbq_get[0];
/* Use callback routine to setp rings in the pcb */ /* Use callback routine to setp rings in the pcb */
lpfc_config_pcb_setup(phba); lpfc_config_pcb_setup(phba);
...@@ -603,10 +749,6 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -603,10 +749,6 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
/* Swap PCB if needed */ /* Swap PCB if needed */
lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb, lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb,
sizeof (PCB_t)); sizeof (PCB_t));
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"%d:0405 Service Level Interface (SLI) 2 selected\n",
phba->brd_no);
} }
void void
......
...@@ -82,8 +82,16 @@ lpfc_mem_alloc(struct lpfc_hba * phba) ...@@ -82,8 +82,16 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
if (!phba->nlp_mem_pool) if (!phba->nlp_mem_pool)
goto fail_free_mbox_pool; goto fail_free_mbox_pool;
phba->lpfc_hbq_pool = pci_pool_create("lpfc_hbq_pool",phba->pcidev,
LPFC_BPL_SIZE, 8, 0);
if (!phba->lpfc_hbq_pool)
goto fail_free_nlp_mem_pool;
return 0; return 0;
fail_free_nlp_mem_pool:
mempool_destroy(phba->nlp_mem_pool);
phba->nlp_mem_pool = NULL;
fail_free_mbox_pool: fail_free_mbox_pool:
mempool_destroy(phba->mbox_mem_pool); mempool_destroy(phba->mbox_mem_pool);
phba->mbox_mem_pool = NULL; phba->mbox_mem_pool = NULL;
...@@ -111,6 +119,8 @@ lpfc_mem_free(struct lpfc_hba * phba) ...@@ -111,6 +119,8 @@ lpfc_mem_free(struct lpfc_hba * phba)
struct lpfc_dmabuf *mp; struct lpfc_dmabuf *mp;
int i; int i;
lpfc_sli_hbqbuf_free_all(phba);
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) { list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
mp = (struct lpfc_dmabuf *) (mbox->context1); mp = (struct lpfc_dmabuf *) (mbox->context1);
...@@ -140,12 +150,14 @@ lpfc_mem_free(struct lpfc_hba * phba) ...@@ -140,12 +150,14 @@ lpfc_mem_free(struct lpfc_hba * phba)
pool->elements[i].phys); pool->elements[i].phys);
kfree(pool->elements); kfree(pool->elements);
pci_pool_destroy(phba->lpfc_hbq_pool);
mempool_destroy(phba->nlp_mem_pool); mempool_destroy(phba->nlp_mem_pool);
mempool_destroy(phba->mbox_mem_pool); mempool_destroy(phba->mbox_mem_pool);
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool); pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
pci_pool_destroy(phba->lpfc_mbuf_pool); pci_pool_destroy(phba->lpfc_mbuf_pool);
phba->lpfc_hbq_pool = NULL;
phba->nlp_mem_pool = NULL; phba->nlp_mem_pool = NULL;
phba->mbox_mem_pool = NULL; phba->mbox_mem_pool = NULL;
phba->lpfc_scsi_dma_buf_pool = NULL; phba->lpfc_scsi_dma_buf_pool = NULL;
...@@ -201,3 +213,20 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) ...@@ -201,3 +213,20 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
spin_unlock_irqrestore(&phba->hbalock, iflags); spin_unlock_irqrestore(&phba->hbalock, iflags);
return; return;
} }
void *
lpfc_hbq_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
{
void *ret;
ret = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_ATOMIC, handle);
return ret;
}
void
lpfc_hbq_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma)
{
pci_pool_free(phba->lpfc_hbq_pool, virt, dma);
return;
}
...@@ -255,9 +255,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -255,9 +255,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
/* Start discovery - this should just do /* Start discovery - this should just do
CLEAR_LA */ CLEAR_LA */
lpfc_disc_start(vport); lpfc_disc_start(vport);
} else { } else
lpfc_initial_flogi(vport); lpfc_initial_flogi(vport);
}
} else { } else {
stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
...@@ -279,19 +278,16 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -279,19 +278,16 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
icmd = &cmdiocb->iocb; icmd = &cmdiocb->iocb;
/* PLOGI chkparm OK */ /* PLOGI chkparm OK */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
KERN_INFO,
LOG_ELS,
"%d:0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n", "%d:0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
phba->brd_no, phba->brd_no,
ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
ndlp->nlp_rpi); ndlp->nlp_rpi);
if (phba->cfg_fcp_class == 2 && sp->cls2.classValid) { if (phba->cfg_fcp_class == 2 && sp->cls2.classValid)
ndlp->nlp_fcp_info |= CLASS2; ndlp->nlp_fcp_info |= CLASS2;
} else { else
ndlp->nlp_fcp_info |= CLASS3; ndlp->nlp_fcp_info |= CLASS3;
}
ndlp->nlp_class_sup = 0; ndlp->nlp_class_sup = 0;
if (sp->cls1.classValid) if (sp->cls1.classValid)
...@@ -327,6 +323,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -327,6 +323,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
goto out; goto out;
lpfc_config_link(phba, mbox); lpfc_config_link(phba, mbox);
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
rc = lpfc_sli_issue_mbox rc = lpfc_sli_issue_mbox
(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
if (rc == MBX_NOT_FINISHED) { if (rc == MBX_NOT_FINISHED) {
...@@ -544,9 +541,7 @@ static uint32_t ...@@ -544,9 +541,7 @@ static uint32_t
lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt) void *arg, uint32_t evt)
{ {
lpfc_printf_log(vport->phba, lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY,
KERN_ERR,
LOG_DISCOVERY,
"%d:0253 Illegal State Transition: node x%x event x%x, " "%d:0253 Illegal State Transition: node x%x event x%x, "
"state x%x Data: x%x x%x\n", "state x%x Data: x%x x%x\n",
vport->phba->brd_no, vport->phba->brd_no,
...@@ -728,9 +723,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, ...@@ -728,9 +723,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
goto out; goto out;
/* PLOGI chkparm OK */ /* PLOGI chkparm OK */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
KERN_INFO,
LOG_ELS,
"%d:0121 PLOGI chkparm OK " "%d:0121 PLOGI chkparm OK "
"Data: x%x x%x x%x x%x\n", "Data: x%x x%x x%x x%x\n",
phba->brd_no, phba->brd_no,
...@@ -1105,9 +1098,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, ...@@ -1105,9 +1098,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
if (mb->mbxStatus) { if (mb->mbxStatus) {
/* RegLogin failed */ /* RegLogin failed */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
KERN_ERR,
LOG_DISCOVERY,
"%d:0246 RegLogin failed Data: x%x x%x x%x\n", "%d:0246 RegLogin failed Data: x%x x%x x%x\n",
phba->brd_no, phba->brd_no,
did, mb->mbxStatus, vport->port_state); did, mb->mbxStatus, vport->port_state);
...@@ -1470,15 +1461,12 @@ static uint32_t ...@@ -1470,15 +1461,12 @@ static uint32_t
lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt) void *arg, uint32_t evt)
{ {
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
/* flush the target */ /* flush the target */
spin_lock_irq(shost->host_lock);
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
spin_unlock_irq(shost->host_lock);
/* Treat like rcv logo */ /* Treat like rcv logo */
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
...@@ -1926,9 +1914,7 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1926,9 +1914,7 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
cur_state = ndlp->nlp_state; cur_state = ndlp->nlp_state;
/* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */ /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
KERN_INFO,
LOG_DISCOVERY,
"%d:0211 DSM in event x%x on NPort x%x in state %d " "%d:0211 DSM in event x%x on NPort x%x in state %d "
"Data: x%x\n", "Data: x%x\n",
phba->brd_no, phba->brd_no,
...@@ -1938,9 +1924,7 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1938,9 +1924,7 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
rc = (func) (vport, ndlp, arg, evt); rc = (func) (vport, ndlp, arg, evt);
/* DSM out state <rc> on NPort <nlp_DID> */ /* DSM out state <rc> on NPort <nlp_DID> */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
KERN_INFO,
LOG_DISCOVERY,
"%d:0212 DSM out state %d on NPort x%x Data: x%x\n", "%d:0212 DSM out state %d on NPort x%x Data: x%x\n",
phba->brd_no, phba->brd_no,
rc, ndlp->nlp_DID, ndlp->nlp_flag); rc, ndlp->nlp_DID, ndlp->nlp_flag);
......
...@@ -840,7 +840,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) ...@@ -840,7 +840,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
cmnd->result = ScsiResult(DID_BUS_BUSY, 0); cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
goto out_fail_command; goto out_fail_command;
} }
lpfc_cmd = lpfc_get_scsi_buf (phba); lpfc_cmd = lpfc_get_scsi_buf(phba);
if (lpfc_cmd == NULL) { if (lpfc_cmd == NULL) {
lpfc_printf_log(phba, KERN_INFO, LOG_FCP, lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
"%d:0707 driver's buffer pool is empty, " "%d:0707 driver's buffer pool is empty, "
......
...@@ -65,6 +65,25 @@ typedef enum _lpfc_iocb_type { ...@@ -65,6 +65,25 @@ typedef enum _lpfc_iocb_type {
LPFC_ABORT_IOCB LPFC_ABORT_IOCB
} lpfc_iocb_type; } lpfc_iocb_type;
/*
* SLI-2/SLI-3 provide different sized iocbs. Given a pointer to the start of
* the ring, and the slot number of the desired iocb entry, calc a pointer to
* that entry.
*/
static inline IOCB_t *
lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
return (IOCB_t *) (((char *) pring->cmdringaddr) +
pring->cmdidx * phba->iocb_cmd_size);
}
static inline IOCB_t *
lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
return (IOCB_t *) (((char *) pring->rspringaddr) +
pring->rspidx * phba->iocb_rsp_size);
}
static struct lpfc_iocbq * static struct lpfc_iocbq *
__lpfc_sli_get_iocbq(struct lpfc_hba *phba) __lpfc_sli_get_iocbq(struct lpfc_hba *phba)
{ {
...@@ -180,6 +199,9 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) ...@@ -180,6 +199,9 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
case CMD_RCV_ELS_REQ_CX: case CMD_RCV_ELS_REQ_CX:
case CMD_RCV_SEQUENCE64_CX: case CMD_RCV_SEQUENCE64_CX:
case CMD_RCV_ELS_REQ64_CX: case CMD_RCV_ELS_REQ64_CX:
case CMD_IOCB_RCV_SEQ64_CX:
case CMD_IOCB_RCV_ELS64_CX:
case CMD_IOCB_RCV_CONT64_CX:
type = LPFC_UNSOL_IOCB; type = LPFC_UNSOL_IOCB;
break; break;
default: default:
...@@ -191,14 +213,19 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) ...@@ -191,14 +213,19 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
} }
static int static int
lpfc_sli_ring_map(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_sli_ring_map(struct lpfc_hba *phba)
{ {
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
MAILBOX_t *pmbox = &pmb->mb; LPFC_MBOXQ_t *pmb;
int i, rc; MAILBOX_t *pmbox;
int i, rc, ret = 0;
pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb)
return -ENOMEM;
pmbox = &pmb->mb;
phba->link_state = LPFC_INIT_MBX_CMDS;
for (i = 0; i < psli->num_rings; i++) { for (i = 0; i < psli->num_rings; i++) {
phba->link_state = LPFC_INIT_MBX_CMDS;
lpfc_config_ring(phba, i, pmb); lpfc_config_ring(phba, i, pmb);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) { if (rc != MBX_SUCCESS) {
...@@ -213,10 +240,12 @@ lpfc_sli_ring_map(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -213,10 +240,12 @@ lpfc_sli_ring_map(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
pmbox->mbxStatus, pmbox->mbxStatus,
i); i);
phba->link_state = LPFC_HBA_ERROR; phba->link_state = LPFC_HBA_ERROR;
return -ENXIO; ret = -ENXIO;
break;
} }
} }
return 0; mempool_free(pmb, phba->mbox_mem_pool);
return ret;
} }
static int static int
...@@ -255,9 +284,10 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -255,9 +284,10 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
static IOCB_t * static IOCB_t *
lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
&phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
&phba->slim2p->mbx.us.s2.port[pring->ringno];
uint32_t max_cmd_idx = pring->numCiocb; uint32_t max_cmd_idx = pring->numCiocb;
IOCB_t *iocb = NULL;
if ((pring->next_cmdidx == pring->cmdidx) && if ((pring->next_cmdidx == pring->cmdidx) &&
(++pring->next_cmdidx >= max_cmd_idx)) (++pring->next_cmdidx >= max_cmd_idx))
...@@ -291,9 +321,7 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -291,9 +321,7 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return NULL; return NULL;
} }
iocb = IOCB_ENTRY(pring->cmdringaddr, pring->cmdidx); return lpfc_cmd_iocb(phba, pring);
return iocb;
} }
uint16_t uint16_t
...@@ -390,8 +418,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -390,8 +418,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
* driver will put a command into. * driver will put a command into.
*/ */
pring->cmdidx = pring->next_cmdidx; pring->cmdidx = pring->next_cmdidx;
writel(pring->cmdidx, phba->MBslimaddr writel(pring->cmdidx, &phba->host_gp[pring->ringno].cmdPutInx);
+ (SLIMOFF + (pring->ringno * 2)) * 4);
} }
static void static void
...@@ -462,7 +489,9 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -462,7 +489,9 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
static void static void
lpfc_sli_turn_on_ring(struct lpfc_hba *phba, int ringno) lpfc_sli_turn_on_ring(struct lpfc_hba *phba, int ringno)
{ {
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[ringno]; struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
&phba->slim2p->mbx.us.s3_pgp.port[ringno] :
&phba->slim2p->mbx.us.s2.port[ringno];
unsigned long iflags; unsigned long iflags;
/* If the ring is active, flag it */ /* If the ring is active, flag it */
...@@ -481,6 +510,168 @@ lpfc_sli_turn_on_ring(struct lpfc_hba *phba, int ringno) ...@@ -481,6 +510,168 @@ lpfc_sli_turn_on_ring(struct lpfc_hba *phba, int ringno)
spin_unlock_irqrestore(&phba->hbalock, iflags); spin_unlock_irqrestore(&phba->hbalock, iflags);
} }
struct lpfc_hbq_entry *
lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
{
struct hbq_s *hbqp = &phba->hbqs[hbqno];
if (hbqp->next_hbqPutIdx == hbqp->hbqPutIdx &&
++hbqp->next_hbqPutIdx >= hbqp->entry_count)
hbqp->next_hbqPutIdx = 0;
if (unlikely(hbqp->local_hbqGetIdx == hbqp->next_hbqPutIdx)) {
uint32_t raw_index = readl(&phba->hbq_get[hbqno]);
uint32_t getidx = le32_to_cpu(raw_index);
hbqp->local_hbqGetIdx = getidx;
if (unlikely(hbqp->local_hbqGetIdx >= hbqp->entry_count)) {
lpfc_printf_log(phba, KERN_ERR,
LOG_SLI,
"%d:1802 HBQ %d: local_hbqGetIdx "
"%u is > than hbqp->entry_count %u\n",
phba->brd_no, hbqno,
hbqp->local_hbqGetIdx,
hbqp->entry_count);
phba->link_state = LPFC_HBA_ERROR;
return NULL;
}
if (hbqp->local_hbqGetIdx == hbqp->next_hbqPutIdx)
return NULL;
}
return (struct lpfc_hbq_entry *) phba->hbqslimp.virt + hbqp->hbqPutIdx;
}
void
lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
{
uint32_t i;
if (!phba->hbq_buffer_pool)
return;
/* Return all memory used by all HBQs */
for (i = 0; i < phba->hbq_buffer_count; i++) {
lpfc_hbq_free(phba, phba->hbq_buffer_pool[i].dbuf.virt,
phba->hbq_buffer_pool[i].dbuf.phys);
}
kfree(phba->hbq_buffer_pool);
phba->hbq_buffer_pool = NULL;
}
static void
lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
struct hbq_dmabuf *hbq_buf_desc)
{
struct lpfc_hbq_entry *hbqe;
/* Get next HBQ entry slot to use */
hbqe = lpfc_sli_next_hbq_slot(phba, hbqno);
if (hbqe) {
struct hbq_s *hbqp = &phba->hbqs[hbqno];
hbqe->bde.addrHigh = putPaddrHigh(hbq_buf_desc->dbuf.phys);
hbqe->bde.addrLow = putPaddrLow(hbq_buf_desc->dbuf.phys);
hbqe->bde.tus.f.bdeSize = FCELSSIZE;
hbqe->bde.tus.f.bdeFlags = 0;
hbqe->buffer_tag = hbq_buf_desc->tag;
/* Sync SLIM */
hbqp->hbqPutIdx = hbqp->next_hbqPutIdx;
writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno);
/* flush */
readl(phba->hbq_put + hbqno);
phba->hbq_buff_count++;
}
}
static void
lpfc_sli_fill_hbq(struct lpfc_hba *phba, uint32_t hbqno, uint32_t buffer_index)
{
struct hbq_dmabuf *hbq_buf_desc;
uint32_t i;
for (i = 0; i < phba->hbqs[hbqno].entry_count; i++) {
/* Search hbqbufq, from the begining,
* looking for an unused entry
*/
phba->hbq_buffer_pool[buffer_index + i].tag |= hbqno << 16;
hbq_buf_desc = phba->hbq_buffer_pool + buffer_index + i;
lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buf_desc);
}
}
int
lpfc_sli_hbqbuf_fill_hbq(struct lpfc_hba *phba)
{
return 0;
}
static int
lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba)
{
uint32_t buffer_index = 0;
uint32_t hbqno;
/* Populate HBQ entries */
for (hbqno = 0; hbqno < phba->hbq_count; ++hbqno) {
/* Find ring associated with HBQ */
lpfc_sli_fill_hbq(phba, hbqno, buffer_index);
buffer_index += phba->hbqs[hbqno].entry_count;
}
return 0;
}
struct hbq_dmabuf *
lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
{
if ((tag & 0xffff) < phba->hbq_buffer_count)
return phba->hbq_buffer_pool + (tag & 0xffff);
lpfc_printf_log(phba, KERN_ERR,
LOG_SLI,
"%d:1803 Bad hbq tag. Data: x%x x%x\n",
phba->brd_no, tag,
phba->hbq_buffer_count);
return NULL;
}
void
lpfc_sli_hbqbuf_free(struct lpfc_hba *phba, void *virt, dma_addr_t phys)
{
uint32_t i, hbqno;
for (i = 0; i < phba->hbq_buffer_count; i++) {
/* Search hbqbufq, from the begining, looking for a match on
phys */
if (phba->hbq_buffer_pool[i].dbuf.phys == phys) {
hbqno = phba->hbq_buffer_pool[i].tag >> 16;
lpfc_sli_hbq_to_firmware(phba, hbqno,
phba->hbq_buffer_pool + i);
return;
}
}
lpfc_printf_log(phba, KERN_ERR,
LOG_SLI,
"%d:1804 Cannot find virtual addr for "
"mapped buf. Data x%llx\n",
phba->brd_no, (unsigned long long) phys);
}
void
lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *sp)
{
uint32_t hbqno;
if (sp) {
hbqno = sp->tag >> 16;
lpfc_sli_hbq_to_firmware(phba, hbqno, sp);
}
}
static int static int
lpfc_sli_chk_mbx_command(uint8_t mbxCommand) lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
{ {
...@@ -757,7 +948,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -757,7 +948,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
match = 0; match = 0;
irsp = &(saveq->iocb); irsp = &(saveq->iocb);
if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX) if ((irsp->ulpCommand == CMD_RCV_ELS_REQ64_CX)
|| (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)) { || (irsp->ulpCommand == CMD_RCV_ELS_REQ_CX)
|| (irsp->ulpCommand == CMD_IOCB_RCV_ELS64_CX)
|| (irsp->ulpCommand == CMD_IOCB_RCV_CONT64_CX)) {
Rctl = FC_ELS_REQ; Rctl = FC_ELS_REQ;
Type = FC_ELS_DATA; Type = FC_ELS_DATA;
} else { } else {
...@@ -769,7 +962,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -769,7 +962,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
/* Firmware Workaround */ /* Firmware Workaround */
if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) && if ((Rctl == 0) && (pring->ringno == LPFC_ELS_RING) &&
(irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX)) { (irsp->ulpCommand == CMD_RCV_SEQUENCE64_CX ||
irsp->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
Rctl = FC_ELS_REQ; Rctl = FC_ELS_REQ;
Type = FC_ELS_DATA; Type = FC_ELS_DATA;
w5p->hcsw.Rctl = Rctl; w5p->hcsw.Rctl = Rctl;
...@@ -906,7 +1100,10 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -906,7 +1100,10 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
static void static void
lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
&phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
&phba->slim2p->mbx.us.s2.port[pring->ringno];
/* /*
* Ring <ringno> handler: portRspPut <portRspPut> is bigger then * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
* rsp ring <portRspMax> * rsp ring <portRspMax>
...@@ -945,14 +1142,15 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba) ...@@ -945,14 +1142,15 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
uint32_t portRspPut, portRspMax; uint32_t portRspPut, portRspMax;
int type; int type;
uint32_t rsp_cmpl = 0; uint32_t rsp_cmpl = 0;
void __iomem *to_slim;
uint32_t ha_copy; uint32_t ha_copy;
unsigned long iflags; unsigned long iflags;
pring->stats.iocb_event++; pring->stats.iocb_event++;
/* The driver assumes SLI-2 mode */ pgp = (phba->sli_rev == 3) ?
pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; &phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
&phba->slim2p->mbx.us.s2.port[pring->ringno];
/* /*
* The next available response entry should never exceed the maximum * The next available response entry should never exceed the maximum
...@@ -967,9 +1165,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba) ...@@ -967,9 +1165,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
rmb(); rmb();
while (pring->rspidx != portRspPut) { while (pring->rspidx != portRspPut) {
entry = lpfc_resp_iocb(phba, pring);
entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
if (++pring->rspidx >= portRspMax) if (++pring->rspidx >= portRspMax)
pring->rspidx = 0; pring->rspidx = 0;
...@@ -1050,9 +1246,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba) ...@@ -1050,9 +1246,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
* been updated, sync the pgp->rspPutInx and fetch the new port * been updated, sync the pgp->rspPutInx and fetch the new port
* response put pointer. * response put pointer.
*/ */
to_slim = phba->MBslimaddr + writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
(SLIMOFF + (pring->ringno * 2) + 1) * 4;
writeb(pring->rspidx, to_slim);
if (pring->rspidx == portRspPut) if (pring->rspidx == portRspPut)
portRspPut = le32_to_cpu(pgp->rspPutInx); portRspPut = le32_to_cpu(pgp->rspPutInx);
...@@ -1096,7 +1290,9 @@ static int ...@@ -1096,7 +1290,9 @@ static int
lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, uint32_t mask) struct lpfc_sli_ring *pring, uint32_t mask)
{ {
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
&phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
&phba->slim2p->mbx.us.s2.port[pring->ringno];
IOCB_t *irsp = NULL; IOCB_t *irsp = NULL;
IOCB_t *entry = NULL; IOCB_t *entry = NULL;
struct lpfc_iocbq *cmdiocbq = NULL; struct lpfc_iocbq *cmdiocbq = NULL;
...@@ -1107,7 +1303,6 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, ...@@ -1107,7 +1303,6 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
lpfc_iocb_type type; lpfc_iocb_type type;
unsigned long iflag; unsigned long iflag;
uint32_t rsp_cmpl = 0; uint32_t rsp_cmpl = 0;
void __iomem *to_slim;
spin_lock_irqsave(&phba->hbalock, iflag); spin_lock_irqsave(&phba->hbalock, iflag);
pring->stats.iocb_event++; pring->stats.iocb_event++;
...@@ -1131,14 +1326,14 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, ...@@ -1131,14 +1326,14 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
* structure. The copy involves a byte-swap since the * structure. The copy involves a byte-swap since the
* network byte order and pci byte orders are different. * network byte order and pci byte orders are different.
*/ */
entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx); entry = lpfc_resp_iocb(phba, pring);
if (++pring->rspidx >= portRspMax) if (++pring->rspidx >= portRspMax)
pring->rspidx = 0; pring->rspidx = 0;
lpfc_sli_pcimem_bcopy((uint32_t *) entry, lpfc_sli_pcimem_bcopy((uint32_t *) entry,
(uint32_t *) &rspiocbq.iocb, (uint32_t *) &rspiocbq.iocb,
sizeof(IOCB_t)); phba->iocb_rsp_size);
INIT_LIST_HEAD(&(rspiocbq.list)); INIT_LIST_HEAD(&(rspiocbq.list));
irsp = &rspiocbq.iocb; irsp = &rspiocbq.iocb;
...@@ -1222,9 +1417,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, ...@@ -1222,9 +1417,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
* been updated, sync the pgp->rspPutInx and fetch the new port * been updated, sync the pgp->rspPutInx and fetch the new port
* response put pointer. * response put pointer.
*/ */
to_slim = phba->MBslimaddr + writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
(SLIMOFF + (pring->ringno * 2) + 1) * 4;
writel(pring->rspidx, to_slim);
if (pring->rspidx == portRspPut) if (pring->rspidx == portRspPut)
portRspPut = le32_to_cpu(pgp->rspPutInx); portRspPut = le32_to_cpu(pgp->rspPutInx);
...@@ -1258,7 +1451,9 @@ int ...@@ -1258,7 +1451,9 @@ int
lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, uint32_t mask) struct lpfc_sli_ring *pring, uint32_t mask)
{ {
struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno]; struct lpfc_pgp *pgp = (phba->sli_rev == 3) ?
&phba->slim2p->mbx.us.s3_pgp.port[pring->ringno] :
&phba->slim2p->mbx.us.s2.port[pring->ringno];
IOCB_t *entry; IOCB_t *entry;
IOCB_t *irsp = NULL; IOCB_t *irsp = NULL;
struct lpfc_iocbq *rspiocbp = NULL; struct lpfc_iocbq *rspiocbp = NULL;
...@@ -1271,7 +1466,6 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, ...@@ -1271,7 +1466,6 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
uint32_t portRspPut, portRspMax; uint32_t portRspPut, portRspMax;
int rc = 1; int rc = 1;
unsigned long iflag; unsigned long iflag;
void __iomem *to_slim;
spin_lock_irqsave(&phba->hbalock, iflag); spin_lock_irqsave(&phba->hbalock, iflag);
pring->stats.iocb_event++; pring->stats.iocb_event++;
...@@ -1287,9 +1481,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, ...@@ -1287,9 +1481,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
* Ring <ringno> handler: portRspPut <portRspPut> is bigger then * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
* rsp ring <portRspMax> * rsp ring <portRspMax>
*/ */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
KERN_ERR,
LOG_SLI,
"%d:0303 Ring %d handler: portRspPut %d " "%d:0303 Ring %d handler: portRspPut %d "
"is bigger then rsp ring %d\n", "is bigger then rsp ring %d\n",
phba->brd_no, phba->brd_no,
...@@ -1319,7 +1511,8 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, ...@@ -1319,7 +1511,8 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
* the ulpLe field is set, the entire Command has been * the ulpLe field is set, the entire Command has been
* received. * received.
*/ */
entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx); entry = lpfc_resp_iocb(phba, pring);
rspiocbp = __lpfc_sli_get_iocbq(phba); rspiocbp = __lpfc_sli_get_iocbq(phba);
if (rspiocbp == NULL) { if (rspiocbp == NULL) {
printk(KERN_ERR "%s: out of buffers! Failing " printk(KERN_ERR "%s: out of buffers! Failing "
...@@ -1327,15 +1520,14 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, ...@@ -1327,15 +1520,14 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
break; break;
} }
lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb, sizeof(IOCB_t)); lpfc_sli_pcimem_bcopy(entry, &rspiocbp->iocb,
phba->iocb_rsp_size);
irsp = &rspiocbp->iocb; irsp = &rspiocbp->iocb;
if (++pring->rspidx >= portRspMax) if (++pring->rspidx >= portRspMax)
pring->rspidx = 0; pring->rspidx = 0;
to_slim = phba->MBslimaddr + (SLIMOFF + (pring->ringno * 2) writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx);
+ 1) * 4;
writel(pring->rspidx, to_slim);
if (list_empty(&(pring->iocb_continueq))) { if (list_empty(&(pring->iocb_continueq))) {
list_add(&rspiocbp->list, &(pring->iocb_continueq)); list_add(&rspiocbp->list, &(pring->iocb_continueq));
...@@ -1361,21 +1553,31 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, ...@@ -1361,21 +1553,31 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
if (irsp->ulpStatus) { if (irsp->ulpStatus) {
/* Rsp ring <ringno> error: IOCB */ /* Rsp ring <ringno> error: IOCB */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
KERN_WARNING, "%d:0328 Rsp Ring %d error: "
LOG_SLI, "IOCB Data: "
"%d:0328 Rsp Ring %d error: IOCB Data: " "x%x x%x x%x x%x "
"x%x x%x x%x x%x x%x x%x x%x x%x\n", "x%x x%x x%x x%x "
phba->brd_no, "x%x x%x x%x x%x "
pring->ringno, "x%x x%x x%x x%x\n",
irsp->un.ulpWord[0], phba->brd_no,
irsp->un.ulpWord[1], pring->ringno,
irsp->un.ulpWord[2], irsp->un.ulpWord[0],
irsp->un.ulpWord[3], irsp->un.ulpWord[1],
irsp->un.ulpWord[4], irsp->un.ulpWord[2],
irsp->un.ulpWord[5], irsp->un.ulpWord[3],
*(((uint32_t *) irsp) + 6), irsp->un.ulpWord[4],
*(((uint32_t *) irsp) + 7)); irsp->un.ulpWord[5],
*(((uint32_t *) irsp) + 6),
*(((uint32_t *) irsp) + 7),
*(((uint32_t *) irsp) + 8),
*(((uint32_t *) irsp) + 9),
*(((uint32_t *) irsp) + 10),
*(((uint32_t *) irsp) + 11),
*(((uint32_t *) irsp) + 12),
*(((uint32_t *) irsp) + 13),
*(((uint32_t *) irsp) + 14),
*(((uint32_t *) irsp) + 15));
} }
/* /*
...@@ -1659,13 +1861,9 @@ lpfc_sli_brdkill(struct lpfc_hba *phba) ...@@ -1659,13 +1861,9 @@ lpfc_sli_brdkill(struct lpfc_hba *phba)
psli = &phba->sli; psli = &phba->sli;
/* Kill HBA */ /* Kill HBA */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
KERN_INFO,
LOG_SLI,
"%d:0329 Kill HBA Data: x%x x%x\n", "%d:0329 Kill HBA Data: x%x x%x\n",
phba->brd_no, phba->brd_no, phba->pport->port_state, psli->sli_flag);
phba->pport->port_state,
psli->sli_flag);
if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL)) == 0) GFP_KERNEL)) == 0)
...@@ -1857,13 +2055,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) ...@@ -1857,13 +2055,10 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
if (i++ >= 20) { if (i++ >= 20) {
/* Adapter failed to init, timeout, status reg /* Adapter failed to init, timeout, status reg
<status> */ <status> */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
KERN_ERR,
LOG_INIT,
"%d:0436 Adapter failed to init, " "%d:0436 Adapter failed to init, "
"timeout, status reg x%x\n", "timeout, status reg x%x\n",
phba->brd_no, phba->brd_no, status);
status);
phba->link_state = LPFC_HBA_ERROR; phba->link_state = LPFC_HBA_ERROR;
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -1873,9 +2068,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) ...@@ -1873,9 +2068,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
/* ERROR: During chipset initialization */ /* ERROR: During chipset initialization */
/* Adapter failed to init, chipset, status reg /* Adapter failed to init, chipset, status reg
<status> */ <status> */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
KERN_ERR,
LOG_INIT,
"%d:0437 Adapter failed to init, " "%d:0437 Adapter failed to init, "
"chipset, status reg x%x\n", "chipset, status reg x%x\n",
phba->brd_no, phba->brd_no,
...@@ -1905,9 +2098,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) ...@@ -1905,9 +2098,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
if (status & HS_FFERM) { if (status & HS_FFERM) {
/* ERROR: During chipset initialization */ /* ERROR: During chipset initialization */
/* Adapter failed to init, chipset, status reg <status> */ /* Adapter failed to init, chipset, status reg <status> */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
KERN_ERR,
LOG_INIT,
"%d:0438 Adapter failed to init, chipset, " "%d:0438 Adapter failed to init, chipset, "
"status reg x%x\n", "status reg x%x\n",
phba->brd_no, phba->brd_no,
...@@ -1926,8 +2117,145 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) ...@@ -1926,8 +2117,145 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
return 0; return 0;
} }
static struct hbq_dmabuf *
lpfc_alloc_hbq_buffers(struct lpfc_hba *phba, int count)
{
struct hbq_dmabuf *hbq_buffer_pool;
int i;
hbq_buffer_pool = kmalloc(count * sizeof(struct hbq_dmabuf),
GFP_KERNEL);
if (!hbq_buffer_pool)
goto out;
for (i = 0; i < count; ++i) {
hbq_buffer_pool[i].dbuf.virt =
lpfc_hbq_alloc(phba, MEM_PRI,
&hbq_buffer_pool[i].dbuf.phys);
if (hbq_buffer_pool[i].dbuf.virt == NULL)
goto alloc_failed;
hbq_buffer_pool[i].tag = i;
}
goto out;
alloc_failed:
while (--i >= 0)
lpfc_hbq_free(phba, hbq_buffer_pool[i].dbuf.virt,
hbq_buffer_pool[i].dbuf.phys);
kfree(hbq_buffer_pool);
hbq_buffer_pool = NULL;
out:
phba->hbq_buffer_pool = hbq_buffer_pool;
return hbq_buffer_pool;
}
static struct lpfc_hbq_init lpfc_els_hbq = {
.rn = 1,
.entry_count = 1200,
.mask_count = 0,
.profile = 0,
.ring_mask = 1 << LPFC_ELS_RING,
};
static struct lpfc_hbq_init *lpfc_hbq_definitions[] = {
&lpfc_els_hbq,
};
static int
lpfc_sli_hbq_count(void)
{
return ARRAY_SIZE(lpfc_hbq_definitions);
}
static int
lpfc_sli_hbq_entry_count(void)
{
int hbq_count = lpfc_sli_hbq_count();
int count = 0;
int i;
for (i = 0; i < hbq_count; ++i)
count += lpfc_hbq_definitions[i]->entry_count;
return count;
}
int int
lpfc_sli_hba_setup(struct lpfc_hba *phba) lpfc_sli_hbq_size(void)
{
return lpfc_sli_hbq_entry_count() * sizeof(struct lpfc_hbq_entry);
}
static int
lpfc_sli_hbq_setup(struct lpfc_hba *phba)
{
int hbq_count = lpfc_sli_hbq_count();
LPFC_MBOXQ_t *pmb;
MAILBOX_t *pmbox;
uint32_t hbqno;
uint32_t hbq_entry_index;
uint32_t hbq_buffer_count;
/* count hbq buffers */
hbq_buffer_count = lpfc_sli_hbq_entry_count();
if (!lpfc_alloc_hbq_buffers(phba, hbq_buffer_count))
return -ENOMEM;
phba->hbq_buffer_count = hbq_buffer_count;
/* Get a Mailbox buffer to setup mailbox
* commands for HBA initialization
*/
pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb)
return -ENOMEM;
pmbox = &pmb->mb;
/* Initialize the struct lpfc_sli_hbq structure for each hbq */
phba->link_state = LPFC_INIT_MBX_CMDS;
hbq_entry_index = 0;
for (hbqno = 0; hbqno < hbq_count; ++hbqno) {
phba->hbqs[hbqno].next_hbqPutIdx = 0;
phba->hbqs[hbqno].hbqPutIdx = 0;
phba->hbqs[hbqno].local_hbqGetIdx = 0;
phba->hbqs[hbqno].entry_count =
lpfc_hbq_definitions[hbqno]->entry_count;
lpfc_config_hbq(phba, lpfc_hbq_definitions[hbqno],
hbq_entry_index, pmb);
hbq_entry_index += phba->hbqs[hbqno].entry_count;
if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
/* Adapter failed to init, mbxCmd <cmd> CFG_RING,
mbxStatus <status>, ring <num> */
lpfc_printf_log(phba, KERN_ERR,
LOG_SLI,
"%d:1805 Adapter failed to init. "
"Data: x%x x%x x%x\n",
phba->brd_no, pmbox->mbxCommand,
pmbox->mbxStatus, hbqno);
phba->link_state = LPFC_HBA_ERROR;
mempool_free(pmb, phba->mbox_mem_pool);
/* Free all HBQ memory */
lpfc_sli_hbqbuf_free_all(phba);
return ENXIO;
}
}
phba->hbq_count = hbq_count;
/* Initially populate or replenish the HBQs */
lpfc_sli_hbqbuf_fill_hbqs(phba);
mempool_free(pmb, phba->mbox_mem_pool);
return 0;
}
static int
lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
{ {
LPFC_MBOXQ_t *pmb; LPFC_MBOXQ_t *pmb;
uint32_t resetcount = 0, rc = 0, done = 0; uint32_t resetcount = 0, rc = 0, done = 0;
...@@ -1938,6 +2266,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) ...@@ -1938,6 +2266,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
return -ENOMEM; return -ENOMEM;
} }
phba->sli_rev = sli_mode;
while (resetcount < 2 && !done) { while (resetcount < 2 && !done) {
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE; phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
...@@ -1954,14 +2283,14 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) ...@@ -1954,14 +2283,14 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
resetcount++; resetcount++;
/* Call pre CONFIG_PORT mailbox command initialization. A value of 0 /* Call pre CONFIG_PORT mailbox command initialization. A
* means the call was successful. Any other nonzero value is a failure, * value of 0 means the call was successful. Any other
* but if ERESTART is returned, the driver may reset the HBA and try * nonzero value is a failure, but if ERESTART is returned,
* again. * the driver may reset the HBA and try again.
*/ */
rc = lpfc_config_port_prep(phba); rc = lpfc_config_port_prep(phba);
if (rc == -ERESTART) { if (rc == -ERESTART) {
phba->pport->port_state = 0; phba->link_state = LPFC_LINK_UNKNOWN;
continue; continue;
} else if (rc) { } else if (rc) {
break; break;
...@@ -1970,39 +2299,116 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) ...@@ -1970,39 +2299,116 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
phba->link_state = LPFC_INIT_MBX_CMDS; phba->link_state = LPFC_INIT_MBX_CMDS;
lpfc_config_port(phba, pmb); lpfc_config_port(phba, pmb);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc == MBX_SUCCESS) if (rc != MBX_SUCCESS) {
done = 1;
else {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"%d:0442 Adapter failed to init, mbxCmd x%x " "%d:0442 Adapter failed to init, "
"CONFIG_PORT, mbxStatus x%x Data: x%x\n", "mbxCmd x%x CONFIG_PORT, mbxStatus "
phba->brd_no, pmb->mb.mbxCommand, "x%x Data: x%x\n",
pmb->mb.mbxStatus, 0); phba->brd_no, pmb->mb.mbxCommand,
pmb->mb.mbxStatus, 0);
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE; phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
rc = -ENXIO; rc = -ENXIO;
} else {
done = 1;
/* DBG: Do we need max_vpi, reg_vpi for that matter
phba->max_vpi = 0;
*/
} }
} }
if (!done)
if (!done) {
rc = -EINVAL;
goto do_prep_failed;
}
if ((pmb->mb.un.varCfgPort.sli_mode == 3) &&
(!pmb->mb.un.varCfgPort.cMA)) {
rc = -ENXIO;
goto do_prep_failed;
}
return rc;
do_prep_failed:
mempool_free(pmb, phba->mbox_mem_pool);
return rc;
}
int
lpfc_sli_hba_setup(struct lpfc_hba *phba)
{
uint32_t rc;
int mode = 3;
switch (lpfc_sli_mode) {
case 2:
mode = 2;
break;
case 0:
case 3:
break;
default:
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"%d:1819 Unrecognized lpfc_sli_mode "
"parameter: %d.\n",
phba->brd_no, lpfc_sli_mode);
break;
}
rc = lpfc_do_config_port(phba, mode);
if (rc && lpfc_sli_mode == 3)
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"%d:1820 Unable to select SLI-3. "
"Not supported by adapter.\n",
phba->brd_no);
if (rc && mode != 2)
rc = lpfc_do_config_port(phba, 2);
if (rc)
goto lpfc_sli_hba_setup_error; goto lpfc_sli_hba_setup_error;
rc = lpfc_sli_ring_map(phba, pmb); if (phba->sli_rev == 3) {
phba->iocb_cmd_size = SLI3_IOCB_CMD_SIZE;
phba->iocb_rsp_size = SLI3_IOCB_RSP_SIZE;
phba->sli3_options |= LPFC_SLI3_ENABLED;
phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED;
} else {
phba->iocb_cmd_size = SLI2_IOCB_CMD_SIZE;
phba->iocb_rsp_size = SLI2_IOCB_RSP_SIZE;
phba->sli3_options = 0x0;
}
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"%d:0444 Firmware in SLI %x mode.\n",
phba->brd_no, phba->sli_rev);
rc = lpfc_sli_ring_map(phba);
if (rc) if (rc)
goto lpfc_sli_hba_setup_error; goto lpfc_sli_hba_setup_error;
/* Init HBQs */
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
rc = lpfc_sli_hbq_setup(phba);
if (rc)
goto lpfc_sli_hba_setup_error;
}
phba->sli.sli_flag |= LPFC_PROCESS_LA; phba->sli.sli_flag |= LPFC_PROCESS_LA;
rc = lpfc_config_port_post(phba); rc = lpfc_config_port_post(phba);
if (rc) if (rc)
goto lpfc_sli_hba_setup_error; goto lpfc_sli_hba_setup_error;
goto lpfc_sli_hba_setup_exit; return rc;
lpfc_sli_hba_setup_error:
lpfc_sli_hba_setup_error:
phba->link_state = LPFC_HBA_ERROR; phba->link_state = LPFC_HBA_ERROR;
lpfc_sli_hba_setup_exit: lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
mempool_free(pmb, phba->mbox_mem_pool); "%d:0445 Firmware initialization failed\n",
phba->brd_no);
return rc; return rc;
} }
...@@ -2027,7 +2433,7 @@ lpfc_mbox_timeout(unsigned long ptr) ...@@ -2027,7 +2433,7 @@ lpfc_mbox_timeout(unsigned long ptr)
uint32_t tmo_posted; uint32_t tmo_posted;
spin_lock_irqsave(&phba->pport->work_port_lock, iflag); spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
tmo_posted = (phba->pport->work_port_events & WORKER_MBOX_TMO) == 0; tmo_posted = (phba->pport->work_port_events & WORKER_MBOX_TMO);
if (!tmo_posted) if (!tmo_posted)
phba->pport->work_port_events |= WORKER_MBOX_TMO; phba->pport->work_port_events |= WORKER_MBOX_TMO;
spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
...@@ -2051,9 +2457,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) ...@@ -2051,9 +2457,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
} }
/* Mbox cmd <mbxCommand> timeout */ /* Mbox cmd <mbxCommand> timeout */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
KERN_ERR,
LOG_MBOX | LOG_SLI,
"%d:0310 Mailbox command x%x timeout Data: x%x x%x x%p\n", "%d:0310 Mailbox command x%x timeout Data: x%x x%x x%p\n",
phba->brd_no, phba->brd_no,
mb->mbxCommand, mb->mbxCommand,
...@@ -2105,13 +2509,25 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) ...@@ -2105,13 +2509,25 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
volatile uint32_t word0, ldata; volatile uint32_t word0, ldata;
void __iomem *to_slim; void __iomem *to_slim;
if (pmbox->mbox_cmpl && pmbox->mbox_cmpl != lpfc_sli_def_mbox_cmpl &&
pmbox->mbox_cmpl != lpfc_sli_wake_mbox_wait) {
if(!pmbox->vport) {
lpfc_printf_log(phba, KERN_ERR,
LOG_MBOX,
"%d:1806 Mbox x%x failed. No vport\n",
phba->brd_no,
pmbox->mb.mbxCommand);
dump_stack();
return MBXERR_ERROR;
}
}
/* If the PCI channel is in offline state, do not post mbox. */ /* If the PCI channel is in offline state, do not post mbox. */
if (unlikely(pci_channel_offline(phba->pcidev))) if (unlikely(pci_channel_offline(phba->pcidev)))
return MBX_NOT_FINISHED; return MBX_NOT_FINISHED;
spin_lock_irqsave(&phba->hbalock, drvr_flag); spin_lock_irqsave(&phba->hbalock, drvr_flag);
psli = &phba->sli; psli = &phba->sli;
mb = &pmbox->mb; mb = &pmbox->mb;
status = MBX_SUCCESS; status = MBX_SUCCESS;
...@@ -2172,15 +2588,11 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) ...@@ -2172,15 +2588,11 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
lpfc_mbox_put(phba, pmbox); lpfc_mbox_put(phba, pmbox);
/* Mbox cmd issue - BUSY */ /* Mbox cmd issue - BUSY */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
KERN_INFO,
LOG_MBOX | LOG_SLI,
"%d:0308 Mbox cmd issue - BUSY Data: x%x x%x x%x x%x\n", "%d:0308 Mbox cmd issue - BUSY Data: x%x x%x x%x x%x\n",
phba->brd_no, phba->brd_no,
mb->mbxCommand, mb->mbxCommand, phba->pport->port_state,
phba->pport->port_state, psli->sli_flag, flag);
psli->sli_flag,
flag);
psli->slistat.mbox_busy++; psli->slistat.mbox_busy++;
spin_unlock_irqrestore(&phba->hbalock, drvr_flag); spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
...@@ -2223,15 +2635,11 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) ...@@ -2223,15 +2635,11 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
} }
/* Mailbox cmd <cmd> issue */ /* Mailbox cmd <cmd> issue */
lpfc_printf_log(phba, lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
KERN_INFO,
LOG_MBOX | LOG_SLI,
"%d:0309 Mailbox cmd x%x issue Data: x%x x%x x%x\n", "%d:0309 Mailbox cmd x%x issue Data: x%x x%x x%x\n",
phba->brd_no, phba->brd_no,
mb->mbxCommand, mb->mbxCommand, phba->pport->port_state,
phba->pport->port_state, psli->sli_flag, flag);
psli->sli_flag,
flag);
psli->slistat.mbox_cmd++; psli->slistat.mbox_cmd++;
evtctr = psli->slistat.mbox_event; evtctr = psli->slistat.mbox_event;
...@@ -2526,7 +2934,7 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) ...@@ -2526,7 +2934,7 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba)
int int
lpfc_sli_setup(struct lpfc_hba *phba) lpfc_sli_setup(struct lpfc_hba *phba)
{ {
int i, totiocb = 0; int i, totiocbsize = 0;
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
...@@ -2551,9 +2959,15 @@ lpfc_sli_setup(struct lpfc_hba *phba) ...@@ -2551,9 +2959,15 @@ lpfc_sli_setup(struct lpfc_hba *phba)
pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES; pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES;
pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES; pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES;
pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES; pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES;
pring->sizeCiocb = (phba->sli_rev == 3) ?
SLI3_IOCB_CMD_SIZE :
SLI2_IOCB_CMD_SIZE;
pring->sizeRiocb = (phba->sli_rev == 3) ?
SLI3_IOCB_RSP_SIZE :
SLI2_IOCB_RSP_SIZE;
pring->iotag_ctr = 0; pring->iotag_ctr = 0;
pring->iotag_max = pring->iotag_max =
(phba->cfg_hba_queue_depth * 2); (phba->cfg_hba_queue_depth * 2);
pring->fast_iotag = pring->iotag_max; pring->fast_iotag = pring->iotag_max;
pring->num_mask = 0; pring->num_mask = 0;
break; break;
...@@ -2561,6 +2975,12 @@ lpfc_sli_setup(struct lpfc_hba *phba) ...@@ -2561,6 +2975,12 @@ lpfc_sli_setup(struct lpfc_hba *phba)
/* numCiocb and numRiocb are used in config_port */ /* numCiocb and numRiocb are used in config_port */
pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES; pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES;
pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES; pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES;
pring->sizeCiocb = (phba->sli_rev == 3) ?
SLI3_IOCB_CMD_SIZE :
SLI2_IOCB_CMD_SIZE;
pring->sizeRiocb = (phba->sli_rev == 3) ?
SLI3_IOCB_RSP_SIZE :
SLI2_IOCB_RSP_SIZE;
pring->iotag_max = phba->cfg_hba_queue_depth; pring->iotag_max = phba->cfg_hba_queue_depth;
pring->num_mask = 0; pring->num_mask = 0;
break; break;
...@@ -2568,6 +2988,12 @@ lpfc_sli_setup(struct lpfc_hba *phba) ...@@ -2568,6 +2988,12 @@ lpfc_sli_setup(struct lpfc_hba *phba)
/* numCiocb and numRiocb are used in config_port */ /* numCiocb and numRiocb are used in config_port */
pring->numCiocb = SLI2_IOCB_CMD_R2_ENTRIES; pring->numCiocb = SLI2_IOCB_CMD_R2_ENTRIES;
pring->numRiocb = SLI2_IOCB_RSP_R2_ENTRIES; pring->numRiocb = SLI2_IOCB_RSP_R2_ENTRIES;
pring->sizeCiocb = (phba->sli_rev == 3) ?
SLI3_IOCB_CMD_SIZE :
SLI2_IOCB_CMD_SIZE;
pring->sizeRiocb = (phba->sli_rev == 3) ?
SLI3_IOCB_RSP_SIZE :
SLI2_IOCB_RSP_SIZE;
pring->fast_iotag = 0; pring->fast_iotag = 0;
pring->iotag_ctr = 0; pring->iotag_ctr = 0;
pring->iotag_max = 4096; pring->iotag_max = 4096;
...@@ -2576,36 +3002,38 @@ lpfc_sli_setup(struct lpfc_hba *phba) ...@@ -2576,36 +3002,38 @@ lpfc_sli_setup(struct lpfc_hba *phba)
pring->prt[0].rctl = FC_ELS_REQ; pring->prt[0].rctl = FC_ELS_REQ;
pring->prt[0].type = FC_ELS_DATA; pring->prt[0].type = FC_ELS_DATA;
pring->prt[0].lpfc_sli_rcv_unsol_event = pring->prt[0].lpfc_sli_rcv_unsol_event =
lpfc_els_unsol_event; lpfc_els_unsol_event;
pring->prt[1].profile = 0; /* Mask 1 */ pring->prt[1].profile = 0; /* Mask 1 */
pring->prt[1].rctl = FC_ELS_RSP; pring->prt[1].rctl = FC_ELS_RSP;
pring->prt[1].type = FC_ELS_DATA; pring->prt[1].type = FC_ELS_DATA;
pring->prt[1].lpfc_sli_rcv_unsol_event = pring->prt[1].lpfc_sli_rcv_unsol_event =
lpfc_els_unsol_event; lpfc_els_unsol_event;
pring->prt[2].profile = 0; /* Mask 2 */ pring->prt[2].profile = 0; /* Mask 2 */
/* NameServer Inquiry */ /* NameServer Inquiry */
pring->prt[2].rctl = FC_UNSOL_CTL; pring->prt[2].rctl = FC_UNSOL_CTL;
/* NameServer */ /* NameServer */
pring->prt[2].type = FC_COMMON_TRANSPORT_ULP; pring->prt[2].type = FC_COMMON_TRANSPORT_ULP;
pring->prt[2].lpfc_sli_rcv_unsol_event = pring->prt[2].lpfc_sli_rcv_unsol_event =
lpfc_ct_unsol_event; lpfc_ct_unsol_event;
pring->prt[3].profile = 0; /* Mask 3 */ pring->prt[3].profile = 0; /* Mask 3 */
/* NameServer response */ /* NameServer response */
pring->prt[3].rctl = FC_SOL_CTL; pring->prt[3].rctl = FC_SOL_CTL;
/* NameServer */ /* NameServer */
pring->prt[3].type = FC_COMMON_TRANSPORT_ULP; pring->prt[3].type = FC_COMMON_TRANSPORT_ULP;
pring->prt[3].lpfc_sli_rcv_unsol_event = pring->prt[3].lpfc_sli_rcv_unsol_event =
lpfc_ct_unsol_event; lpfc_ct_unsol_event;
break; break;
} }
totiocb += (pring->numCiocb + pring->numRiocb); totiocbsize += (pring->numCiocb * pring->sizeCiocb) +
(pring->numRiocb * pring->sizeRiocb);
} }
if (totiocb > MAX_SLI2_IOCB) { if (totiocbsize > MAX_SLIM_IOCB_SIZE) {
/* Too many cmd / rsp ring entries in SLI2 SLIM */ /* Too many cmd / rsp ring entries in SLI2 SLIM */
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"%d:0462 Too many cmd / rsp ring entries in " "%d:0462 Too many cmd / rsp ring entries in "
"SLI2 SLIM Data: x%x x%x\n", "SLI2 SLIM Data: x%x x%lx\n",
phba->brd_no, totiocb, MAX_SLI2_IOCB); phba->brd_no, totiocbsize,
(unsigned long) MAX_SLIM_IOCB_SIZE);
} }
if (phba->cfg_multi_ring_support == 2) if (phba->cfg_multi_ring_support == 2)
lpfc_extra_ring_setup(phba); lpfc_extra_ring_setup(phba);
...@@ -2689,6 +3117,7 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) ...@@ -2689,6 +3117,7 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
phba->pport->work_port_events &= ~WORKER_MBOX_TMO; phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
spin_unlock_irqrestore(&phba->pport->work_port_lock, flags); spin_unlock_irqrestore(&phba->pport->work_port_lock, flags);
spin_lock_irqsave(&phba->hbalock, flags);
pmb = psli->mbox_active; pmb = psli->mbox_active;
if (pmb) { if (pmb) {
psli->mbox_active = NULL; psli->mbox_active = NULL;
...@@ -2708,6 +3137,9 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) ...@@ -2708,6 +3137,9 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
} }
INIT_LIST_HEAD(&psli->mboxq); INIT_LIST_HEAD(&psli->mboxq);
/* Free all HBQ memory */
lpfc_sli_hbqbuf_free_all(phba);
return 1; return 1;
} }
...@@ -3075,11 +3507,9 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, ...@@ -3075,11 +3507,9 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0); retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0);
if (retval == IOCB_SUCCESS) { if (retval == IOCB_SUCCESS) {
timeout_req = timeout * HZ; timeout_req = timeout * HZ;
spin_unlock_irq(&phba->hbalock);
timeleft = wait_event_timeout(done_q, timeleft = wait_event_timeout(done_q,
piocb->iocb_flag & LPFC_IO_WAKE, piocb->iocb_flag & LPFC_IO_WAKE,
timeout_req); timeout_req);
spin_lock_irq(&phba->hbalock);
if (piocb->iocb_flag & LPFC_IO_WAKE) { if (piocb->iocb_flag & LPFC_IO_WAKE) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI, lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
...@@ -3164,13 +3594,25 @@ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba) ...@@ -3164,13 +3594,25 @@ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
{ {
struct lpfc_vport *vport = phba->pport; struct lpfc_vport *vport = phba->pport;
int i = 0; int i = 0;
uint32_t ha_copy;
while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !vport->stopped) { while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !vport->stopped) {
if (i++ > LPFC_MBOX_TMO * 1000) if (i++ > LPFC_MBOX_TMO * 1000)
return 1; return 1;
if (lpfc_sli_handle_mb_event(phba) == 0) /*
i = 0; * Call lpfc_sli_handle_mb_event only if a mailbox cmd
* did finish. This way we won't get the misleading
* "Stray Mailbox Interrupt" message.
*/
spin_lock_irq(&phba->hbalock);
ha_copy = phba->work_ha;
phba->work_ha &= ~HA_MBATT;
spin_unlock_irq(&phba->hbalock);
if (ha_copy & HA_MBATT)
if (lpfc_sli_handle_mb_event(phba) == 0)
i = 0;
msleep(1); msleep(1);
} }
......
...@@ -138,6 +138,8 @@ struct lpfc_sli_ring { ...@@ -138,6 +138,8 @@ struct lpfc_sli_ring {
uint8_t ringno; /* ring number */ uint8_t ringno; /* ring number */
uint16_t numCiocb; /* number of command iocb's per ring */ uint16_t numCiocb; /* number of command iocb's per ring */
uint16_t numRiocb; /* number of rsp iocb's per ring */ uint16_t numRiocb; /* number of rsp iocb's per ring */
uint16_t sizeCiocb; /* Size of command iocb's in this ring */
uint16_t sizeRiocb; /* Size of response iocb's in this ring */
uint32_t fast_iotag; /* max fastlookup based iotag */ uint32_t fast_iotag; /* max fastlookup based iotag */
uint32_t iotag_ctr; /* keeps track of the next iotag to use */ uint32_t iotag_ctr; /* keeps track of the next iotag to use */
...@@ -168,6 +170,29 @@ struct lpfc_sli_ring { ...@@ -168,6 +170,29 @@ struct lpfc_sli_ring {
struct lpfc_sli_ring *); struct lpfc_sli_ring *);
}; };
/* Structure used for configuring rings to a specific profile or rctl / type */
struct lpfc_hbq_init {
uint32_t rn; /* Receive buffer notification */
uint32_t entry_count; /* # of entries in HBQ */
uint32_t headerLen; /* 0 if not profile 4 or 5 */
uint32_t logEntry; /* Set to 1 if this HBQ used for LogEntry */
uint32_t profile; /* Selection profile 0=all, 7=logentry */
uint32_t ring_mask; /* Binds HBQ to a ring e.g. Ring0=b0001,
* ring2=b0100 */
uint32_t hbq_index; /* index of this hbq in ring .HBQs[] */
uint32_t seqlenoff;
uint32_t maxlen;
uint32_t seqlenbcnt;
uint32_t cmdcodeoff;
uint32_t cmdmatch[8];
uint32_t mask_count; /* number of mask entries in prt array */
struct hbq_mask hbqMasks[6];
} ;
#define LPFC_MAX_HBQ 16
/* Structure used to hold SLI statistical counters and info */ /* Structure used to hold SLI statistical counters and info */
struct lpfc_sli_stat { struct lpfc_sli_stat {
uint64_t mbox_stat_err; /* Mbox cmds completed status error */ uint64_t mbox_stat_err; /* Mbox cmds completed status error */
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* included with this package. * * included with this package. *
*******************************************************************/ *******************************************************************/
#define LPFC_DRIVER_VERSION "8.1.12_psplit" #define LPFC_DRIVER_VERSION "8.1.12_sli3"
#define LPFC_DRIVER_NAME "lpfc" #define LPFC_DRIVER_NAME "lpfc"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment