diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-11-29 09:51:07 (GMT) |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-11-29 09:51:07 (GMT) |
commit | 0d2cd91bf7b1a7cc1d638296111fcc2bcf5c0bb4 (patch) | |
tree | d2ca69347816c27f9dc352581f5d0fe76811cd49 /drivers/scsi/lpfc | |
parent | 3d95fd6ad8d3cf582a70ed65660017114b6e4065 (diff) | |
parent | caca6a03d365883564885f2c1da3e88dcf65d139 (diff) | |
download | linux-0d2cd91bf7b1a7cc1d638296111fcc2bcf5c0bb4.tar.xz |
Merge commit 'v3.2-rc3' into next
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 20 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 80 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 182 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 33 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 300 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 288 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_logmsg.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 80 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 245 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 460 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 18 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 23 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_version.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 16 |
17 files changed, 1416 insertions, 346 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index c088a36..bb4c8e0 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -846,8 +846,24 @@ struct lpfc_hba { struct dentry *debug_hbqinfo; struct dentry *debug_dumpHostSlim; struct dentry *debug_dumpHBASlim; - struct dentry *debug_dumpData; /* BlockGuard BPL*/ - struct dentry *debug_dumpDif; /* BlockGuard BPL*/ + struct dentry *debug_dumpData; /* BlockGuard BPL */ + struct dentry *debug_dumpDif; /* BlockGuard BPL */ + struct dentry *debug_InjErrLBA; /* LBA to inject errors at */ + struct dentry *debug_writeGuard; /* inject write guard_tag errors */ + struct dentry *debug_writeApp; /* inject write app_tag errors */ + struct dentry *debug_writeRef; /* inject write ref_tag errors */ + struct dentry *debug_readApp; /* inject read app_tag errors */ + struct dentry *debug_readRef; /* inject read ref_tag errors */ + + /* T10 DIF error injection */ + uint32_t lpfc_injerr_wgrd_cnt; + uint32_t lpfc_injerr_wapp_cnt; + uint32_t lpfc_injerr_wref_cnt; + uint32_t lpfc_injerr_rapp_cnt; + uint32_t lpfc_injerr_rref_cnt; + sector_t lpfc_injerr_lba; +#define LPFC_INJERR_LBA_OFF (sector_t)0xffffffffffffffff + struct dentry *debug_slow_ring_trc; struct lpfc_debugfs_trc *slow_ring_trc; atomic_t slow_ring_trc_cnt; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 2542f1f..d0ebaeb 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -23,6 +23,7 @@ #include <linux/delay.h> #include <linux/pci.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <linux/aer.h> #include <linux/gfp.h> #include <linux/kernel.h> @@ -52,6 +53,13 @@ #define LPFC_MIN_DEVLOSS_TMO 1 #define LPFC_MAX_DEVLOSS_TMO 255 +/* + * Write key size should be multiple of 4. If write key is changed + * make sure that library write key is also changed. + */ +#define LPFC_REG_WRITE_KEY_SIZE 4 +#define LPFC_REG_WRITE_KEY "EMLX" + /** * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules * @incr: integer to convert. @@ -693,7 +701,7 @@ lpfc_selective_reset(struct lpfc_hba *phba) int rc; if (!phba->cfg_enable_hba_reset) - return -EIO; + return -EACCES; status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); @@ -742,9 +750,11 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr, struct Scsi_Host *shost = class_to_shost(dev); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; - int status = -EINVAL; + if (!phba->cfg_enable_hba_reset) + return -EACCES; + if (strncmp(buf, "selective", sizeof("selective") - 1) == 0) status = phba->lpfc_selective_reset(phba); @@ -765,16 +775,21 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr, * Returns: * zero for success **/ -static int +int lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba) { - struct lpfc_register portstat_reg; + struct lpfc_register portstat_reg = {0}; int i; - + msleep(100); lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, &portstat_reg.word0); + /* verify if privilaged for the request operation */ + if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) && + !bf_get(lpfc_sliport_status_err, &portstat_reg)) + return -EPERM; + /* wait for the SLI port firmware ready after firmware reset */ for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) { msleep(10); @@ -816,16 +831,13 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) int rc; if (!phba->cfg_enable_hba_reset) - return -EIO; + return -EACCES; if ((phba->sli_rev < LPFC_SLI_REV4) || (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != LPFC_SLI_INTF_IF_TYPE_2)) return -EPERM; - if (!pdev->is_physfn) - return -EPERM; - /* Disable SR-IOV virtual functions if enabled */ if (phba->cfg_sriov_nr_virtfn) { pci_disable_sriov(pdev); @@ -858,7 +870,7 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) rc = lpfc_sli4_pdev_status_reg_wait(phba); if (rc) - return -EIO; + return rc; init_completion(&online_compl); rc = lpfc_workq_post_event(phba, &status, &online_compl, @@ -984,7 +996,7 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, if (!status) return strlen(buf); else - return -EIO; + return status; } /** @@ -3885,18 +3897,23 @@ sysfs_ctlreg_write(struct file *filp, struct kobject *kobj, if ((off + count) > FF_REG_AREA_SIZE) return -ERANGE; - if (count == 0) return 0; + if (count <= LPFC_REG_WRITE_KEY_SIZE) + return 0; if (off % 4 || count % 4 || (unsigned long)buf % 4) return -EINVAL; - if (!(vport->fc_flag & FC_OFFLINE_MODE)) { + /* This is to protect HBA registers from accidental writes. */ + if (memcmp(buf, LPFC_REG_WRITE_KEY, LPFC_REG_WRITE_KEY_SIZE)) + return -EINVAL; + + if (!(vport->fc_flag & FC_OFFLINE_MODE)) return -EPERM; - } spin_lock_irq(&phba->hbalock); - for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) - writel(*((uint32_t *)(buf + buf_off)), + for (buf_off = 0; buf_off < count - LPFC_REG_WRITE_KEY_SIZE; + buf_off += sizeof(uint32_t)) + writel(*((uint32_t *)(buf + buf_off + LPFC_REG_WRITE_KEY_SIZE)), phba->ctrl_regs_memmap_p + off + buf_off); spin_unlock_irq(&phba->hbalock); @@ -4097,8 +4114,10 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj, struct Scsi_Host *shost = class_to_shost(dev); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; - int rc; + LPFC_MBOXQ_t *mboxq; MAILBOX_t *pmb; + uint32_t mbox_tmo; + int rc; if (off > MAILBOX_CMD_SIZE) return -ERANGE; @@ -4123,7 +4142,8 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj, if (off == 0 && phba->sysfs_mbox.state == SMBOX_WRITING && phba->sysfs_mbox.offset >= 2 * sizeof(uint32_t)) { - pmb = &phba->sysfs_mbox.mbox->u.mb; + mboxq = (LPFC_MBOXQ_t *)&phba->sysfs_mbox.mbox; + pmb = &mboxq->u.mb; switch (pmb->mbxCommand) { /* Offline only */ case MBX_INIT_LINK: @@ -4233,9 +4253,8 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj, } else { spin_unlock_irq(&phba->hbalock); - rc = lpfc_sli_issue_mbox_wait (phba, - phba->sysfs_mbox.mbox, - lpfc_mbox_tmo_val(phba, pmb->mbxCommand) * HZ); + mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq); + rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); spin_lock_irq(&phba->hbalock); } @@ -4480,9 +4499,10 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost) spin_lock_irq(shost->host_lock); - if ((vport->fc_flag & FC_FABRIC) || - ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && - (vport->fc_flag & FC_PUBLIC_LOOP))) + if ((vport->port_state > LPFC_FLOGI) && + ((vport->fc_flag & FC_FABRIC) || + ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && + (vport->fc_flag & FC_PUBLIC_LOOP)))) node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn); else /* fabric is local port if there is no F/FL_Port */ @@ -4555,9 +4575,17 @@ lpfc_get_stats(struct Scsi_Host *shost) memset(hs, 0, sizeof (struct fc_host_statistics)); hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt; - hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256); + /* + * The MBX_READ_STATUS returns tx_k_bytes which has to + * converted to words + */ + hs->tx_words = (uint64_t) + ((uint64_t)pmb->un.varRdStatus.xmitByteCnt + * (uint64_t)256); hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt; - hs->rx_words = (pmb->un.varRdStatus.rcvByteCnt * 256); + hs->rx_words = (uint64_t) + ((uint64_t)pmb->un.varRdStatus.rcvByteCnt + * (uint64_t)256); memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t)); pmb->mbxCommand = MBX_READ_LNK_STAT; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index a6db6ae..60f9534 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -209,7 +209,7 @@ void __lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_mbox_cmd_check(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_mbox_dev_check(struct lpfc_hba *); -int lpfc_mbox_tmo_val(struct lpfc_hba *, int); +int lpfc_mbox_tmo_val(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_init_vfi(struct lpfcMboxq *, struct lpfc_vport *); void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t); void lpfc_init_vpi(struct lpfc_hba *, struct lpfcMboxq *, uint16_t); @@ -451,3 +451,5 @@ int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *); /* functions to support SR-IOV */ int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); uint16_t lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *); +int lpfc_sli4_queue_create(struct lpfc_hba *); +void lpfc_sli4_queue_destroy(struct lpfc_hba *); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 779b88e..707081d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1856,6 +1856,9 @@ lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag) case 2: c = 'B'; break; + case 3: + c = 'X'; + break; default: c = 0; break; diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index a0424dd..2838259 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -20,6 +20,7 @@ #include <linux/blkdev.h> #include <linux/delay.h> +#include <linux/module.h> #include <linux/dma-mapping.h> #include <linux/idr.h> #include <linux/interrupt.h> @@ -996,6 +997,85 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf, return nbytes; } +static int +lpfc_debugfs_dif_err_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t +lpfc_debugfs_dif_err_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + struct dentry *dent = file->f_dentry; + struct lpfc_hba *phba = file->private_data; + char cbuf[16]; + int cnt = 0; + + if (dent == phba->debug_writeGuard) + cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wgrd_cnt); + else if (dent == phba->debug_writeApp) + cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wapp_cnt); + else if (dent == phba->debug_writeRef) + cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wref_cnt); + else if (dent == phba->debug_readApp) + cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rapp_cnt); + else if (dent == phba->debug_readRef) + cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rref_cnt); + else if (dent == phba->debug_InjErrLBA) + cnt = snprintf(cbuf, 16, "0x%lx\n", + (unsigned long) phba->lpfc_injerr_lba); + else + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0547 Unknown debugfs error injection entry\n"); + + return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt); +} + +static ssize_t +lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf, + size_t nbytes, loff_t *ppos) +{ + struct dentry *dent = file->f_dentry; + struct lpfc_hba *phba = file->private_data; + char dstbuf[32]; + unsigned long tmp; + int size; + + memset(dstbuf, 0, 32); + size = (nbytes < 32) ? nbytes : 32; + if (copy_from_user(dstbuf, buf, size)) + return 0; + + if (strict_strtoul(dstbuf, 0, &tmp)) + return 0; + + if (dent == phba->debug_writeGuard) + phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp; + else if (dent == phba->debug_writeApp) + phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp; + else if (dent == phba->debug_writeRef) + phba->lpfc_injerr_wref_cnt = (uint32_t)tmp; + else if (dent == phba->debug_readApp) + phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp; + else if (dent == phba->debug_readRef) + phba->lpfc_injerr_rref_cnt = (uint32_t)tmp; + else if (dent == phba->debug_InjErrLBA) + phba->lpfc_injerr_lba = (sector_t)tmp; + else + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0548 Unknown debugfs error injection entry\n"); + + return nbytes; +} + +static int +lpfc_debugfs_dif_err_release(struct inode *inode, struct file *file) +{ + return 0; +} + /** * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file * @inode: The inode pointer that contains a vport pointer. @@ -3380,6 +3460,16 @@ static const struct file_operations lpfc_debugfs_op_dumpDif = { .release = lpfc_debugfs_dumpDataDif_release, }; +#undef lpfc_debugfs_op_dif_err +static const struct file_operations lpfc_debugfs_op_dif_err = { + .owner = THIS_MODULE, + .open = lpfc_debugfs_dif_err_open, + .llseek = lpfc_debugfs_lseek, + .read = lpfc_debugfs_dif_err_read, + .write = lpfc_debugfs_dif_err_write, + .release = lpfc_debugfs_dif_err_release, +}; + #undef lpfc_debugfs_op_slow_ring_trc static const struct file_operations lpfc_debugfs_op_slow_ring_trc = { .owner = THIS_MODULE, @@ -3788,6 +3878,74 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) goto debug_failed; } + /* Setup DIF Error Injections */ + snprintf(name, sizeof(name), "InjErrLBA"); + phba->debug_InjErrLBA = + debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, + phba->hba_debugfs_root, + phba, &lpfc_debugfs_op_dif_err); + if (!phba->debug_InjErrLBA) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0807 Cannot create debugfs InjErrLBA\n"); + goto debug_failed; + } + phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF; + + snprintf(name, sizeof(name), "writeGuardInjErr"); + phba->debug_writeGuard = + debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, + phba->hba_debugfs_root, + phba, &lpfc_debugfs_op_dif_err); + if (!phba->debug_writeGuard) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0802 Cannot create debugfs writeGuard\n"); + goto debug_failed; + } + + snprintf(name, sizeof(name), "writeAppInjErr"); + phba->debug_writeApp = + debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, + phba->hba_debugfs_root, + phba, &lpfc_debugfs_op_dif_err); + if (!phba->debug_writeApp) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0803 Cannot create debugfs writeApp\n"); + goto debug_failed; + } + + snprintf(name, sizeof(name), "writeRefInjErr"); + phba->debug_writeRef = + debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, + phba->hba_debugfs_root, + phba, &lpfc_debugfs_op_dif_err); + if (!phba->debug_writeRef) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0804 Cannot create debugfs writeRef\n"); + goto debug_failed; + } + + snprintf(name, sizeof(name), "readAppInjErr"); + phba->debug_readApp = + debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, + phba->hba_debugfs_root, + phba, &lpfc_debugfs_op_dif_err); + if (!phba->debug_readApp) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0805 Cannot create debugfs readApp\n"); + goto debug_failed; + } + + snprintf(name, sizeof(name), "readRefInjErr"); + phba->debug_readRef = + debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, + phba->hba_debugfs_root, + phba, &lpfc_debugfs_op_dif_err); + if (!phba->debug_readRef) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0806 Cannot create debugfs readApp\n"); + goto debug_failed; + } + /* Setup slow ring trace */ if (lpfc_debugfs_max_slow_ring_trc) { num = lpfc_debugfs_max_slow_ring_trc - 1; @@ -4090,6 +4248,30 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) debugfs_remove(phba->debug_dumpDif); /* dumpDif */ phba->debug_dumpDif = NULL; } + if (phba->debug_InjErrLBA) { + debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */ + phba->debug_InjErrLBA = NULL; + } + if (phba->debug_writeGuard) { + debugfs_remove(phba->debug_writeGuard); /* writeGuard */ + phba->debug_writeGuard = NULL; + } + if (phba->debug_writeApp) { + debugfs_remove(phba->debug_writeApp); /* writeApp */ + phba->debug_writeApp = NULL; + } + if (phba->debug_writeRef) { + debugfs_remove(phba->debug_writeRef); /* writeRef */ + phba->debug_writeRef = NULL; + } + if (phba->debug_readApp) { + debugfs_remove(phba->debug_readApp); /* readApp */ + phba->debug_readApp = NULL; + } + if (phba->debug_readRef) { + debugfs_remove(phba->debug_readRef); /* readRef */ + phba->debug_readRef = NULL; + } if (phba->slow_ring_trc) { kfree(phba->slow_ring_trc); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 023da0e..445826a 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -3386,7 +3386,14 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, cmdiocb->context1 = NULL; } } + + /* + * The driver received a LOGO from the rport and has ACK'd it. + * At this point, the driver is done so release the IOCB and + * remove the ndlp reference. + */ lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); return; } @@ -4082,9 +4089,6 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, phba->fc_stat.elsXmitACC++; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; - lpfc_nlp_put(ndlp); - elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, - * it could be freed */ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); if (rc == IOCB_ERROR) { @@ -4166,6 +4170,11 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data, psli = &phba->sli; cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len; + /* The accumulated length can exceed the BPL_SIZE. For + * now, use this as the limit + */ + if (cmdsize > LPFC_BPL_SIZE) + cmdsize = LPFC_BPL_SIZE; elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, ndlp->nlp_DID, ELS_CMD_ACC); if (!elsiocb) @@ -4189,9 +4198,6 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data, phba->fc_stat.elsXmitACC++; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; - lpfc_nlp_put(ndlp); - elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, - * it could be freed */ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); if (rc == IOCB_ERROR) { @@ -7258,16 +7264,11 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, icmd->un.elsreq64.myID = 0; icmd->un.elsreq64.fl = 1; - if ((phba->sli_rev == LPFC_SLI_REV4) && - (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == - LPFC_SLI_INTF_IF_TYPE_0)) { - /* FDISC needs to be 1 for WQE VPI */ - elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1; - elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ; - /* Set the ulpContext to the vpi */ - elsiocb->iocb.ulpContext = phba->vpi_ids[vport->vpi]; - } else { - /* For FDISC, Let FDISC rsp set the NPortID for this VPI */ + /* + * SLI3 ports require a different context type value than SLI4. + * Catch SLI3 ports here and override the prep. + */ + if (phba->sli_rev == LPFC_SLI_REV3) { icmd->ulpCt_h = 1; icmd->ulpCt_l = 0; } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 0b47adf..091f68e 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1412,7 +1412,7 @@ lpfc_register_fcf(struct lpfc_hba *phba) if (phba->pport->port_state != LPFC_FLOGI) { phba->hba_flag |= FCF_RR_INPROG; spin_unlock_irq(&phba->hbalock); - lpfc_issue_init_vfi(phba->pport); + lpfc_initial_flogi(phba->pport); return; } spin_unlock_irq(&phba->hbalock); @@ -2646,7 +2646,9 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { struct lpfc_vport *vport = mboxq->vport; - if (mboxq->u.mb.mbxStatus && (mboxq->u.mb.mbxStatus != 0x4002)) { + /* VFI not supported on interface type 0, just do the flogi */ + if (mboxq->u.mb.mbxStatus && (bf_get(lpfc_sli_intf_if_type, + &phba->sli4_hba.sli_intf) != LPFC_SLI_INTF_IF_TYPE_0)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, "2891 Init VFI mailbox failed 0x%x\n", @@ -2655,6 +2657,7 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) lpfc_vport_set_state(vport, FC_VPORT_FAILED); return; } + lpfc_initial_flogi(vport); mempool_free(mboxq, phba->mbox_mem_pool); return; diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 7f8003b..98d2152 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -41,6 +41,8 @@ * Or clear that bit field: * bf_set(example_bit_field, &t1, 0); */ +#define bf_get_be32(name, ptr) \ + ((be32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK) #define bf_get_le32(name, ptr) \ ((le32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK) #define bf_get(name, ptr) \ @@ -678,7 +680,6 @@ struct lpfc_register { #define lpfc_rq_doorbell_num_posted_SHIFT 16 #define lpfc_rq_doorbell_num_posted_MASK 0x3FFF #define lpfc_rq_doorbell_num_posted_WORD word0 -#define LPFC_RQ_POST_BATCH 8 /* RQEs to post at one time */ #define lpfc_rq_doorbell_id_SHIFT 0 #define lpfc_rq_doorbell_id_MASK 0xFFFF #define lpfc_rq_doorbell_id_WORD word0 @@ -784,6 +785,8 @@ union lpfc_sli4_cfg_shdr { #define LPFC_Q_CREATE_VERSION_2 2 #define LPFC_Q_CREATE_VERSION_1 1 #define LPFC_Q_CREATE_VERSION_0 0 +#define LPFC_OPCODE_VERSION_0 0 +#define LPFC_OPCODE_VERSION_1 1 } request; struct { uint32_t word6; @@ -825,6 +828,7 @@ struct mbox_header { #define LPFC_EXTENT_VERSION_DEFAULT 0 /* Subsystem Definitions */ +#define LPFC_MBOX_SUBSYSTEM_NA 0x0 #define LPFC_MBOX_SUBSYSTEM_COMMON 0x1 #define LPFC_MBOX_SUBSYSTEM_FCOE 0xC @@ -835,25 +839,34 @@ struct mbox_header { #define HOST_ENDIAN_HIGH_WORD1 0xFF7856FF /* Common Opcodes */ -#define LPFC_MBOX_OPCODE_CQ_CREATE 0x0C -#define LPFC_MBOX_OPCODE_EQ_CREATE 0x0D -#define LPFC_MBOX_OPCODE_MQ_CREATE 0x15 -#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES 0x20 -#define LPFC_MBOX_OPCODE_NOP 0x21 -#define LPFC_MBOX_OPCODE_MQ_DESTROY 0x35 -#define LPFC_MBOX_OPCODE_CQ_DESTROY 0x36 -#define LPFC_MBOX_OPCODE_EQ_DESTROY 0x37 -#define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A -#define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D -#define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A -#define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A -#define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B -#define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT 0x9C -#define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT 0x9D -#define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0 -#define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4 -#define LPFC_MBOX_OPCODE_WRITE_OBJECT 0xAC -#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5 +#define LPFC_MBOX_OPCODE_NA 0x00 +#define LPFC_MBOX_OPCODE_CQ_CREATE 0x0C +#define LPFC_MBOX_OPCODE_EQ_CREATE 0x0D +#define LPFC_MBOX_OPCODE_MQ_CREATE 0x15 +#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES 0x20 +#define LPFC_MBOX_OPCODE_NOP 0x21 +#define LPFC_MBOX_OPCODE_MQ_DESTROY 0x35 +#define LPFC_MBOX_OPCODE_CQ_DESTROY 0x36 +#define LPFC_MBOX_OPCODE_EQ_DESTROY 0x37 +#define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A +#define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D +#define LPFC_MBOX_OPCODE_GET_PORT_NAME 0x4D +#define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A +#define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A +#define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B +#define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT 0x9C +#define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT 0x9D +#define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0 +#define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4 +#define LPFC_MBOX_OPCODE_SET_PROFILE_CONFIG 0xA5 +#define LPFC_MBOX_OPCODE_GET_PROFILE_LIST 0xA6 +#define LPFC_MBOX_OPCODE_SET_ACT_PROFILE 0xA8 +#define LPFC_MBOX_OPCODE_GET_FACTORY_PROFILE_CONFIG 0xA9 +#define LPFC_MBOX_OPCODE_READ_OBJECT 0xAB +#define LPFC_MBOX_OPCODE_WRITE_OBJECT 0xAC +#define LPFC_MBOX_OPCODE_READ_OBJECT_LIST 0xAD +#define LPFC_MBOX_OPCODE_DELETE_OBJECT 0xAE +#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5 /* FCoE Opcodes */ #define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE 0x01 @@ -867,6 +880,7 @@ struct mbox_header { #define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF 0x0A #define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE 0x0B #define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF 0x10 +#define LPFC_MBOX_OPCODE_FCOE_SET_FCLINK_SETTINGS 0x21 #define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE 0x22 #define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK 0x23 @@ -1470,16 +1484,81 @@ struct sli4_sge { /* SLI-4 */ uint32_t addr_lo; uint32_t word2; -#define lpfc_sli4_sge_offset_SHIFT 0 /* Offset of buffer - Not used*/ -#define lpfc_sli4_sge_offset_MASK 0x1FFFFFFF +#define lpfc_sli4_sge_offset_SHIFT 0 +#define lpfc_sli4_sge_offset_MASK 0x07FFFFFF #define lpfc_sli4_sge_offset_WORD word2 -#define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets - this flag !! */ +#define lpfc_sli4_sge_type_SHIFT 27 +#define lpfc_sli4_sge_type_MASK 0x0000000F +#define lpfc_sli4_sge_type_WORD word2 +#define LPFC_SGE_TYPE_DATA 0x0 +#define LPFC_SGE_TYPE_DIF 0x4 +#define LPFC_SGE_TYPE_LSP 0x5 +#define LPFC_SGE_TYPE_PEDIF 0x6 +#define LPFC_SGE_TYPE_PESEED 0x7 +#define LPFC_SGE_TYPE_DISEED 0x8 +#define LPFC_SGE_TYPE_ENC 0x9 +#define LPFC_SGE_TYPE_ATM 0xA +#define LPFC_SGE_TYPE_SKIP 0xC +#define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets it */ #define lpfc_sli4_sge_last_MASK 0x00000001 #define lpfc_sli4_sge_last_WORD word2 uint32_t sge_len; }; +struct sli4_sge_diseed { /* SLI-4 */ + uint32_t ref_tag; + uint32_t ref_tag_tran; + + uint32_t word2; +#define lpfc_sli4_sge_dif_apptran_SHIFT 0 +#define lpfc_sli4_sge_dif_apptran_MASK 0x0000FFFF +#define lpfc_sli4_sge_dif_apptran_WORD word2 +#define lpfc_sli4_sge_dif_af_SHIFT 24 +#define lpfc_sli4_sge_dif_af_MASK 0x00000001 +#define lpfc_sli4_sge_dif_af_WORD word2 +#define lpfc_sli4_sge_dif_na_SHIFT 25 +#define lpfc_sli4_sge_dif_na_MASK 0x00000001 +#define lpfc_sli4_sge_dif_na_WORD word2 +#define lpfc_sli4_sge_dif_hi_SHIFT 26 +#define lpfc_sli4_sge_dif_hi_MASK 0x00000001 +#define lpfc_sli4_sge_dif_hi_WORD word2 +#define lpfc_sli4_sge_dif_type_SHIFT 27 +#define lpfc_sli4_sge_dif_type_MASK 0x0000000F +#define lpfc_sli4_sge_dif_type_WORD word2 +#define lpfc_sli4_sge_dif_last_SHIFT 31 /* Last SEG in the SGL sets it */ +#define lpfc_sli4_sge_dif_last_MASK 0x00000001 +#define lpfc_sli4_sge_dif_last_WORD word2 + uint32_t word3; +#define lpfc_sli4_sge_dif_apptag_SHIFT 0 +#define lpfc_sli4_sge_dif_apptag_MASK 0x0000FFFF +#define lpfc_sli4_sge_dif_apptag_WORD word3 +#define lpfc_sli4_sge_dif_bs_SHIFT 16 +#define lpfc_sli4_sge_dif_bs_MASK 0x00000007 +#define lpfc_sli4_sge_dif_bs_WORD word3 +#define lpfc_sli4_sge_dif_ai_SHIFT 19 +#define lpfc_sli4_sge_dif_ai_MASK 0x00000001 +#define lpfc_sli4_sge_dif_ai_WORD word3 +#define lpfc_sli4_sge_dif_me_SHIFT 20 +#define lpfc_sli4_sge_dif_me_MASK 0x00000001 +#define lpfc_sli4_sge_dif_me_WORD word3 +#define lpfc_sli4_sge_dif_re_SHIFT 21 +#define lpfc_sli4_sge_dif_re_MASK 0x00000001 +#define lpfc_sli4_sge_dif_re_WORD word3 +#define lpfc_sli4_sge_dif_ce_SHIFT 22 +#define lpfc_sli4_sge_dif_ce_MASK 0x00000001 +#define lpfc_sli4_sge_dif_ce_WORD word3 +#define lpfc_sli4_sge_dif_nr_SHIFT 23 +#define lpfc_sli4_sge_dif_nr_MASK 0x00000001 +#define lpfc_sli4_sge_dif_nr_WORD word3 +#define lpfc_sli4_sge_dif_oprx_SHIFT 24 +#define lpfc_sli4_sge_dif_oprx_MASK 0x0000000F +#define lpfc_sli4_sge_dif_oprx_WORD word3 +#define lpfc_sli4_sge_dif_optx_SHIFT 28 +#define lpfc_sli4_sge_dif_optx_MASK 0x0000000F +#define lpfc_sli4_sge_dif_optx_WORD word3 +/* optx and oprx use BG_OP_IN defines in lpfc_hw.h */ +}; + struct fcf_record { uint32_t max_rcv_size; uint32_t fka_adv_period; @@ -2019,6 +2098,15 @@ struct lpfc_mbx_read_config { #define lpfc_mbx_rd_conf_extnts_inuse_MASK 0x00000001 #define lpfc_mbx_rd_conf_extnts_inuse_WORD word1 uint32_t word2; +#define lpfc_mbx_rd_conf_lnk_numb_SHIFT 0 +#define lpfc_mbx_rd_conf_lnk_numb_MASK 0x0000003F +#define lpfc_mbx_rd_conf_lnk_numb_WORD word2 +#define lpfc_mbx_rd_conf_lnk_type_SHIFT 6 +#define lpfc_mbx_rd_conf_lnk_type_MASK 0x00000003 +#define lpfc_mbx_rd_conf_lnk_type_WORD word2 +#define lpfc_mbx_rd_conf_lnk_ldv_SHIFT 8 +#define lpfc_mbx_rd_conf_lnk_ldv_MASK 0x00000001 +#define lpfc_mbx_rd_conf_lnk_ldv_WORD word2 #define lpfc_mbx_rd_conf_topology_SHIFT 24 #define lpfc_mbx_rd_conf_topology_MASK 0x000000FF #define lpfc_mbx_rd_conf_topology_WORD word2 @@ -2552,8 +2640,152 @@ struct lpfc_mbx_get_prof_cfg { } u; }; +struct lpfc_controller_attribute { + uint32_t version_string[8]; + uint32_t manufacturer_name[8]; + uint32_t supported_modes; + uint32_t word17; +#define lpfc_cntl_attr_eprom_ver_lo_SHIFT 0 +#define lpfc_cntl_attr_eprom_ver_lo_MASK 0x000000ff +#define lpfc_cntl_attr_eprom_ver_lo_WORD word17 +#define lpfc_cntl_attr_eprom_ver_hi_SHIFT 8 +#define lpfc_cntl_attr_eprom_ver_hi_MASK 0x000000ff +#define lpfc_cntl_attr_eprom_ver_hi_WORD word17 + uint32_t mbx_da_struct_ver; + uint32_t ep_fw_da_struct_ver; + uint32_t ncsi_ver_str[3]; + uint32_t dflt_ext_timeout; + uint32_t model_number[8]; + uint32_t description[16]; + uint32_t serial_number[8]; + uint32_t ip_ver_str[8]; + uint32_t fw_ver_str[8]; + uint32_t bios_ver_str[8]; + uint32_t redboot_ver_str[8]; + uint32_t driver_ver_str[8]; + uint32_t flash_fw_ver_str[8]; + uint32_t functionality; + uint32_t word105; +#define lpfc_cntl_attr_max_cbd_len_SHIFT 0 +#define lpfc_cntl_attr_max_cbd_len_MASK 0x0000ffff +#define lpfc_cntl_attr_max_cbd_len_WORD word105 +#define lpfc_cntl_attr_asic_rev_SHIFT 16 +#define lpfc_cntl_attr_asic_rev_MASK 0x000000ff +#define lpfc_cntl_attr_asic_rev_WORD word105 +#define lpfc_cntl_attr_gen_guid0_SHIFT 24 +#define lpfc_cntl_attr_gen_guid0_MASK 0x000000ff +#define lpfc_cntl_attr_gen_guid0_WORD word105 + uint32_t gen_guid1_12[3]; + uint32_t word109; +#define lpfc_cntl_attr_gen_guid13_14_SHIFT 0 +#define lpfc_cntl_attr_gen_guid13_14_MASK 0x0000ffff +#define lpfc_cntl_attr_gen_guid13_14_WORD word109 +#define lpfc_cntl_attr_gen_guid15_SHIFT 16 +#define lpfc_cntl_attr_gen_guid15_MASK 0x000000ff +#define lpfc_cntl_attr_gen_guid15_WORD word109 +#define lpfc_cntl_attr_hba_port_cnt_SHIFT 24 +#define lpfc_cntl_attr_hba_port_cnt_MASK 0x000000ff +#define lpfc_cntl_attr_hba_port_cnt_WORD word109 + uint32_t word110; +#define lpfc_cntl_attr_dflt_lnk_tmo_SHIFT 0 +#define lpfc_cntl_attr_dflt_lnk_tmo_MASK 0x0000ffff +#define lpfc_cntl_attr_dflt_lnk_tmo_WORD word110 +#define lpfc_cntl_attr_multi_func_dev_SHIFT 24 +#define lpfc_cntl_attr_multi_func_dev_MASK 0x000000ff +#define lpfc_cntl_attr_multi_func_dev_WORD word110 + uint32_t word111; +#define lpfc_cntl_attr_cache_valid_SHIFT 0 +#define lpfc_cntl_attr_cache_valid_MASK 0x000000ff +#define lpfc_cntl_attr_cache_valid_WORD word111 +#define lpfc_cntl_attr_hba_status_SHIFT 8 +#define lpfc_cntl_attr_hba_status_MASK 0x000000ff +#define lpfc_cntl_attr_hba_status_WORD word111 +#define lpfc_cntl_attr_max_domain_SHIFT 16 +#define lpfc_cntl_attr_max_domain_MASK 0x000000ff +#define lpfc_cntl_attr_max_domain_WORD word111 +#define lpfc_cntl_attr_lnk_numb_SHIFT 24 +#define lpfc_cntl_attr_lnk_numb_MASK 0x0000003f +#define lpfc_cntl_attr_lnk_numb_WORD word111 +#define lpfc_cntl_attr_lnk_type_SHIFT 30 +#define lpfc_cntl_attr_lnk_type_MASK 0x00000003 +#define lpfc_cntl_attr_lnk_type_WORD word111 + uint32_t fw_post_status; + uint32_t hba_mtu[8]; + uint32_t word121; + uint32_t reserved1[3]; + uint32_t word125; +#define lpfc_cntl_attr_pci_vendor_id_SHIFT 0 +#define lpfc_cntl_attr_pci_vendor_id_MASK 0x0000ffff +#define lpfc_cntl_attr_pci_vendor_id_WORD word125 +#define lpfc_cntl_attr_pci_device_id_SHIFT 16 +#define lpfc_cntl_attr_pci_device_id_MASK 0x0000ffff +#define lpfc_cntl_attr_pci_device_id_WORD word125 + uint32_t word126; +#define lpfc_cntl_attr_pci_subvdr_id_SHIFT 0 +#define lpfc_cntl_attr_pci_subvdr_id_MASK 0x0000ffff +#define lpfc_cntl_attr_pci_subvdr_id_WORD word126 +#define lpfc_cntl_attr_pci_subsys_id_SHIFT 16 +#define lpfc_cntl_attr_pci_subsys_id_MASK 0x0000ffff +#define lpfc_cntl_attr_pci_subsys_id_WORD word126 + uint32_t word127; +#define lpfc_cntl_attr_pci_bus_num_SHIFT 0 +#define lpfc_cntl_attr_pci_bus_num_MASK 0x000000ff +#define lpfc_cntl_attr_pci_bus_num_WORD word127 +#define lpfc_cntl_attr_pci_dev_num_SHIFT 8 +#define lpfc_cntl_attr_pci_dev_num_MASK 0x000000ff +#define lpfc_cntl_attr_pci_dev_num_WORD word127 +#define lpfc_cntl_attr_pci_fnc_num_SHIFT 16 +#define lpfc_cntl_attr_pci_fnc_num_MASK 0x000000ff +#define lpfc_cntl_attr_pci_fnc_num_WORD word127 +#define lpfc_cntl_attr_inf_type_SHIFT 24 +#define lpfc_cntl_attr_inf_type_MASK 0x000000ff +#define lpfc_cntl_attr_inf_type_WORD word127 + uint32_t unique_id[2]; + uint32_t word130; +#define lpfc_cntl_attr_num_netfil_SHIFT 0 +#define lpfc_cntl_attr_num_netfil_MASK 0x000000ff +#define lpfc_cntl_attr_num_netfil_WORD word130 + uint32_t reserved2[4]; +}; + +struct lpfc_mbx_get_cntl_attributes { + union lpfc_sli4_cfg_shdr cfg_shdr; + struct lpfc_controller_attribute cntl_attr; +}; + +struct lpfc_mbx_get_port_name { + struct mbox_header header; + union { + struct { + uint32_t word4; +#define lpfc_mbx_get_port_name_lnk_type_SHIFT 0 +#define lpfc_mbx_get_port_name_lnk_type_MASK 0x00000003 +#define lpfc_mbx_get_port_name_lnk_type_WORD word4 + } request; + struct { + uint32_t word4; +#define lpfc_mbx_get_port_name_name0_SHIFT 0 +#define lpfc_mbx_get_port_name_name0_MASK 0x000000FF +#define lpfc_mbx_get_port_name_name0_WORD word4 +#define lpfc_mbx_get_port_name_name1_SHIFT 8 +#define lpfc_mbx_get_port_name_name1_MASK 0x000000FF +#define lpfc_mbx_get_port_name_name1_WORD word4 +#define lpfc_mbx_get_port_name_name2_SHIFT 16 +#define lpfc_mbx_get_port_name_name2_MASK 0x000000FF +#define lpfc_mbx_get_port_name_name2_WORD word4 +#define lpfc_mbx_get_port_name_name3_SHIFT 24 +#define lpfc_mbx_get_port_name_name3_MASK 0x000000FF +#define lpfc_mbx_get_port_name_name3_WORD word4 +#define LPFC_LINK_NUMBER_0 0 +#define LPFC_LINK_NUMBER_1 1 +#define LPFC_LINK_NUMBER_2 2 +#define LPFC_LINK_NUMBER_3 3 + } response; + } u; +}; + /* Mailbox Completion Queue Error Messages */ -#define MB_CQE_STATUS_SUCCESS 0x0 +#define MB_CQE_STATUS_SUCCESS 0x0 #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1 #define MB_CQE_STATUS_INVALID_PARAMETER 0x2 #define MB_CQE_STATUS_INSUFFICIENT_RESOURCES 0x3 @@ -2637,8 +2869,9 @@ struct lpfc_mqe { struct lpfc_mbx_run_link_diag_test link_diag_test; struct lpfc_mbx_get_func_cfg get_func_cfg; struct lpfc_mbx_get_prof_cfg get_prof_cfg; - struct lpfc_mbx_nop nop; struct lpfc_mbx_wr_object wr_object; + struct lpfc_mbx_get_port_name get_port_name; + struct lpfc_mbx_nop nop; } un; }; @@ -2855,6 +3088,9 @@ struct wqe_common { #define wqe_ctxt_tag_MASK 0x0000FFFF #define wqe_ctxt_tag_WORD word6 uint32_t word7; +#define wqe_dif_SHIFT 0 +#define wqe_dif_MASK 0x00000003 +#define wqe_dif_WORD word7 #define wqe_ct_SHIFT 2 #define wqe_ct_MASK 0x00000003 #define wqe_ct_WORD word7 @@ -2867,12 +3103,21 @@ struct wqe_common { #define wqe_class_SHIFT 16 #define wqe_class_MASK 0x00000007 #define wqe_class_WORD word7 +#define wqe_ar_SHIFT 19 +#define wqe_ar_MASK 0x00000001 +#define wqe_ar_WORD word7 +#define wqe_ag_SHIFT wqe_ar_SHIFT +#define wqe_ag_MASK wqe_ar_MASK +#define wqe_ag_WORD wqe_ar_WORD #define wqe_pu_SHIFT 20 #define wqe_pu_MASK 0x00000003 #define wqe_pu_WORD word7 #define wqe_erp_SHIFT 22 #define wqe_erp_MASK 0x00000001 #define wqe_erp_WORD word7 +#define wqe_conf_SHIFT wqe_erp_SHIFT +#define wqe_conf_MASK wqe_erp_MASK +#define wqe_conf_WORD wqe_erp_WORD #define wqe_lnk_SHIFT 23 #define wqe_lnk_MASK 0x00000001 #define wqe_lnk_WORD word7 @@ -2931,6 +3176,9 @@ struct wqe_common { #define wqe_xc_SHIFT 21 #define wqe_xc_MASK 0x00000001 #define wqe_xc_WORD word10 +#define wqe_sr_SHIFT 22 +#define wqe_sr_MASK 0x00000001 +#define wqe_sr_WORD word10 #define wqe_ccpe_SHIFT 23 #define wqe_ccpe_MASK 0x00000001 #define wqe_ccpe_WORD word10 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index a3c8200..55bc4fc 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -24,6 +24,7 @@ #include <linux/dma-mapping.h> #include <linux/idr.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <linux/kthread.h> #include <linux/pci.h> #include <linux/spinlock.h> @@ -58,8 +59,7 @@ spinlock_t _dump_buf_lock; static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); static int lpfc_post_rcv_buf(struct lpfc_hba *); -static int lpfc_sli4_queue_create(struct lpfc_hba *); -static void lpfc_sli4_queue_destroy(struct lpfc_hba *); +static int lpfc_sli4_queue_verify(struct lpfc_hba *); static int lpfc_create_bootstrap_mbox(struct lpfc_hba *); static int lpfc_setup_endian_order(struct lpfc_hba *); static int lpfc_sli4_read_config(struct lpfc_hba *); @@ -1438,6 +1438,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) struct Scsi_Host *shost; uint32_t if_type; struct lpfc_register portstat_reg; + int rc; /* If the pci channel is offline, ignore possible errors, since * we cannot communicate with the pci card anyway. @@ -1480,16 +1481,24 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) lpfc_sli4_offline_eratt(phba); return; } - if (bf_get(lpfc_sliport_status_rn, &portstat_reg)) { - /* - * TODO: Attempt port recovery via a port reset. - * When fully implemented, the driver should - * attempt to recover the port here and return. - * For now, log an error and take the port offline. - */ + /* + * On error status condition, driver need to wait for port + * ready before performing reset. + */ + rc = lpfc_sli4_pdev_status_reg_wait(phba); + if (!rc) { + /* need reset: attempt for port recovery */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "2887 Port Error: Attempting " "Port Recovery\n"); + lpfc_offline_prep(phba); + lpfc_offline(phba); + lpfc_sli_brdrestart(phba); + if (lpfc_online(phba) == 0) { + lpfc_unblock_mgmt_io(phba); + return; + } + /* fall through for not able to recover */ } lpfc_sli4_offline_eratt(phba); break; @@ -1724,11 +1733,20 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len) j = 0; Length -= (3+i); while(i--) { - phba->Port[j++] = vpd[index++]; - if (j == 19) - break; + if ((phba->sli_rev == LPFC_SLI_REV4) && + (phba->sli4_hba.pport_name_sta == + LPFC_SLI4_PPNAME_GET)) { + j++; + index++; + } else + phba->Port[j++] = vpd[index++]; + if (j == 19) + break; } - phba->Port[j] = 0; + if ((phba->sli_rev != LPFC_SLI_REV4) || + (phba->sli4_hba.pport_name_sta == + LPFC_SLI4_PPNAME_NON)) + phba->Port[j] = 0; continue; } else { @@ -1958,7 +1976,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) case PCI_DEVICE_ID_LANCER_FCOE: case PCI_DEVICE_ID_LANCER_FCOE_VF: oneConnect = 1; - m = (typeof(m)){"OCe50100", "PCIe", "FCoE"}; + m = (typeof(m)){"OCe15100", "PCIe", "FCoE"}; break; default: m = (typeof(m)){"Unknown", "", ""}; @@ -2432,17 +2450,19 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba) uint8_t actcmd = MBX_HEARTBEAT; unsigned long timeout; - + timeout = msecs_to_jiffies(LPFC_MBOX_TMO * 1000) + jiffies; spin_lock_irqsave(&phba->hbalock, iflag); phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO; - if (phba->sli.mbox_active) + if (phba->sli.mbox_active) { actcmd = phba->sli.mbox_active->u.mb.mbxCommand; + /* Determine how long we might wait for the active mailbox + * command to be gracefully completed by firmware. + */ + timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, + phba->sli.mbox_active) * 1000) + jiffies; + } spin_unlock_irqrestore(&phba->hbalock, iflag); - /* Determine how long we might wait for the active mailbox - * command to be gracefully completed by firmware. - */ - timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) + - jiffies; + /* Wait for the outstnading mailbox command to complete */ while (phba->sli.mbox_active) { /* Check active mailbox complete status every 2ms */ @@ -3949,7 +3969,7 @@ static int lpfc_enable_pci_dev(struct lpfc_hba *phba) { struct pci_dev *pdev; - int bars; + int bars = 0; /* Obtain PCI device reference */ if (!phba->pcidev) @@ -3978,6 +3998,8 @@ lpfc_enable_pci_dev(struct lpfc_hba *phba) out_disable_device: pci_disable_device(pdev); out_error: + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "1401 Failed to enable pci device, bars:x%x\n", bars); return -ENODEV; } @@ -4051,9 +4073,6 @@ lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *phba) uint16_t nr_virtfn; int pos; - if (!pdev->is_physfn) - return 0; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); if (pos == 0) return 0; @@ -4474,15 +4493,15 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) } } mempool_free(mboxq, phba->mbox_mem_pool); - /* Create all the SLI4 queues */ - rc = lpfc_sli4_queue_create(phba); + /* Verify all the SLI4 queues */ + rc = lpfc_sli4_queue_verify(phba); if (rc) goto out_free_bsmbx; /* Create driver internal CQE event pool */ rc = lpfc_sli4_cq_event_pool_create(phba); if (rc) - goto out_destroy_queue; + goto out_free_bsmbx; /* Initialize and populate the iocb list per host */ rc = lpfc_init_sgl_list(phba); @@ -4516,14 +4535,21 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) goto out_remove_rpi_hdrs; } - phba->sli4_hba.fcp_eq_hdl = kzalloc((sizeof(struct lpfc_fcp_eq_hdl) * + /* + * The cfg_fcp_eq_count can be zero whenever there is exactly one + * interrupt vector. This is not an error + */ + if (phba->cfg_fcp_eq_count) { + phba->sli4_hba.fcp_eq_hdl = + kzalloc((sizeof(struct lpfc_fcp_eq_hdl) * phba->cfg_fcp_eq_count), GFP_KERNEL); - if (!phba->sli4_hba.fcp_eq_hdl) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2572 Failed allocate memory for fast-path " - "per-EQ handle array\n"); - rc = -ENOMEM; - goto out_free_fcf_rr_bmask; + if (!phba->sli4_hba.fcp_eq_hdl) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2572 Failed allocate memory for " + "fast-path per-EQ handle array\n"); + rc = -ENOMEM; + goto out_free_fcf_rr_bmask; + } } phba->sli4_hba.msix_entries = kzalloc((sizeof(struct msix_entry) * @@ -4567,8 +4593,6 @@ out_free_sgl_list: lpfc_free_sgl_list(phba); out_destroy_cq_event_pool: lpfc_sli4_cq_event_pool_destroy(phba); -out_destroy_queue: - lpfc_sli4_queue_destroy(phba); out_free_bsmbx: lpfc_destroy_bootstrap_mbox(phba); out_free_mem: @@ -4608,9 +4632,6 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba) /* Free the SCSI sgl management array */ kfree(phba->sli4_hba.lpfc_scsi_psb_array); - /* Free the SLI4 queues */ - lpfc_sli4_queue_destroy(phba); - /* Free the completion queue EQ event pool */ lpfc_sli4_cq_event_release_all(phba); lpfc_sli4_cq_event_pool_destroy(phba); @@ -6139,24 +6160,21 @@ lpfc_setup_endian_order(struct lpfc_hba *phba) } /** - * lpfc_sli4_queue_create - Create all the SLI4 queues + * lpfc_sli4_queue_verify - Verify and update EQ and CQ counts * @phba: pointer to lpfc hba data structure. * - * This routine is invoked to allocate all the SLI4 queues for the FCoE HBA - * operation. For each SLI4 queue type, the parameters such as queue entry - * count (queue depth) shall be taken from the module parameter. For now, - * we just use some constant number as place holder. + * This routine is invoked to check the user settable queue counts for EQs and + * CQs. after this routine is called the counts will be set to valid values that + * adhere to the constraints of the system's interrupt vectors and the port's + * queue resources. * * Return codes * 0 - successful * -ENOMEM - No available memory - * -EIO - The mailbox failed to complete successfully. **/ static int -lpfc_sli4_queue_create(struct lpfc_hba *phba) +lpfc_sli4_queue_verify(struct lpfc_hba *phba) { - struct lpfc_queue *qdesc; - int fcp_eqidx, fcp_cqidx, fcp_wqidx; int cfg_fcp_wq_count; int cfg_fcp_eq_count; @@ -6229,14 +6247,43 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) /* The overall number of event queues used */ phba->sli4_hba.cfg_eqn = phba->cfg_fcp_eq_count + LPFC_SP_EQN_DEF; - /* - * Create Event Queues (EQs) - */ - /* Get EQ depth from module parameter, fake the default for now */ phba->sli4_hba.eq_esize = LPFC_EQE_SIZE_4B; phba->sli4_hba.eq_ecount = LPFC_EQE_DEF_COUNT; + /* Get CQ depth from module parameter, fake the default for now */ + phba->sli4_hba.cq_esize = LPFC_CQE_SIZE; + phba->sli4_hba.cq_ecount = LPFC_CQE_DEF_COUNT; + + return 0; +out_error: + return -ENOMEM; +} + +/** + * lpfc_sli4_queue_create - Create all the SLI4 queues + * @phba: pointer to lpfc hba data structure. + * + * This routine is invoked to allocate all the SLI4 queues for the FCoE HBA + * operation. For each SLI4 queue type, the parameters such as queue entry + * count (queue depth) shall be taken from the module parameter. For now, + * we just use some constant number as place holder. + * + * Return codes + * 0 - sucessful + * -ENOMEM - No availble memory + * -EIO - The mailbox failed to complete successfully. + **/ +int +lpfc_sli4_queue_create(struct lpfc_hba *phba) +{ + struct lpfc_queue *qdesc; + int fcp_eqidx, fcp_cqidx, fcp_wqidx; + + /* + * Create Event Queues (EQs) + */ + /* Create slow path event queue */ qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.eq_esize, phba->sli4_hba.eq_ecount); @@ -6247,14 +6294,20 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) } phba->sli4_hba.sp_eq = qdesc; - /* Create fast-path FCP Event Queue(s) */ - phba->sli4_hba.fp_eq = kzalloc((sizeof(struct lpfc_queue *) * - phba->cfg_fcp_eq_count), GFP_KERNEL); - if (!phba->sli4_hba.fp_eq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2576 Failed allocate memory for fast-path " - "EQ record array\n"); - goto out_free_sp_eq; + /* + * Create fast-path FCP Event Queue(s). The cfg_fcp_eq_count can be + * zero whenever there is exactly one interrupt vector. This is not + * an error. + */ + if (phba->cfg_fcp_eq_count) { + phba->sli4_hba.fp_eq = kzalloc((sizeof(struct lpfc_queue *) * + phba->cfg_fcp_eq_count), GFP_KERNEL); + if (!phba->sli4_hba.fp_eq) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2576 Failed allocate memory for " + "fast-path EQ record array\n"); + goto out_free_sp_eq; + } } for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) { qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.eq_esize, @@ -6271,10 +6324,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) * Create Complete Queues (CQs) */ - /* Get CQ depth from module parameter, fake the default for now */ - phba->sli4_hba.cq_esize = LPFC_CQE_SIZE; - phba->sli4_hba.cq_ecount = LPFC_CQE_DEF_COUNT; - /* Create slow-path Mailbox Command Complete Queue */ qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize, phba->sli4_hba.cq_ecount); @@ -6296,16 +6345,25 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) phba->sli4_hba.els_cq = qdesc; - /* Create fast-path FCP Completion Queue(s), one-to-one with EQs */ - phba->sli4_hba.fcp_cq = kzalloc((sizeof(struct lpfc_queue *) * - phba->cfg_fcp_eq_count), GFP_KERNEL); + /* + * Create fast-path FCP Completion Queue(s), one-to-one with FCP EQs. + * If there are no FCP EQs then create exactly one FCP CQ. + */ + if (phba->cfg_fcp_eq_count) + phba->sli4_hba.fcp_cq = kzalloc((sizeof(struct lpfc_queue *) * + phba->cfg_fcp_eq_count), + GFP_KERNEL); + else + phba->sli4_hba.fcp_cq = kzalloc(sizeof(struct lpfc_queue *), + GFP_KERNEL); if (!phba->sli4_hba.fcp_cq) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "2577 Failed allocate memory for fast-path " "CQ record array\n"); goto out_free_els_cq; } - for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++) { + fcp_cqidx = 0; + do { qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize, phba->sli4_hba.cq_ecount); if (!qdesc) { @@ -6315,7 +6373,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) goto out_free_fcp_cq; } phba->sli4_hba.fcp_cq[fcp_cqidx] = qdesc; - } + } while (++fcp_cqidx < phba->cfg_fcp_eq_count); /* Create Mailbox Command Queue */ phba->sli4_hba.mq_esize = LPFC_MQE_SIZE; @@ -6447,7 +6505,7 @@ out_error: * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ -static void +void lpfc_sli4_queue_destroy(struct lpfc_hba *phba) { int fcp_qidx; @@ -6723,6 +6781,10 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) "0540 Receive Queue not allocated\n"); goto out_destroy_fcp_wq; } + + lpfc_rq_adjust_repost(phba, phba->sli4_hba.hdr_rq, LPFC_ELS_HBQ); + lpfc_rq_adjust_repost(phba, phba->sli4_hba.dat_rq, LPFC_ELS_HBQ); + rc = lpfc_rq_create(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq, phba->sli4_hba.els_cq, LPFC_USOL); if (rc) { @@ -6731,6 +6793,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) "rc = 0x%x\n", rc); goto out_destroy_fcp_wq; } + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "2592 USL RQ setup: hdr-rq-id=%d, dat-rq-id=%d " "parent cq-id=%d\n", @@ -6790,8 +6853,10 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba) /* Unset ELS complete queue */ lpfc_cq_destroy(phba, phba->sli4_hba.els_cq); /* Unset FCP response complete queue */ - for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) + fcp_qidx = 0; + do { lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_qidx]); + } while (++fcp_qidx < phba->cfg_fcp_eq_count); /* Unset fast-path event queue */ for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) lpfc_eq_destroy(phba, phba->sli4_hba.fp_eq[fcp_qidx]); @@ -7040,10 +7105,11 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) * the loop again. */ for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) { + msleep(10); if (lpfc_readl(phba->sli4_hba.u.if_type2. STATUSregaddr, ®_data.word0)) { rc = -ENODEV; - break; + goto out; } if (bf_get(lpfc_sliport_status_rdy, ®_data)) break; @@ -7051,7 +7117,6 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) reset_again++; break; } - msleep(10); } /* @@ -7065,11 +7130,6 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) } /* Detect any port errors. */ - if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, - ®_data.word0)) { - rc = -ENODEV; - break; - } if ((bf_get(lpfc_sliport_status_err, ®_data)) || (rdy_chk >= 1000)) { phba->work_status[0] = readl( @@ -7102,6 +7162,7 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) break; } +out: /* Catch the not-ready port failure after a port reset. */ if (num_resets >= MAX_IF_TYPE_2_RESETS) rc = -ENODEV; @@ -7149,12 +7210,13 @@ lpfc_sli4_send_nop_mbox_cmds(struct lpfc_hba *phba, uint32_t cnt) lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, LPFC_MBOX_OPCODE_NOP, length, LPFC_SLI4_MBX_EMBED); - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); for (cmdsent = 0; cmdsent < cnt; cmdsent++) { if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); - else + else { + mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq); rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); + } if (rc == MBX_TIMEOUT) break; /* Check return status */ @@ -7974,6 +8036,7 @@ lpfc_sli4_unset_hba(struct lpfc_hba *phba) /* Reset SLI4 HBA FCoE function */ lpfc_pci_function_reset(phba); + lpfc_sli4_queue_destroy(phba); return; } @@ -8087,6 +8150,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) /* Reset SLI4 HBA FCoE function */ lpfc_pci_function_reset(phba); + lpfc_sli4_queue_destroy(phba); /* Stop the SLI4 device port */ phba->pport->work_port_events = 0; @@ -8120,7 +8184,7 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_PORT_CAPABILITIES); + mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq); rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); } @@ -8182,6 +8246,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) int rc; struct lpfc_mqe *mqe = &mboxq->u.mqe; struct lpfc_pc_sli4_params *sli4_params; + uint32_t mbox_tmo; int length; struct lpfc_sli4_parameters *mbx_sli4_parameters; @@ -8200,9 +8265,10 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) length, LPFC_SLI4_MBX_EMBED); if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); - else - rc = lpfc_sli_issue_mbox_wait(phba, mboxq, - lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG)); + else { + mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq); + rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); + } if (unlikely(rc)) return rc; sli4_params = &phba->sli4_hba.pc_sli4_params; @@ -8271,11 +8337,8 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) /* Perform generic PCI device enabling operation */ error = lpfc_enable_pci_dev(phba); - if (error) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "1401 Failed to enable pci device.\n"); + if (error) goto out_free_phba; - } /* Set up SLI API function jump table for PCI-device group-0 HBAs */ error = lpfc_api_table_setup(phba, LPFC_PCI_DEV_LP); @@ -8322,6 +8385,9 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_free_iocb_list; } + /* Get the default values for Model Name and Description */ + lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc); + /* Create SCSI host to the physical port */ error = lpfc_create_shost(phba); if (error) { @@ -8885,16 +8951,17 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw) uint32_t offset = 0, temp_offset = 0; INIT_LIST_HEAD(&dma_buffer_list); - if ((image->magic_number != LPFC_GROUP_OJECT_MAGIC_NUM) || - (bf_get(lpfc_grp_hdr_file_type, image) != LPFC_FILE_TYPE_GROUP) || - (bf_get(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) || - (image->size != fw->size)) { + if ((be32_to_cpu(image->magic_number) != LPFC_GROUP_OJECT_MAGIC_NUM) || + (bf_get_be32(lpfc_grp_hdr_file_type, image) != + LPFC_FILE_TYPE_GROUP) || + (bf_get_be32(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) || + (be32_to_cpu(image->size) != fw->size)) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3022 Invalid FW image found. " - "Magic:%d Type:%x ID:%x\n", - image->magic_number, - bf_get(lpfc_grp_hdr_file_type, image), - bf_get(lpfc_grp_hdr_id, image)); + "Magic:%x Type:%x ID:%x\n", + be32_to_cpu(image->magic_number), + bf_get_be32(lpfc_grp_hdr_file_type, image), + bf_get_be32(lpfc_grp_hdr_id, image)); return -EINVAL; } lpfc_decode_firmware_rev(phba, fwrev, 1); @@ -8924,11 +8991,11 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw) while (offset < fw->size) { temp_offset = offset; list_for_each_entry(dmabuf, &dma_buffer_list, list) { - if (offset + SLI4_PAGE_SIZE > fw->size) { - temp_offset += fw->size - offset; + if (temp_offset + SLI4_PAGE_SIZE > fw->size) { memcpy(dmabuf->virt, fw->data + temp_offset, - fw->size - offset); + fw->size - temp_offset); + temp_offset = fw->size; break; } memcpy(dmabuf->virt, fw->data + temp_offset, @@ -8984,7 +9051,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) uint32_t cfg_mode, intr_mode; int mcnt; int adjusted_fcp_eq_count; - int fcp_qidx; const struct firmware *fw; uint8_t file_name[16]; @@ -8995,11 +9061,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) /* Perform generic PCI device enabling operation */ error = lpfc_enable_pci_dev(phba); - if (error) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "1409 Failed to enable pci device.\n"); + if (error) goto out_free_phba; - } /* Set up SLI API function jump table for PCI-device group-1 HBAs */ error = lpfc_api_table_setup(phba, LPFC_PCI_DEV_OC); @@ -9054,6 +9117,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_free_iocb_list; } + /* Get the default values for Model Name and Description */ + lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc); + /* Create SCSI host to the physical port */ error = lpfc_create_shost(phba); if (error) { @@ -9093,16 +9159,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) adjusted_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1; else adjusted_fcp_eq_count = phba->cfg_fcp_eq_count; - /* Free unused EQs */ - for (fcp_qidx = adjusted_fcp_eq_count; - fcp_qidx < phba->cfg_fcp_eq_count; - fcp_qidx++) { - lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]); - /* do not delete the first fcp_cq */ - if (fcp_qidx) - lpfc_sli4_queue_free( - phba->sli4_hba.fcp_cq[fcp_qidx]); - } phba->cfg_fcp_eq_count = adjusted_fcp_eq_count; /* Set up SLI-4 HBA */ if (lpfc_sli4_hba_setup(phba)) { @@ -9285,6 +9341,7 @@ lpfc_pci_suspend_one_s4(struct pci_dev *pdev, pm_message_t msg) /* Disable interrupt from device */ lpfc_sli4_disable_intr(phba); + lpfc_sli4_queue_destroy(phba); /* Save device state to PCI config space */ pci_save_state(pdev); @@ -9414,6 +9471,7 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba) /* Disable interrupt and pci device */ lpfc_sli4_disable_intr(phba); + lpfc_sli4_queue_destroy(phba); pci_disable_device(phba->pcidev); /* Flush all driver's outstanding SCSI I/Os as we are to reset */ diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index e3b790e..baf53e6 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h @@ -36,6 +36,7 @@ #define LOG_SECURITY 0x00008000 /* Security events */ #define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */ #define LOG_FIP 0x00020000 /* FIP events */ +#define LOG_FCP_UNDER 0x00040000 /* FCP underruns errors */ #define LOG_ALL_MSG 0xffffffff /* LOG all messages */ #define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \ diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 83450cc..2ebc7d2 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1598,9 +1598,12 @@ lpfc_mbox_dev_check(struct lpfc_hba *phba) * Timeout value to be used for the given mailbox command **/ int -lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd) +lpfc_mbox_tmo_val(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { - switch (cmd) { + MAILBOX_t *mbox = &mboxq->u.mb; + uint8_t subsys, opcode; + + switch (mbox->mbxCommand) { case MBX_WRITE_NV: /* 0x03 */ case MBX_UPDATE_CFG: /* 0x1B */ case MBX_DOWN_LOAD: /* 0x1C */ @@ -1610,6 +1613,28 @@ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd) case MBX_LOAD_EXP_ROM: /* 0x9C */ return LPFC_MBOX_TMO_FLASH_CMD; case MBX_SLI4_CONFIG: /* 0x9b */ + subsys = lpfc_sli_config_mbox_subsys_get(phba, mboxq); + opcode = lpfc_sli_config_mbox_opcode_get(phba, mboxq); + if (subsys == LPFC_MBOX_SUBSYSTEM_COMMON) { + switch (opcode) { + case LPFC_MBOX_OPCODE_READ_OBJECT: + case LPFC_MBOX_OPCODE_WRITE_OBJECT: + case LPFC_MBOX_OPCODE_READ_OBJECT_LIST: + case LPFC_MBOX_OPCODE_DELETE_OBJECT: + case LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG: + case LPFC_MBOX_OPCODE_GET_PROFILE_LIST: + case LPFC_MBOX_OPCODE_SET_ACT_PROFILE: + case LPFC_MBOX_OPCODE_SET_PROFILE_CONFIG: + case LPFC_MBOX_OPCODE_GET_FACTORY_PROFILE_CONFIG: + return LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO; + } + } + if (subsys == LPFC_MBOX_SUBSYSTEM_FCOE) { + switch (opcode) { + case LPFC_MBOX_OPCODE_FCOE_SET_FCLINK_SETTINGS: + return LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO; + } + } return LPFC_MBOX_SLI4_CONFIG_TMO; } return LPFC_MBOX_TMO; @@ -1859,7 +1884,7 @@ lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox, } /* Complete the initialization for the particular Opcode. */ - opcode = lpfc_sli4_mbox_opcode_get(phba, mbox); + opcode = lpfc_sli_config_mbox_opcode_get(phba, mbox); switch (opcode) { case LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT: if (emb == LPFC_SLI4_MBX_EMBED) @@ -1886,23 +1911,56 @@ lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox, } /** - * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command + * lpfc_sli_config_mbox_subsys_get - Get subsystem from a sli_config mbox cmd * @phba: pointer to lpfc hba data structure. - * @mbox: pointer to lpfc mbox command. + * @mbox: pointer to lpfc mbox command queue entry. + * + * This routine gets the subsystem from a SLI4 specific SLI_CONFIG mailbox + * command. If the mailbox command is not MBX_SLI4_CONFIG (0x9B) or if the + * sub-header is not present, subsystem LPFC_MBOX_SUBSYSTEM_NA (0x0) shall + * be returned. + **/ +uint8_t +lpfc_sli_config_mbox_subsys_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) +{ + struct lpfc_mbx_sli4_config *sli4_cfg; + union lpfc_sli4_cfg_shdr *cfg_shdr; + + if (mbox->u.mb.mbxCommand != MBX_SLI4_CONFIG) + return LPFC_MBOX_SUBSYSTEM_NA; + sli4_cfg = &mbox->u.mqe.un.sli4_config; + + /* For embedded mbox command, get opcode from embedded sub-header*/ + if (bf_get(lpfc_mbox_hdr_emb, &sli4_cfg->header.cfg_mhdr)) { + cfg_shdr = &mbox->u.mqe.un.sli4_config.header.cfg_shdr; + return bf_get(lpfc_mbox_hdr_subsystem, &cfg_shdr->request); + } + + /* For non-embedded mbox command, get opcode from first dma page */ + if (unlikely(!mbox->sge_array)) + return LPFC_MBOX_SUBSYSTEM_NA; + cfg_shdr = (union lpfc_sli4_cfg_shdr *)mbox->sge_array->addr[0]; + return bf_get(lpfc_mbox_hdr_subsystem, &cfg_shdr->request); +} + +/** + * lpfc_sli_config_mbox_opcode_get - Get opcode from a sli_config mbox cmd + * @phba: pointer to lpfc hba data structure. + * @mbox: pointer to lpfc mbox command queue entry. * - * This routine gets the opcode from a SLI4 specific mailbox command for - * sending IOCTL command. If the mailbox command is not MBX_SLI4_CONFIG - * (0x9B) or if the IOCTL sub-header is not present, opcode 0x0 shall be + * This routine gets the opcode from a SLI4 specific SLI_CONFIG mailbox + * command. If the mailbox command is not MBX_SLI4_CONFIG (0x9B) or if + * the sub-header is not present, opcode LPFC_MBOX_OPCODE_NA (0x0) be * returned. **/ uint8_t -lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox) +lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) { struct lpfc_mbx_sli4_config *sli4_cfg; union lpfc_sli4_cfg_shdr *cfg_shdr; if (mbox->u.mb.mbxCommand != MBX_SLI4_CONFIG) - return 0; + return LPFC_MBOX_OPCODE_NA; sli4_cfg = &mbox->u.mqe.un.sli4_config; /* For embedded mbox command, get opcode from embedded sub-header*/ @@ -1913,7 +1971,7 @@ lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox) /* For non-embedded mbox command, get opcode from first dma page */ if (unlikely(!mbox->sge_array)) - return 0; + return LPFC_MBOX_OPCODE_NA; cfg_shdr = (union lpfc_sli4_cfg_shdr *)mbox->sge_array->addr[0]; return bf_get(lpfc_mbox_hdr_opcode, &cfg_shdr->request); } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index eadd241..2e1e54e 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -21,6 +21,7 @@ #include <linux/pci.h> #include <linux/slab.h> #include <linux/interrupt.h> +#include <linux/export.h> #include <linux/delay.h> #include <asm/unaligned.h> @@ -58,6 +59,13 @@ static char *dif_op_str[] = { "SCSI_PROT_READ_PASS", "SCSI_PROT_WRITE_PASS", }; + +struct scsi_dif_tuple { + __be16 guard_tag; /* Checksum */ + __be16 app_tag; /* Opaque storage */ + __be32 ref_tag; /* Target LBA or indirect LBA */ +}; + static void lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); static void @@ -1263,6 +1271,174 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) return 0; } +static inline unsigned +lpfc_cmd_blksize(struct scsi_cmnd *sc) +{ + return sc->device->sector_size; +} + +#ifdef CONFIG_SCSI_LPFC_DEBUG_FS +/* + * Given a scsi cmnd, determine the BlockGuard tags to be used with it + * @sc: The SCSI command to examine + * @reftag: (out) BlockGuard reference tag for transmitted data + * @apptag: (out) BlockGuard application tag for transmitted data + * @new_guard (in) Value to replace CRC with if needed + * + * Returns (1) if error injection was performed, (0) otherwise + */ +static int +lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, + uint32_t *reftag, uint16_t *apptag, uint32_t new_guard) +{ + struct scatterlist *sgpe; /* s/g prot entry */ + struct scatterlist *sgde; /* s/g data entry */ + struct scsi_dif_tuple *src; + uint32_t op = scsi_get_prot_op(sc); + uint32_t blksize; + uint32_t numblks; + sector_t lba; + int rc = 0; + + if (op == SCSI_PROT_NORMAL) + return 0; + + lba = scsi_get_lba(sc); + if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) { + blksize = lpfc_cmd_blksize(sc); + numblks = (scsi_bufflen(sc) + blksize - 1) / blksize; + + /* Make sure we have the right LBA if one is specified */ + if ((phba->lpfc_injerr_lba < lba) || + (phba->lpfc_injerr_lba >= (lba + numblks))) + return 0; + } + + sgpe = scsi_prot_sglist(sc); + sgde = scsi_sglist(sc); + + /* Should we change the Reference Tag */ + if (reftag) { + /* + * If we are SCSI_PROT_WRITE_STRIP, the protection data is + * being stripped from the wire, thus it doesn't matter. + */ + if ((op == SCSI_PROT_WRITE_PASS) || + (op == SCSI_PROT_WRITE_INSERT)) { + if (phba->lpfc_injerr_wref_cnt) { + + /* DEADBEEF will be the reftag on the wire */ + *reftag = 0xDEADBEEF; + phba->lpfc_injerr_wref_cnt--; + phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF; + rc = 1; + + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9081 BLKGRD: Injecting reftag error: " + "write lba x%lx\n", (unsigned long)lba); + } + } else { + if (phba->lpfc_injerr_rref_cnt) { + *reftag = 0xDEADBEEF; + phba->lpfc_injerr_rref_cnt--; + phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF; + rc = 1; + + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9076 BLKGRD: Injecting reftag error: " + "read lba x%lx\n", (unsigned long)lba); + } + } + } + + /* Should we change the Application Tag */ + if (apptag) { + /* + * If we are SCSI_PROT_WRITE_STRIP, the protection data is + * being stripped from the wire, thus it doesn't matter. + */ + if ((op == SCSI_PROT_WRITE_PASS) || + (op == SCSI_PROT_WRITE_INSERT)) { + if (phba->lpfc_injerr_wapp_cnt) { + + /* DEAD will be the apptag on the wire */ + *apptag = 0xDEAD; + phba->lpfc_injerr_wapp_cnt--; + phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF; + rc = 1; + + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9077 BLKGRD: Injecting apptag error: " + "write lba x%lx\n", (unsigned long)lba); + } + } else { + if (phba->lpfc_injerr_rapp_cnt) { + *apptag = 0xDEAD; + phba->lpfc_injerr_rapp_cnt--; + phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF; + rc = 1; + + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9078 BLKGRD: Injecting apptag error: " + "read lba x%lx\n", (unsigned long)lba); + } + } + } + + /* Should we change the Guard Tag */ + + /* + * If we are SCSI_PROT_WRITE_INSERT, the protection data is + * being on the wire is being fully generated on the HBA. + * The host cannot change it or force an error. + */ + if (((op == SCSI_PROT_WRITE_STRIP) || + (op == SCSI_PROT_WRITE_PASS)) && + phba->lpfc_injerr_wgrd_cnt) { + if (sgpe) { + src = (struct scsi_dif_tuple *)sg_virt(sgpe); + /* + * Just inject an error in the first + * prot block. + */ + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9079 BLKGRD: Injecting guard error: " + "write lba x%lx oldGuard x%x refTag x%x\n", + (unsigned long)lba, src->guard_tag, + src->ref_tag); + + src->guard_tag = (uint16_t)new_guard; + phba->lpfc_injerr_wgrd_cnt--; + phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF; + rc = 1; + + } else { + blksize = lpfc_cmd_blksize(sc); + /* + * Jump past the first data block + * and inject an error in the + * prot data. The prot data is already + * embedded after the regular data. + */ + src = (struct scsi_dif_tuple *) + (sg_virt(sgde) + blksize); + + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9080 BLKGRD: Injecting guard error: " + "write lba x%lx oldGuard x%x refTag x%x\n", + (unsigned long)lba, src->guard_tag, + src->ref_tag); + + src->guard_tag = (uint16_t)new_guard; + phba->lpfc_injerr_wgrd_cnt--; + phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF; + rc = 1; + } + } + return rc; +} +#endif + /* * Given a scsi cmnd, determine the BlockGuard opcodes to be used with it * @sc: The SCSI command to examine @@ -1341,18 +1517,6 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc, return ret; } -struct scsi_dif_tuple { - __be16 guard_tag; /* Checksum */ - __be16 app_tag; /* Opaque storage */ - __be32 ref_tag; /* Target LBA or indirect LBA */ -}; - -static inline unsigned -lpfc_cmd_blksize(struct scsi_cmnd *sc) -{ - return sc->device->sector_size; -} - /* * This function sets up buffer list for protection groups of * type LPFC_PG_TYPE_NO_DIF @@ -1401,6 +1565,11 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, blksize = lpfc_cmd_blksize(sc); reftag = scsi_get_lba(sc) & 0xffffffff; +#ifdef CONFIG_SCSI_LPFC_DEBUG_FS + /* reftag is the only error we can inject here */ + lpfc_bg_err_inject(phba, sc, &reftag, 0, 0); +#endif + /* setup PDE5 with what we have */ pde5 = (struct lpfc_pde5 *) bpl; memset(pde5, 0, sizeof(struct lpfc_pde5)); @@ -1532,6 +1701,11 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, blksize = lpfc_cmd_blksize(sc); reftag = scsi_get_lba(sc) & 0xffffffff; +#ifdef CONFIG_SCSI_LPFC_DEBUG_FS + /* reftag / guard tag are the only errors we can inject here */ + lpfc_bg_err_inject(phba, sc, &reftag, 0, 0xDEAD); +#endif + split_offset = 0; do { /* setup PDE5 with what we have */ @@ -1671,7 +1845,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, } } while (!alldone); - out: return num_bde; @@ -2075,6 +2248,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) else bf_set(lpfc_sli4_sge_last, sgl, 0); bf_set(lpfc_sli4_sge_offset, sgl, dma_offset); + bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA); sgl->word2 = cpu_to_le32(sgl->word2); sgl->sge_len = cpu_to_le32(dma_len); dma_offset += dma_len; @@ -2325,8 +2499,9 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, } lp = (uint32_t *)cmnd->sense_buffer; - if (!scsi_status && (resp_info & RESID_UNDER)) - logit = LOG_FCP; + if (!scsi_status && (resp_info & RESID_UNDER) && + vport->cfg_log_verbose & LOG_FCP_UNDER) + logit = LOG_FCP_UNDER; lpfc_printf_vlog(vport, KERN_WARNING, logit, "9024 FCP command x%x failed: x%x SNS x%x x%x " @@ -2342,7 +2517,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, if (resp_info & RESID_UNDER) { scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId)); - lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_UNDER, "9025 FCP Read Underrun, expected %d, " "residual %d Data: x%x x%x x%x\n", be32_to_cpu(fcpcmd->fcpDl), @@ -2449,6 +2624,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, struct lpfc_fast_path_event *fast_path_evt; struct Scsi_Host *shost; uint32_t queue_depth, scsi_id; + uint32_t logit = LOG_FCP; /* Sanity check on return of outstanding command */ if (!(lpfc_cmd->pCmd)) @@ -2470,16 +2646,22 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, lpfc_cmd->status = IOSTAT_DRIVER_REJECT; else if (lpfc_cmd->status >= IOSTAT_CNT) lpfc_cmd->status = IOSTAT_DEFAULT; - - lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, - "9030 FCP cmd x%x failed <%d/%d> " - "status: x%x result: x%x Data: x%x x%x\n", - cmd->cmnd[0], - cmd->device ? cmd->device->id : 0xffff, - cmd->device ? cmd->device->lun : 0xffff, - lpfc_cmd->status, lpfc_cmd->result, - pIocbOut->iocb.ulpContext, - lpfc_cmd->cur_iocbq.iocb.ulpIoTag); + if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR + && !lpfc_cmd->fcp_rsp->rspStatus3 + && (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER) + && !(phba->cfg_log_verbose & LOG_FCP_UNDER)) + logit = 0; + else + logit = LOG_FCP | LOG_FCP_UNDER; + lpfc_printf_vlog(vport, KERN_WARNING, logit, + "9030 FCP cmd x%x failed <%d/%d> " + "status: x%x result: x%x Data: x%x x%x\n", + cmd->cmnd[0], + cmd->device ? cmd->device->id : 0xffff, + cmd->device ? cmd->device->lun : 0xffff, + lpfc_cmd->status, lpfc_cmd->result, + pIocbOut->iocb.ulpContext, + lpfc_cmd->cur_iocbq.iocb.ulpIoTag); switch (lpfc_cmd->status) { case IOSTAT_FCP_RSP_ERROR: @@ -3056,8 +3238,9 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) } ndlp = rdata->pnode; - if (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && - scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { + if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) && + (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) || + (phba->sli_rev == LPFC_SLI_REV4))) { lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9058 BLKGRD: ERROR: rcvd protected cmd:%02x" @@ -3691,9 +3874,9 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) fc_host_post_vendor_event(shost, fc_get_event_number(), sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); - ret = fc_block_scsi_eh(cmnd); - if (ret) - return ret; + status = fc_block_scsi_eh(cmnd); + if (status) + return status; /* * Since the driver manages a single bus device, reset all diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8b799f0..4d4104f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -379,10 +379,10 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq, dq->host_index = ((dq->host_index + 1) % dq->entry_count); /* Ring The Header Receive Queue Doorbell */ - if (!(hq->host_index % LPFC_RQ_POST_BATCH)) { + if (!(hq->host_index % hq->entry_repost)) { doorbell.word0 = 0; bf_set(lpfc_rq_doorbell_num_posted, &doorbell, - LPFC_RQ_POST_BATCH); + hq->entry_repost); bf_set(lpfc_rq_doorbell_id, &doorbell, hq->queue_id); writel(doorbell.word0, hq->phba->sli4_hba.RQDBregaddr); } @@ -1864,7 +1864,7 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno) { if (phba->sli_rev == LPFC_SLI_REV4) return lpfc_sli_hbqbuf_fill_hbqs(phba, qno, - lpfc_hbq_defs[qno]->entry_count); + lpfc_hbq_defs[qno]->entry_count); else return lpfc_sli_hbqbuf_fill_hbqs(phba, qno, lpfc_hbq_defs[qno]->init_count); @@ -2200,10 +2200,13 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) /* Unknown mailbox command compl */ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, "(%d):0323 Unknown Mailbox command " - "x%x (x%x) Cmpl\n", + "x%x (x%x/x%x) Cmpl\n", pmb->vport ? pmb->vport->vpi : 0, pmbox->mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, pmb)); + lpfc_sli_config_mbox_subsys_get(phba, + pmb), + lpfc_sli_config_mbox_opcode_get(phba, + pmb)); phba->link_state = LPFC_HBA_ERROR; phba->work_hs = HS_FFER3; lpfc_handle_eratt(phba); @@ -2215,17 +2218,19 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) if (pmbox->mbxStatus == MBXERR_NO_RESOURCES) { /* Mbox cmd cmpl error - RETRYing */ lpfc_printf_log(phba, KERN_INFO, - LOG_MBOX | LOG_SLI, - "(%d):0305 Mbox cmd cmpl " - "error - RETRYing Data: x%x " - "(x%x) x%x x%x x%x\n", - pmb->vport ? pmb->vport->vpi :0, - pmbox->mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, - pmb), - pmbox->mbxStatus, - pmbox->un.varWords[0], - pmb->vport->port_state); + LOG_MBOX | LOG_SLI, + "(%d):0305 Mbox cmd cmpl " + "error - RETRYing Data: x%x " + "(x%x/x%x) x%x x%x x%x\n", + pmb->vport ? pmb->vport->vpi : 0, + pmbox->mbxCommand, + lpfc_sli_config_mbox_subsys_get(phba, + pmb), + lpfc_sli_config_mbox_opcode_get(phba, + pmb), + pmbox->mbxStatus, + pmbox->un.varWords[0], + pmb->vport->port_state); pmbox->mbxStatus = 0; pmbox->mbxOwner = OWN_HOST; rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); @@ -2236,11 +2241,12 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) /* Mailbox cmd <cmd> Cmpl <cmpl> */ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "(%d):0307 Mailbox cmd x%x (x%x) Cmpl x%p " + "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p " "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n", pmb->vport ? pmb->vport->vpi : 0, pmbox->mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, pmb), + lpfc_sli_config_mbox_subsys_get(phba, pmb), + lpfc_sli_config_mbox_opcode_get(phba, pmb), pmb->mbox_cmpl, *((uint32_t *) pmbox), pmbox->un.varWords[0], @@ -4686,6 +4692,175 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, } /** + * lpfc_sli4_retrieve_pport_name - Retrieve SLI4 device physical port name + * @phba: pointer to lpfc hba data structure. + * + * This routine retrieves SLI4 device physical port name this PCI function + * is attached to. + * + * Return codes + * 0 - sucessful + * otherwise - failed to retrieve physical port name + **/ +static int +lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba) +{ + LPFC_MBOXQ_t *mboxq; + struct lpfc_mbx_read_config *rd_config; + struct lpfc_mbx_get_cntl_attributes *mbx_cntl_attr; + struct lpfc_controller_attribute *cntl_attr; + struct lpfc_mbx_get_port_name *get_port_name; + void *virtaddr = NULL; + uint32_t alloclen, reqlen; + uint32_t shdr_status, shdr_add_status; + union lpfc_sli4_cfg_shdr *shdr; + char cport_name = 0; + int rc; + + /* We assume nothing at this point */ + phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_INVAL; + phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_NON; + + mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mboxq) + return -ENOMEM; + + /* obtain link type and link number via READ_CONFIG */ + lpfc_read_config(phba, mboxq); + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + if (rc == MBX_SUCCESS) { + rd_config = &mboxq->u.mqe.un.rd_config; + if (bf_get(lpfc_mbx_rd_conf_lnk_ldv, rd_config)) { + phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL; + phba->sli4_hba.lnk_info.lnk_tp = + bf_get(lpfc_mbx_rd_conf_lnk_type, rd_config); + phba->sli4_hba.lnk_info.lnk_no = + bf_get(lpfc_mbx_rd_conf_lnk_numb, rd_config); + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "3081 lnk_type:%d, lnk_numb:%d\n", + phba->sli4_hba.lnk_info.lnk_tp, + phba->sli4_hba.lnk_info.lnk_no); + goto retrieve_ppname; + } else + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3082 Mailbox (x%x) returned ldv:x0\n", + bf_get(lpfc_mqe_command, + &mboxq->u.mqe)); + } else + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3083 Mailbox (x%x) failed, status:x%x\n", + bf_get(lpfc_mqe_command, &mboxq->u.mqe), + bf_get(lpfc_mqe_status, &mboxq->u.mqe)); + + /* obtain link type and link number via COMMON_GET_CNTL_ATTRIBUTES */ + reqlen = sizeof(struct lpfc_mbx_get_cntl_attributes); + alloclen = lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, + LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES, reqlen, + LPFC_SLI4_MBX_NEMBED); + if (alloclen < reqlen) { + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "3084 Allocated DMA memory size (%d) is " + "less than the requested DMA memory size " + "(%d)\n", alloclen, reqlen); + rc = -ENOMEM; + goto out_free_mboxq; + } + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + virtaddr = mboxq->sge_array->addr[0]; + mbx_cntl_attr = (struct lpfc_mbx_get_cntl_attributes *)virtaddr; + shdr = &mbx_cntl_attr->cfg_shdr; + shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); + shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); + if (shdr_status || shdr_add_status || rc) { + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3085 Mailbox x%x (x%x/x%x) failed, " + "rc:x%x, status:x%x, add_status:x%x\n", + bf_get(lpfc_mqe_command, &mboxq->u.mqe), + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), + rc, shdr_status, shdr_add_status); + rc = -ENXIO; + goto out_free_mboxq; + } + cntl_attr = &mbx_cntl_attr->cntl_attr; + phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL; + phba->sli4_hba.lnk_info.lnk_tp = + bf_get(lpfc_cntl_attr_lnk_type, cntl_attr); + phba->sli4_hba.lnk_info.lnk_no = + bf_get(lpfc_cntl_attr_lnk_numb, cntl_attr); + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "3086 lnk_type:%d, lnk_numb:%d\n", + phba->sli4_hba.lnk_info.lnk_tp, + phba->sli4_hba.lnk_info.lnk_no); + +retrieve_ppname: + lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, + LPFC_MBOX_OPCODE_GET_PORT_NAME, + sizeof(struct lpfc_mbx_get_port_name) - + sizeof(struct lpfc_sli4_cfg_mhdr), + LPFC_SLI4_MBX_EMBED); + get_port_name = &mboxq->u.mqe.un.get_port_name; + shdr = (union lpfc_sli4_cfg_shdr *)&get_port_name->header.cfg_shdr; + bf_set(lpfc_mbox_hdr_version, &shdr->request, LPFC_OPCODE_VERSION_1); + bf_set(lpfc_mbx_get_port_name_lnk_type, &get_port_name->u.request, + phba->sli4_hba.lnk_info.lnk_tp); + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); + shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); + if (shdr_status || shdr_add_status || rc) { + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3087 Mailbox x%x (x%x/x%x) failed: " + "rc:x%x, status:x%x, add_status:x%x\n", + bf_get(lpfc_mqe_command, &mboxq->u.mqe), + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), + rc, shdr_status, shdr_add_status); + rc = -ENXIO; + goto out_free_mboxq; + } + switch (phba->sli4_hba.lnk_info.lnk_no) { + case LPFC_LINK_NUMBER_0: + cport_name = bf_get(lpfc_mbx_get_port_name_name0, + &get_port_name->u.response); + phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET; + break; + case LPFC_LINK_NUMBER_1: + cport_name = bf_get(lpfc_mbx_get_port_name_name1, + &get_port_name->u.response); + phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET; + break; + case LPFC_LINK_NUMBER_2: + cport_name = bf_get(lpfc_mbx_get_port_name_name2, + &get_port_name->u.response); + phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET; + break; + case LPFC_LINK_NUMBER_3: + cport_name = bf_get(lpfc_mbx_get_port_name_name3, + &get_port_name->u.response); + phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET; + break; + default: + break; + } + + if (phba->sli4_hba.pport_name_sta == LPFC_SLI4_PPNAME_GET) { + phba->Port[0] = cport_name; + phba->Port[1] = '\0'; + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "3091 SLI get port name: %s\n", phba->Port); + } + +out_free_mboxq: + if (rc != MBX_TIMEOUT) { + if (bf_get(lpfc_mqe_command, &mboxq->u.mqe) == MBX_SLI4_CONFIG) + lpfc_sli4_mbox_cmd_free(phba, mboxq); + else + mempool_free(mboxq, phba->mbox_mem_pool); + } + return rc; +} + +/** * lpfc_sli4_arm_cqeq_intr - Arm sli-4 device completion and event queues * @phba: pointer to lpfc hba data structure. * @@ -4754,7 +4929,7 @@ lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type, if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } if (unlikely(rc)) { @@ -4911,7 +5086,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt, if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } @@ -5194,7 +5369,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type) if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, mbox_tmo); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } if (unlikely(rc)) { @@ -5619,7 +5794,7 @@ lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type, if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } @@ -5748,6 +5923,17 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) kfree(vpd); goto out_free_mbox; } + + /* + * Retrieve sli4 device physical port name, failure of doing it + * is considered as non-fatal. + */ + rc = lpfc_sli4_retrieve_pport_name(phba); + if (!rc) + lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, + "3080 Successful retrieving SLI4 device " + "physical port name: %s.\n", phba->Port); + /* * Evaluate the read rev and vpd data. Populate the driver * state with the results. If this routine fails, the failure @@ -5818,9 +6004,13 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) * then turn off the global config parameters to disable the * feature in the driver. This is not a fatal error. */ - if ((phba->cfg_enable_bg) && - !(bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs))) - ftr_rsp++; + phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED; + if (phba->cfg_enable_bg) { + if (bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs)) + phba->sli3_options |= LPFC_SLI3_BG_ENABLED; + else + ftr_rsp++; + } if (phba->max_vpi && phba->cfg_enable_npiv && !(bf_get(lpfc_mbx_rq_ftr_rsp_npiv, &mqe->un.req_ftrs))) @@ -5937,12 +6127,20 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) goto out_free_mbox; } + /* Create all the SLI4 queues */ + rc = lpfc_sli4_queue_create(phba); + if (rc) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3089 Failed to allocate queues\n"); + rc = -ENODEV; + goto out_stop_timers; + } /* Set up all the queues to the device */ rc = lpfc_sli4_queue_setup(phba); if (unlikely(rc)) { lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, "0381 Error %d during queue setup.\n ", rc); - goto out_stop_timers; + goto out_destroy_queue; } /* Arm the CQs and then EQs on device */ @@ -6015,15 +6213,20 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); phba->link_state = LPFC_LINK_DOWN; spin_unlock_irq(&phba->hbalock); - if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) + if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) { rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); + if (rc) + goto out_unset_queue; + } + mempool_free(mboxq, phba->mbox_mem_pool); + return rc; out_unset_queue: /* Unset all the queues set up in this routine when error out */ - if (rc) - lpfc_sli4_queue_unset(phba); + lpfc_sli4_queue_unset(phba); +out_destroy_queue: + lpfc_sli4_queue_destroy(phba); out_stop_timers: - if (rc) - lpfc_stop_hba_timers(phba); + lpfc_stop_hba_timers(phba); out_free_mbox: mempool_free(mboxq, phba->mbox_mem_pool); return rc; @@ -6318,7 +6521,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, } /* timeout active mbox command */ mod_timer(&psli->mbox_tmo, (jiffies + - (HZ * lpfc_mbox_tmo_val(phba, mb->mbxCommand)))); + (HZ * lpfc_mbox_tmo_val(phba, pmbox)))); } /* Mailbox cmd <cmd> issue */ @@ -6442,9 +6645,8 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, drvr_flag); goto out_not_finished; } - timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, - mb->mbxCommand) * - 1000) + jiffies; + timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, pmbox) * + 1000) + jiffies; i = 0; /* Wait for command to complete */ while (((word0 & OWN_CHIP) == OWN_CHIP) || @@ -6555,21 +6757,21 @@ static int lpfc_sli4_async_mbox_block(struct lpfc_hba *phba) { struct lpfc_sli *psli = &phba->sli; - uint8_t actcmd = MBX_HEARTBEAT; int rc = 0; - unsigned long timeout; + unsigned long timeout = 0; /* Mark the asynchronous mailbox command posting as blocked */ spin_lock_irq(&phba->hbalock); psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK; - if (phba->sli.mbox_active) - actcmd = phba->sli.mbox_active->u.mb.mbxCommand; - spin_unlock_irq(&phba->hbalock); /* Determine how long we might wait for the active mailbox * command to be gracefully completed by firmware. */ - timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) + - jiffies; + if (phba->sli.mbox_active) + timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, + phba->sli.mbox_active) * + 1000) + jiffies; + spin_unlock_irq(&phba->hbalock); + /* Wait for the outstnading mailbox command to complete */ while (phba->sli.mbox_active) { /* Check active mailbox complete status every 2ms */ @@ -6664,11 +6866,12 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) { spin_unlock_irqrestore(&phba->hbalock, iflag); lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "(%d):2532 Mailbox command x%x (x%x) " + "(%d):2532 Mailbox command x%x (x%x/x%x) " "cannot issue Data: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, mboxq->u.mb.mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, mboxq), + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), psli->sli_flag, MBX_POLL); return MBXERR_ERROR; } @@ -6691,7 +6894,7 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) dma_address = &phba->sli4_hba.bmbx.dma_address; writel(dma_address->addr_hi, phba->sli4_hba.BMBXregaddr); - timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mbx_cmnd) + timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq) * 1000) + jiffies; do { bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr); @@ -6707,7 +6910,7 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) /* Post the low mailbox dma address to the port. */ writel(dma_address->addr_lo, phba->sli4_hba.BMBXregaddr); - timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mbx_cmnd) + timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq) * 1000) + jiffies; do { bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr); @@ -6746,11 +6949,12 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) lpfc_sli4_swap_str(phba, mboxq); lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "(%d):0356 Mailbox cmd x%x (x%x) Status x%x " + "(%d):0356 Mailbox cmd x%x (x%x/x%x) Status x%x " "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 x%x CQ: x%x x%x x%x x%x\n", - mboxq->vport ? mboxq->vport->vpi : 0, - mbx_cmnd, lpfc_sli4_mbox_opcode_get(phba, mboxq), + mboxq->vport ? mboxq->vport->vpi : 0, mbx_cmnd, + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), bf_get(lpfc_mqe_status, mb), mb->un.mb_words[0], mb->un.mb_words[1], mb->un.mb_words[2], mb->un.mb_words[3], @@ -6796,11 +7000,12 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, rc = lpfc_mbox_dev_check(phba); if (unlikely(rc)) { lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "(%d):2544 Mailbox command x%x (x%x) " + "(%d):2544 Mailbox command x%x (x%x/x%x) " "cannot issue Data: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, mboxq->u.mb.mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, mboxq), + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), psli->sli_flag, flag); goto out_not_finished; } @@ -6814,20 +7019,25 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, if (rc != MBX_SUCCESS) lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, "(%d):2541 Mailbox command x%x " - "(x%x) cannot issue Data: x%x x%x\n", + "(x%x/x%x) cannot issue Data: " + "x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, mboxq->u.mb.mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, mboxq), + lpfc_sli_config_mbox_subsys_get(phba, + mboxq), + lpfc_sli_config_mbox_opcode_get(phba, + mboxq), psli->sli_flag, flag); return rc; } else if (flag == MBX_POLL) { lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, "(%d):2542 Try to issue mailbox command " - "x%x (x%x) synchronously ahead of async" + "x%x (x%x/x%x) synchronously ahead of async" "mailbox command queue: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, mboxq->u.mb.mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, mboxq), + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), psli->sli_flag, flag); /* Try to block the asynchronous mailbox posting */ rc = lpfc_sli4_async_mbox_block(phba); @@ -6836,16 +7046,18 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, rc = lpfc_sli4_post_sync_mbox(phba, mboxq); if (rc != MBX_SUCCESS) lpfc_printf_log(phba, KERN_ERR, - LOG_MBOX | LOG_SLI, - "(%d):2597 Mailbox command " - "x%x (x%x) cannot issue " - "Data: x%x x%x\n", - mboxq->vport ? - mboxq->vport->vpi : 0, - mboxq->u.mb.mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, - mboxq), - psli->sli_flag, flag); + LOG_MBOX | LOG_SLI, + "(%d):2597 Mailbox command " + "x%x (x%x/x%x) cannot issue " + "Data: x%x x%x\n", + mboxq->vport ? + mboxq->vport->vpi : 0, + mboxq->u.mb.mbxCommand, + lpfc_sli_config_mbox_subsys_get(phba, + mboxq), + lpfc_sli_config_mbox_opcode_get(phba, + mboxq), + psli->sli_flag, flag); /* Unblock the async mailbox posting afterward */ lpfc_sli4_async_mbox_unblock(phba); } @@ -6856,11 +7068,12 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, rc = lpfc_mbox_cmd_check(phba, mboxq); if (rc) { lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "(%d):2543 Mailbox command x%x (x%x) " + "(%d):2543 Mailbox command x%x (x%x/x%x) " "cannot issue Data: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, mboxq->u.mb.mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, mboxq), + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), psli->sli_flag, flag); goto out_not_finished; } @@ -6872,10 +7085,11 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, spin_unlock_irqrestore(&phba->hbalock, iflags); lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, "(%d):0354 Mbox cmd issue - Enqueue Data: " - "x%x (x%x) x%x x%x x%x\n", + "x%x (x%x/x%x) x%x x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0xffffff, bf_get(lpfc_mqe_command, &mboxq->u.mqe), - lpfc_sli4_mbox_opcode_get(phba, mboxq), + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), phba->pport->port_state, psli->sli_flag, MBX_NOWAIT); /* Wake up worker thread to transport mailbox command from head */ @@ -6952,13 +7166,14 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba) /* Start timer for the mbox_tmo and log some mailbox post messages */ mod_timer(&psli->mbox_tmo, (jiffies + - (HZ * lpfc_mbox_tmo_val(phba, mbx_cmnd)))); + (HZ * lpfc_mbox_tmo_val(phba, mboxq)))); lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "(%d):0355 Mailbox cmd x%x (x%x) issue Data: " + "(%d):0355 Mailbox cmd x%x (x%x/x%x) issue Data: " "x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, mbx_cmnd, - lpfc_sli4_mbox_opcode_get(phba, mboxq), + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), phba->pport->port_state, psli->sli_flag); if (mbx_cmnd != MBX_HEARTBEAT) { @@ -6982,11 +7197,12 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba) rc = lpfc_sli4_mq_put(phba->sli4_hba.mbx_wq, mqe); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "(%d):2533 Mailbox command x%x (x%x) " + "(%d):2533 Mailbox command x%x (x%x/x%x) " "cannot issue Data: x%x x%x\n", mboxq->vport ? mboxq->vport->vpi : 0, mboxq->u.mb.mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, mboxq), + lpfc_sli_config_mbox_subsys_get(phba, mboxq), + lpfc_sli_config_mbox_opcode_get(phba, mboxq), psli->sli_flag, MBX_NOWAIT); goto out_not_finished; } @@ -7322,6 +7538,8 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, if (inbound == 1) offset = 0; bf_set(lpfc_sli4_sge_offset, sgl, offset); + bf_set(lpfc_sli4_sge_type, sgl, + LPFC_SGE_TYPE_DATA); offset += bde.tus.f.bdeSize; } sgl->word2 = cpu_to_le32(sgl->word2); @@ -9359,7 +9577,6 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, /* now issue the command */ retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); - if (retval == MBX_BUSY || retval == MBX_SUCCESS) { wait_event_interruptible_timeout(done_q, pmboxq->mbox_flag & LPFC_MBX_WAKE, @@ -9403,23 +9620,24 @@ void lpfc_sli_mbox_sys_shutdown(struct lpfc_hba *phba) { struct lpfc_sli *psli = &phba->sli; - uint8_t actcmd = MBX_HEARTBEAT; unsigned long timeout; + timeout = msecs_to_jiffies(LPFC_MBOX_TMO * 1000) + jiffies; spin_lock_irq(&phba->hbalock); psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK; spin_unlock_irq(&phba->hbalock); if (psli->sli_flag & LPFC_SLI_ACTIVE) { spin_lock_irq(&phba->hbalock); - if (phba->sli.mbox_active) - actcmd = phba->sli.mbox_active->u.mb.mbxCommand; - spin_unlock_irq(&phba->hbalock); /* Determine how long we might wait for the active mailbox * command to be gracefully completed by firmware. */ - timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * - 1000) + jiffies; + if (phba->sli.mbox_active) + timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, + phba->sli.mbox_active) * + 1000) + jiffies; + spin_unlock_irq(&phba->hbalock); + while (phba->sli.mbox_active) { /* Check active mailbox complete status every 2ms */ msleep(2); @@ -10415,12 +10633,17 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) /* Move mbox data to caller's mailbox region, do endian swapping */ if (pmb->mbox_cmpl && mbox) lpfc_sli_pcimem_bcopy(mbox, mqe, sizeof(struct lpfc_mqe)); - /* Set the mailbox status with SLI4 range 0x4000 */ - mcqe_status = bf_get(lpfc_mcqe_status, mcqe); - if (mcqe_status != MB_CQE_STATUS_SUCCESS) - bf_set(lpfc_mqe_status, mqe, - (LPFC_MBX_ERROR_RANGE | mcqe_status)); + /* + * For mcqe errors, conditionally move a modified error code to + * the mbox so that the error will not be missed. + */ + mcqe_status = bf_get(lpfc_mcqe_status, mcqe); + if (mcqe_status != MB_CQE_STATUS_SUCCESS) { + if (bf_get(lpfc_mqe_status, mqe) == MBX_SUCCESS) + bf_set(lpfc_mqe_status, mqe, + (LPFC_MBX_ERROR_RANGE | mcqe_status)); + } if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) { pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_MBOX_VPORT, @@ -10796,7 +11019,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe) case LPFC_MCQ: while ((cqe = lpfc_sli4_cq_get(cq))) { workposted |= lpfc_sli4_sp_handle_mcqe(phba, cqe); - if (!(++ecount % LPFC_GET_QE_REL_INT)) + if (!(++ecount % cq->entry_repost)) lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM); } break; @@ -10808,7 +11031,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe) else workposted |= lpfc_sli4_sp_handle_cqe(phba, cq, cqe); - if (!(++ecount % LPFC_GET_QE_REL_INT)) + if (!(++ecount % cq->entry_repost)) lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM); } break; @@ -11040,7 +11263,7 @@ lpfc_sli4_fp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, /* Process all the entries to the CQ */ while ((cqe = lpfc_sli4_cq_get(cq))) { workposted |= lpfc_sli4_fp_handle_wcqe(phba, cq, cqe); - if (!(++ecount % LPFC_GET_QE_REL_INT)) + if (!(++ecount % cq->entry_repost)) lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM); } @@ -11110,6 +11333,8 @@ lpfc_sli4_sp_intr_handler(int irq, void *dev_id) /* Get to the EQ struct associated with this vector */ speq = phba->sli4_hba.sp_eq; + if (unlikely(!speq)) + return IRQ_NONE; /* Check device state for handling interrupt */ if (unlikely(lpfc_intr_state_check(phba))) { @@ -11127,7 +11352,7 @@ lpfc_sli4_sp_intr_handler(int irq, void *dev_id) */ while ((eqe = lpfc_sli4_eq_get(speq))) { lpfc_sli4_sp_handle_eqe(phba, eqe); - if (!(++ecount % LPFC_GET_QE_REL_INT)) + if (!(++ecount % speq->entry_repost)) lpfc_sli4_eq_release(speq, LPFC_QUEUE_NOARM); } @@ -11187,6 +11412,8 @@ lpfc_sli4_fp_intr_handler(int irq, void *dev_id) if (unlikely(!phba)) return IRQ_NONE; + if (unlikely(!phba->sli4_hba.fp_eq)) + return IRQ_NONE; /* Get to the EQ struct associated with this vector */ fpeq = phba->sli4_hba.fp_eq[fcp_eqidx]; @@ -11207,7 +11434,7 @@ lpfc_sli4_fp_intr_handler(int irq, void *dev_id) */ while ((eqe = lpfc_sli4_eq_get(fpeq))) { lpfc_sli4_fp_handle_eqe(phba, eqe, fcp_eqidx); - if (!(++ecount % LPFC_GET_QE_REL_INT)) + if (!(++ecount % fpeq->entry_repost)) lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_NOARM); } @@ -11359,6 +11586,15 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size, } queue->entry_size = entry_size; queue->entry_count = entry_count; + + /* + * entry_repost is calculated based on the number of entries in the + * queue. This works out except for RQs. If buffers are NOT initially + * posted for every RQE, entry_repost should be adjusted accordingly. + */ + queue->entry_repost = (entry_count >> 3); + if (queue->entry_repost < LPFC_QUEUE_MIN_REPOST) + queue->entry_repost = LPFC_QUEUE_MIN_REPOST; queue->phba = phba; return queue; @@ -11924,6 +12160,31 @@ out: } /** + * lpfc_rq_adjust_repost - Adjust entry_repost for an RQ + * @phba: HBA structure that indicates port to create a queue on. + * @rq: The queue structure to use for the receive queue. + * @qno: The associated HBQ number + * + * + * For SLI4 we need to adjust the RQ repost value based on + * the number of buffers that are initially posted to the RQ. + */ +void +lpfc_rq_adjust_repost(struct lpfc_hba *phba, struct lpfc_queue *rq, int qno) +{ + uint32_t cnt; + + cnt = lpfc_hbq_defs[qno]->entry_count; + + /* Recalc repost for RQs based on buffers initially posted */ + cnt = (cnt >> 3); + if (cnt < LPFC_QUEUE_MIN_REPOST) + cnt = LPFC_QUEUE_MIN_REPOST; + + rq->entry_repost = cnt; +} + +/** * lpfc_rq_create - Create a Receive Queue on the HBA * @phba: HBA structure that indicates port to create a queue on. * @hrq: The queue structure to use to create the header receive queue. @@ -12489,7 +12750,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } /* The IOCTL status is embedded in the mailbox subheader. */ @@ -12704,7 +12965,7 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba) if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr; @@ -12867,7 +13128,7 @@ lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba) if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr; @@ -12991,7 +13252,7 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist, if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr; @@ -13147,7 +13408,7 @@ lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *phba, struct list_head *sblist, if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr; @@ -13296,7 +13557,8 @@ lpfc_fc_frame_to_vport(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr, uint32_t did = (fc_hdr->fh_d_id[0] << 16 | fc_hdr->fh_d_id[1] << 8 | fc_hdr->fh_d_id[2]); - + if (did == Fabric_DID) + return phba->pport; vports = lpfc_create_vport_work_array(phba); if (vports != NULL) for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { @@ -14312,7 +14574,7 @@ lpfc_sli4_init_vpi(struct lpfc_vport *vport) if (!mboxq) return -ENOMEM; lpfc_init_vpi(phba, mboxq, vport->vpi); - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI); + mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq); rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); if (rc != MBX_SUCCESS) { lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, @@ -15188,7 +15450,7 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list, if (!phba->sli4_hba.intr_enable) rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); else { - mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); + mbox_tmo = lpfc_mbox_tmo_val(phba, mbox); rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); } /* The IOCTL status is embedded in the mailbox subheader. */ diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index a0075b0..29c13b6 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -293,13 +293,11 @@ struct lpfc_sli { struct lpfc_lnk_stat lnk_stat_offsets; }; -#define LPFC_MBOX_TMO 30 /* Sec tmo for outstanding mbox - command */ -#define LPFC_MBOX_SLI4_CONFIG_TMO 60 /* Sec tmo for outstanding mbox - command */ -#define LPFC_MBOX_TMO_FLASH_CMD 300 /* Sec tmo for outstanding FLASH write - * or erase cmds. This is especially - * long because of the potential of - * multiple flash erases that can be - * spawned. - */ +/* Timeout for normal outstanding mbox command (Seconds) */ +#define LPFC_MBOX_TMO 30 +/* Timeout for non-flash-based outstanding sli_config mbox command (Seconds) */ +#define LPFC_MBOX_SLI4_CONFIG_TMO 60 +/* Timeout for flash-based outstanding sli_config mbox command (Seconds) */ +#define LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO 300 +/* Timeout for other flash-based outstanding mbox command (Seconds) */ +#define LPFC_MBOX_TMO_FLASH_CMD 300 diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 19bb87a..d5cffd8 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -23,7 +23,6 @@ #define LPFC_XRI_EXCH_BUSY_WAIT_T1 10 #define LPFC_XRI_EXCH_BUSY_WAIT_T2 30000 #define LPFC_RELEASE_NOTIFICATION_INTERVAL 32 -#define LPFC_GET_QE_REL_INT 32 #define LPFC_RPI_LOW_WATER_MARK 10 #define LPFC_UNREG_FCF 1 @@ -126,6 +125,8 @@ struct lpfc_queue { struct list_head child_list; uint32_t entry_count; /* Number of entries to support on the queue */ uint32_t entry_size; /* Size of each queue entry. */ + uint32_t entry_repost; /* Count of entries before doorbell is rung */ +#define LPFC_QUEUE_MIN_REPOST 8 uint32_t queue_id; /* Queue ID assigned by the hardware */ uint32_t assoc_qid; /* Queue ID associated with, for CQ/WQ/MQ */ struct list_head page_list; @@ -388,6 +389,16 @@ struct lpfc_iov { uint32_t vf_number; }; +struct lpfc_sli4_lnk_info { + uint8_t lnk_dv; +#define LPFC_LNK_DAT_INVAL 0 +#define LPFC_LNK_DAT_VAL 1 + uint8_t lnk_tp; +#define LPFC_LNK_GE 0x0 /* FCoE */ +#define LPFC_LNK_FC 0x1 /* FC */ + uint8_t lnk_no; +}; + /* SLI4 HBA data structure entries */ struct lpfc_sli4_hba { void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for @@ -503,6 +514,10 @@ struct lpfc_sli4_hba { struct list_head sp_els_xri_aborted_work_queue; struct list_head sp_unsol_work_queue; struct lpfc_sli4_link link_state; + struct lpfc_sli4_lnk_info lnk_info; + uint32_t pport_name_sta; +#define LPFC_SLI4_PPNAME_NON 0 +#define LPFC_SLI4_PPNAME_GET 1 struct lpfc_iov iov; spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */ @@ -553,6 +568,7 @@ struct lpfc_rsrc_blks { * SLI4 specific function prototypes */ int lpfc_pci_function_reset(struct lpfc_hba *); +int lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *); int lpfc_sli4_hba_setup(struct lpfc_hba *); int lpfc_sli4_config(struct lpfc_hba *, struct lpfcMboxq *, uint8_t, uint8_t, uint32_t, bool); @@ -576,6 +592,7 @@ uint32_t lpfc_wq_create(struct lpfc_hba *, struct lpfc_queue *, struct lpfc_queue *, uint32_t); uint32_t lpfc_rq_create(struct lpfc_hba *, struct lpfc_queue *, struct lpfc_queue *, struct lpfc_queue *, uint32_t); +void lpfc_rq_adjust_repost(struct lpfc_hba *, struct lpfc_queue *, int); uint32_t lpfc_eq_destroy(struct lpfc_hba *, struct lpfc_queue *); uint32_t lpfc_cq_destroy(struct lpfc_hba *, struct lpfc_queue *); uint32_t lpfc_mq_destroy(struct lpfc_hba *, struct lpfc_queue *); @@ -632,5 +649,5 @@ void lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_sli4_unregister_fcf(struct lpfc_hba *); int lpfc_sli4_post_status_check(struct lpfc_hba *); -uint8_t lpfc_sli4_mbox_opcode_get(struct lpfc_hba *, struct lpfcMboxq *); - +uint8_t lpfc_sli_config_mbox_subsys_get(struct lpfc_hba *, LPFC_MBOXQ_t *); +uint8_t lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *, LPFC_MBOXQ_t *); diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index c1e0ae9..b0630e3 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.25" +#define LPFC_DRIVER_VERSION "8.3.27" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 1feb551..cff6ca6 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -692,13 +692,14 @@ lpfc_vport_delete(struct fc_vport *fc_vport) /* Indicate free memory when release */ NLP_SET_FREE_REQ(ndlp); } else { - if (!NLP_CHK_NODE_ACT(ndlp)) + if (!NLP_CHK_NODE_ACT(ndlp)) { ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); if (!ndlp) goto skip_logo; + } - /* Remove ndlp from vport npld list */ + /* Remove ndlp from vport list */ lpfc_dequeue_node(vport, ndlp); spin_lock_irq(&phba->ndlp_lock); if (!NLP_CHK_FREE_REQ(ndlp)) @@ -711,8 +712,17 @@ lpfc_vport_delete(struct fc_vport *fc_vport) } spin_unlock_irq(&phba->ndlp_lock); } - if (!(vport->vpi_state & LPFC_VPI_REGISTERED)) + + /* + * If the vpi is not registered, then a valid FDISC doesn't + * exist and there is no need for a ELS LOGO. Just cleanup + * the ndlp. + */ + if (!(vport->vpi_state & LPFC_VPI_REGISTERED)) { + lpfc_nlp_put(ndlp); goto skip_logo; + } + vport->unreg_vpi_cmpl = VPORT_INVAL; timeout = msecs_to_jiffies(phba->fc_ratov * 2000); if (!lpfc_issue_els_npiv_logo(vport, ndlp)) |