diff options
| author | James Smart <James.Smart@Emulex.Com> | 2007-10-27 13:37:53 -0400 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:22:33 -0500 |
| commit | a8adb83208020c913f010cb4e26d09e25300db8e (patch) | |
| tree | 2245ca9f0dba5139946c99d45b80e7f2ce324b74 | |
| parent | 87af33fe5f78c27cf9e43c6e586dd6efd4be3e40 (diff) | |
[SCSI] lpfc 8.2.3 : Miscellaneous Small Fixes - part 2
Miscellaneous Small Fixes - part 2
- Fix ndlp left in PLOGI state after link up
- Fix cannot rcv unsol ELS frames after running HBA resets for a few minutes
- Fix HBQ buffer_count implemention
- Fix RPI leak
- Fix crash while deleting vports while HBA is reset
- Revert the FCP Fbits offset back to 7
- Fix panic when deleting vports
- Remove unused code in switch statement outside of a case
- Reject PLOGI from invalid PName or NName of 0
- Ignore PLOGI responses from WWPName or WWNName of 0
- Fix debugfs hbqinfo display for ppc
- Added 8G to list of supported speeds for sysfs parameter
- Defer ndlp cleanup to dev-loss timeout handler
- Added support for WRITE_VPARMS mailbox command by applications
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
| -rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 8 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 13 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 34 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 67 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 7 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 22 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 30 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 10 |
10 files changed, 152 insertions, 41 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index ff6b7d33ccab..636a930a5739 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
| @@ -367,6 +367,7 @@ struct lpfc_vport { | |||
| 367 | 367 | ||
| 368 | struct hbq_s { | 368 | struct hbq_s { |
| 369 | uint16_t entry_count; /* Current number of HBQ slots */ | 369 | uint16_t entry_count; /* Current number of HBQ slots */ |
| 370 | uint16_t buffer_count; /* Current number of buffers posted */ | ||
| 370 | uint32_t next_hbqPutIdx; /* Index to next HBQ slot to use */ | 371 | uint32_t next_hbqPutIdx; /* Index to next HBQ slot to use */ |
| 371 | uint32_t hbqPutIdx; /* HBQ slot to use */ | 372 | uint32_t hbqPutIdx; /* HBQ slot to use */ |
| 372 | uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */ | 373 | uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */ |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index e8e9905828c9..4e9e890449a3 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
| @@ -187,12 +187,9 @@ lpfc_state_show(struct class_device *cdev, char *buf) | |||
| 187 | case LPFC_LINK_UP: | 187 | case LPFC_LINK_UP: |
| 188 | case LPFC_CLEAR_LA: | 188 | case LPFC_CLEAR_LA: |
| 189 | case LPFC_HBA_READY: | 189 | case LPFC_HBA_READY: |
| 190 | len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - \n"); | 190 | len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - "); |
| 191 | 191 | ||
| 192 | switch (vport->port_state) { | 192 | switch (vport->port_state) { |
| 193 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
| 194 | "initializing\n"); | ||
| 195 | break; | ||
| 196 | case LPFC_LOCAL_CFG_LINK: | 193 | case LPFC_LOCAL_CFG_LINK: |
| 197 | len += snprintf(buf + len, PAGE_SIZE-len, | 194 | len += snprintf(buf + len, PAGE_SIZE-len, |
| 198 | "Configuring Link\n"); | 195 | "Configuring Link\n"); |
| @@ -1759,7 +1756,6 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
| 1759 | 1756 | ||
| 1760 | switch (phba->sysfs_mbox.mbox->mb.mbxCommand) { | 1757 | switch (phba->sysfs_mbox.mbox->mb.mbxCommand) { |
| 1761 | /* Offline only */ | 1758 | /* Offline only */ |
| 1762 | case MBX_WRITE_NV: | ||
| 1763 | case MBX_INIT_LINK: | 1759 | case MBX_INIT_LINK: |
| 1764 | case MBX_DOWN_LINK: | 1760 | case MBX_DOWN_LINK: |
| 1765 | case MBX_CONFIG_LINK: | 1761 | case MBX_CONFIG_LINK: |
| @@ -1782,6 +1778,8 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
| 1782 | spin_unlock_irq(&phba->hbalock); | 1778 | spin_unlock_irq(&phba->hbalock); |
| 1783 | return -EPERM; | 1779 | return -EPERM; |
| 1784 | } | 1780 | } |
| 1781 | case MBX_WRITE_NV: | ||
| 1782 | case MBX_WRITE_VPARMS: | ||
| 1785 | case MBX_LOAD_SM: | 1783 | case MBX_LOAD_SM: |
| 1786 | case MBX_READ_NV: | 1784 | case MBX_READ_NV: |
| 1787 | case MBX_READ_CONFIG: | 1785 | case MBX_READ_CONFIG: |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index d6a98bc970ff..da607c775cfc 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
| @@ -243,16 +243,17 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) | |||
| 243 | raw_index = phba->hbq_get[i]; | 243 | raw_index = phba->hbq_get[i]; |
| 244 | getidx = le32_to_cpu(raw_index); | 244 | getidx = le32_to_cpu(raw_index); |
| 245 | len += snprintf(buf+len, size-len, | 245 | len += snprintf(buf+len, size-len, |
| 246 | "entrys:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n", | 246 | "entrys:%d bufcnt:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n", |
| 247 | hbqs->entry_count, hbqs->hbqPutIdx, hbqs->next_hbqPutIdx, | 247 | hbqs->entry_count, hbqs->buffer_count, hbqs->hbqPutIdx, |
| 248 | hbqs->local_hbqGetIdx, getidx); | 248 | hbqs->next_hbqPutIdx, hbqs->local_hbqGetIdx, getidx); |
| 249 | 249 | ||
| 250 | hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt; | 250 | hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt; |
| 251 | for (j=0; j<hbqs->entry_count; j++) { | 251 | for (j=0; j<hbqs->entry_count; j++) { |
| 252 | len += snprintf(buf+len, size-len, | 252 | len += snprintf(buf+len, size-len, |
| 253 | "%03d: %08x %04x %05x ", j, | 253 | "%03d: %08x %04x %05x ", j, |
| 254 | hbqe->bde.addrLow, hbqe->bde.tus.w, hbqe->buffer_tag); | 254 | le32_to_cpu(hbqe->bde.addrLow), |
| 255 | 255 | le32_to_cpu(hbqe->bde.tus.w), | |
| 256 | le32_to_cpu(hbqe->buffer_tag)); | ||
| 256 | i = 0; | 257 | i = 0; |
| 257 | found = 0; | 258 | found = 0; |
| 258 | 259 | ||
| @@ -276,7 +277,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) | |||
| 276 | list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) { | 277 | list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) { |
| 277 | hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); | 278 | hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); |
| 278 | phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); | 279 | phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); |
| 279 | if (phys == hbqe->bde.addrLow) { | 280 | if (phys == le32_to_cpu(hbqe->bde.addrLow)) { |
| 280 | len += snprintf(buf+len, size-len, | 281 | len += snprintf(buf+len, size-len, |
| 281 | "Buf%d: %p %06x\n", i, | 282 | "Buf%d: %p %06x\n", i, |
| 282 | hbq_buf->dbuf.virt, hbq_buf->tag); | 283 | hbq_buf->dbuf.virt, hbq_buf->tag); |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 99bc1a1ecac2..cfe81c50529a 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
| @@ -91,6 +91,7 @@ struct lpfc_nodelist { | |||
| 91 | #define NLP_LOGO_SND 0x100 /* sent LOGO request for this entry */ | 91 | #define NLP_LOGO_SND 0x100 /* sent LOGO request for this entry */ |
| 92 | #define NLP_RNID_SND 0x400 /* sent RNID request for this entry */ | 92 | #define NLP_RNID_SND 0x400 /* sent RNID request for this entry */ |
| 93 | #define NLP_ELS_SND_MASK 0x7e0 /* sent ELS request for this entry */ | 93 | #define NLP_ELS_SND_MASK 0x7e0 /* sent ELS request for this entry */ |
| 94 | #define NLP_DEFER_RM 0x10000 /* Remove this ndlp if no longer used */ | ||
| 94 | #define NLP_DELAY_TMO 0x20000 /* delay timeout is running for node */ | 95 | #define NLP_DELAY_TMO 0x20000 /* delay timeout is running for node */ |
| 95 | #define NLP_NPR_2B_DISC 0x40000 /* node is included in num_disc_nodes */ | 96 | #define NLP_NPR_2B_DISC 0x40000 /* node is included in num_disc_nodes */ |
| 96 | #define NLP_RCV_PLOGI 0x80000 /* Rcv'ed PLOGI from remote system */ | 97 | #define NLP_RCV_PLOGI 0x80000 /* Rcv'ed PLOGI from remote system */ |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 0a5006ea9909..9315c3c2e6f6 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
| @@ -2069,9 +2069,25 @@ int | |||
| 2069 | lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) | 2069 | lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) |
| 2070 | { | 2070 | { |
| 2071 | struct lpfc_dmabuf *buf_ptr, *buf_ptr1; | 2071 | struct lpfc_dmabuf *buf_ptr, *buf_ptr1; |
| 2072 | struct lpfc_nodelist *ndlp; | ||
| 2072 | 2073 | ||
| 2073 | if (elsiocb->context1) { | 2074 | ndlp = (struct lpfc_nodelist *)elsiocb->context1; |
| 2074 | lpfc_nlp_put(elsiocb->context1); | 2075 | if (ndlp) { |
| 2076 | if (ndlp->nlp_flag & NLP_DEFER_RM) { | ||
| 2077 | lpfc_nlp_put(ndlp); | ||
| 2078 | |||
| 2079 | /* If the ndlp is not being used by another discovery | ||
| 2080 | * thread, free it. | ||
| 2081 | */ | ||
| 2082 | if (!lpfc_nlp_not_used(ndlp)) { | ||
| 2083 | /* If ndlp is being used by another discovery | ||
| 2084 | * thread, just clear NLP_DEFER_RM | ||
| 2085 | */ | ||
| 2086 | ndlp->nlp_flag &= ~NLP_DEFER_RM; | ||
| 2087 | } | ||
| 2088 | } | ||
| 2089 | else | ||
| 2090 | lpfc_nlp_put(ndlp); | ||
| 2075 | elsiocb->context1 = NULL; | 2091 | elsiocb->context1 = NULL; |
| 2076 | } | 2092 | } |
| 2077 | /* context2 = cmd, context2->next = rsp, context3 = bpl */ | 2093 | /* context2 = cmd, context2->next = rsp, context3 = bpl */ |
| @@ -2130,13 +2146,15 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 2130 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 2146 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
| 2131 | kfree(mp); | 2147 | kfree(mp); |
| 2132 | mempool_free(pmb, phba->mbox_mem_pool); | 2148 | mempool_free(pmb, phba->mbox_mem_pool); |
| 2133 | lpfc_nlp_put(ndlp); | 2149 | if (ndlp) { |
| 2150 | lpfc_nlp_put(ndlp); | ||
| 2134 | 2151 | ||
| 2135 | /* This is the end of the default RPI cleanup logic for this | 2152 | /* This is the end of the default RPI cleanup logic for this |
| 2136 | * ndlp. If no other discovery threads are using this ndlp. | 2153 | * ndlp. If no other discovery threads are using this ndlp. |
| 2137 | * we should free all resources associated with it. | 2154 | * we should free all resources associated with it. |
| 2138 | */ | 2155 | */ |
| 2139 | lpfc_nlp_not_used(ndlp); | 2156 | lpfc_nlp_not_used(ndlp); |
| 2157 | } | ||
| 2140 | return; | 2158 | return; |
| 2141 | } | 2159 | } |
| 2142 | 2160 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f64ce88e8a06..371f41e886d6 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
| @@ -108,6 +108,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
| 108 | struct lpfc_vport *vport; | 108 | struct lpfc_vport *vport; |
| 109 | struct lpfc_hba *phba; | 109 | struct lpfc_hba *phba; |
| 110 | struct lpfc_work_evt *evtp; | 110 | struct lpfc_work_evt *evtp; |
| 111 | int put_node; | ||
| 112 | int put_rport; | ||
| 111 | 113 | ||
| 112 | rdata = rport->dd_data; | 114 | rdata = rport->dd_data; |
| 113 | ndlp = rdata->pnode; | 115 | ndlp = rdata->pnode; |
| @@ -128,6 +130,25 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
| 128 | "rport devlosscb: sid:x%x did:x%x flg:x%x", | 130 | "rport devlosscb: sid:x%x did:x%x flg:x%x", |
| 129 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); | 131 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); |
| 130 | 132 | ||
| 133 | /* Don't defer this if we are in the process of deleting the vport | ||
| 134 | * or unloading the driver. The unload will cleanup the node | ||
| 135 | * appropriately we just need to cleanup the ndlp rport info here. | ||
| 136 | */ | ||
| 137 | if (vport->load_flag & FC_UNLOADING) { | ||
| 138 | put_node = rdata->pnode != NULL; | ||
| 139 | put_rport = ndlp->rport != NULL; | ||
| 140 | rdata->pnode = NULL; | ||
| 141 | ndlp->rport = NULL; | ||
| 142 | if (put_node) | ||
| 143 | lpfc_nlp_put(ndlp); | ||
| 144 | if (put_rport) | ||
| 145 | put_device(&rport->dev); | ||
| 146 | return; | ||
| 147 | } | ||
| 148 | |||
| 149 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) | ||
| 150 | return; | ||
| 151 | |||
| 131 | evtp = &ndlp->dev_loss_evt; | 152 | evtp = &ndlp->dev_loss_evt; |
| 132 | 153 | ||
| 133 | if (!list_empty(&evtp->evt_listp)) | 154 | if (!list_empty(&evtp->evt_listp)) |
| @@ -175,8 +196,23 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
| 175 | "rport devlosstmo:did:x%x type:x%x id:x%x", | 196 | "rport devlosstmo:did:x%x type:x%x id:x%x", |
| 176 | ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id); | 197 | ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id); |
| 177 | 198 | ||
| 178 | if (!(vport->load_flag & FC_UNLOADING) && | 199 | /* Don't defer this if we are in the process of deleting the vport |
| 179 | ndlp->nlp_state == NLP_STE_MAPPED_NODE) | 200 | * or unloading the driver. The unload will cleanup the node |
| 201 | * appropriately we just need to cleanup the ndlp rport info here. | ||
| 202 | */ | ||
| 203 | if (vport->load_flag & FC_UNLOADING) { | ||
| 204 | put_node = rdata->pnode != NULL; | ||
| 205 | put_rport = ndlp->rport != NULL; | ||
| 206 | rdata->pnode = NULL; | ||
| 207 | ndlp->rport = NULL; | ||
| 208 | if (put_node) | ||
| 209 | lpfc_nlp_put(ndlp); | ||
| 210 | if (put_rport) | ||
| 211 | put_device(&rport->dev); | ||
| 212 | return; | ||
| 213 | } | ||
| 214 | |||
| 215 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) | ||
| 180 | return; | 216 | return; |
| 181 | 217 | ||
| 182 | if (ndlp->nlp_type & NLP_FABRIC) { | 218 | if (ndlp->nlp_type & NLP_FABRIC) { |
| @@ -1965,12 +2001,39 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 1965 | static void | 2001 | static void |
| 1966 | lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 2002 | lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
| 1967 | { | 2003 | { |
| 2004 | struct lpfc_hba *phba = vport->phba; | ||
| 1968 | struct lpfc_rport_data *rdata; | 2005 | struct lpfc_rport_data *rdata; |
| 2006 | LPFC_MBOXQ_t *mbox; | ||
| 2007 | int rc; | ||
| 1969 | 2008 | ||
| 1970 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { | 2009 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { |
| 1971 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | 2010 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
| 1972 | } | 2011 | } |
| 1973 | 2012 | ||
| 2013 | if (ndlp->nlp_flag & NLP_DEFER_RM && !ndlp->nlp_rpi) { | ||
| 2014 | /* For this case we need to cleanup the default rpi | ||
| 2015 | * allocated by the firmware. | ||
| 2016 | */ | ||
| 2017 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) | ||
| 2018 | != NULL) { | ||
| 2019 | rc = lpfc_reg_login(phba, vport->vpi, ndlp->nlp_DID, | ||
| 2020 | (uint8_t *) &vport->fc_sparam, mbox, 0); | ||
| 2021 | if (rc) { | ||
| 2022 | mempool_free(mbox, phba->mbox_mem_pool); | ||
| 2023 | } | ||
| 2024 | else { | ||
| 2025 | mbox->mbox_flag |= LPFC_MBX_IMED_UNREG; | ||
| 2026 | mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; | ||
| 2027 | mbox->vport = vport; | ||
| 2028 | mbox->context2 = 0; | ||
| 2029 | rc =lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | ||
| 2030 | if (rc == MBX_NOT_FINISHED) { | ||
| 2031 | mempool_free(mbox, phba->mbox_mem_pool); | ||
| 2032 | } | ||
| 2033 | } | ||
| 2034 | } | ||
| 2035 | } | ||
| 2036 | |||
| 1974 | lpfc_cleanup_node(vport, ndlp); | 2037 | lpfc_cleanup_node(vport, ndlp); |
| 1975 | 2038 | ||
| 1976 | /* | 2039 | /* |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index b075d5956488..8635b9294640 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
| @@ -153,11 +153,7 @@ struct lpfc_sli_ct_request { | |||
| 153 | struct gff_acc { | 153 | struct gff_acc { |
| 154 | uint8_t fbits[128]; | 154 | uint8_t fbits[128]; |
| 155 | } gff_acc; | 155 | } gff_acc; |
| 156 | #ifdef __BIG_ENDIAN_BITFIELD | ||
| 157 | #define FCP_TYPE_FEATURE_OFFSET 7 | 156 | #define FCP_TYPE_FEATURE_OFFSET 7 |
| 158 | #else /* __LITTLE_ENDIAN_BITFIELD */ | ||
| 159 | #define FCP_TYPE_FEATURE_OFFSET 4 | ||
| 160 | #endif | ||
| 161 | struct rff { | 157 | struct rff { |
| 162 | uint32_t PortId; | 158 | uint32_t PortId; |
| 163 | uint8_t reserved[2]; | 159 | uint8_t reserved[2]; |
| @@ -1288,8 +1284,9 @@ typedef struct { /* FireFly BIU registers */ | |||
| 1288 | #define MBX_KILL_BOARD 0x24 | 1284 | #define MBX_KILL_BOARD 0x24 |
| 1289 | #define MBX_CONFIG_FARP 0x25 | 1285 | #define MBX_CONFIG_FARP 0x25 |
| 1290 | #define MBX_BEACON 0x2A | 1286 | #define MBX_BEACON 0x2A |
| 1291 | #define MBX_ASYNCEVT_ENABLE 0x33 | ||
| 1292 | #define MBX_HEARTBEAT 0x31 | 1287 | #define MBX_HEARTBEAT 0x31 |
| 1288 | #define MBX_WRITE_VPARMS 0x32 | ||
| 1289 | #define MBX_ASYNCEVT_ENABLE 0x33 | ||
| 1293 | 1290 | ||
| 1294 | #define MBX_CONFIG_HBQ 0x7C | 1291 | #define MBX_CONFIG_HBQ 0x7C |
| 1295 | #define MBX_LOAD_AREA 0x81 | 1292 | #define MBX_LOAD_AREA 0x81 |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index ceb185fa3216..db96f7504a14 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
| @@ -1339,6 +1339,7 @@ lpfc_cleanup(struct lpfc_vport *vport) | |||
| 1339 | { | 1339 | { |
| 1340 | struct lpfc_hba *phba = vport->phba; | 1340 | struct lpfc_hba *phba = vport->phba; |
| 1341 | struct lpfc_nodelist *ndlp, *next_ndlp; | 1341 | struct lpfc_nodelist *ndlp, *next_ndlp; |
| 1342 | int i = 0; | ||
| 1342 | 1343 | ||
| 1343 | if (phba->link_state > LPFC_LINK_DOWN) | 1344 | if (phba->link_state > LPFC_LINK_DOWN) |
| 1344 | lpfc_port_link_failure(vport); | 1345 | lpfc_port_link_failure(vport); |
| @@ -1351,17 +1352,20 @@ lpfc_cleanup(struct lpfc_vport *vport) | |||
| 1351 | NLP_EVT_DEVICE_RM); | 1352 | NLP_EVT_DEVICE_RM); |
| 1352 | } | 1353 | } |
| 1353 | 1354 | ||
| 1354 | /* At this point, ALL ndlp's should be gone */ | 1355 | /* At this point, ALL ndlp's should be gone |
| 1356 | * because of the previous NLP_EVT_DEVICE_RM. | ||
| 1357 | * Lets wait for this to happen, if needed. | ||
| 1358 | */ | ||
| 1355 | while (!list_empty(&vport->fc_nodes)) { | 1359 | while (!list_empty(&vport->fc_nodes)) { |
| 1356 | 1360 | ||
| 1357 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, | 1361 | if (i++ > 3000) { |
| 1358 | nlp_listp) { | ||
| 1359 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | 1362 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, |
| 1360 | "0233 Nodelist x%x not free: %d\n", | 1363 | "0233 Nodelist not empty\n"); |
| 1361 | ndlp->nlp_DID, | 1364 | break; |
| 1362 | atomic_read(&ndlp->kref.refcount)); | ||
| 1363 | lpfc_drop_node(vport, ndlp); | ||
| 1364 | } | 1365 | } |
| 1366 | |||
| 1367 | /* Wait for any activity on ndlps to settle */ | ||
| 1368 | msleep(10); | ||
| 1365 | } | 1369 | } |
| 1366 | return; | 1370 | return; |
| 1367 | } | 1371 | } |
| @@ -1499,6 +1503,8 @@ lpfc_offline_prep(struct lpfc_hba * phba) | |||
| 1499 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { | 1503 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { |
| 1500 | struct Scsi_Host *shost; | 1504 | struct Scsi_Host *shost; |
| 1501 | 1505 | ||
| 1506 | if (vports[i]->load_flag & FC_UNLOADING) | ||
| 1507 | continue; | ||
| 1502 | shost = lpfc_shost_from_vport(vports[i]); | 1508 | shost = lpfc_shost_from_vport(vports[i]); |
| 1503 | list_for_each_entry_safe(ndlp, next_ndlp, | 1509 | list_for_each_entry_safe(ndlp, next_ndlp, |
| 1504 | &vports[i]->fc_nodes, | 1510 | &vports[i]->fc_nodes, |
| @@ -1771,6 +1777,8 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost) | |||
| 1771 | fc_host_supported_speeds(shost) = 0; | 1777 | fc_host_supported_speeds(shost) = 0; |
| 1772 | if (phba->lmt & LMT_10Gb) | 1778 | if (phba->lmt & LMT_10Gb) |
| 1773 | fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT; | 1779 | fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT; |
| 1780 | if (phba->lmt & LMT_8Gb) | ||
| 1781 | fc_host_supported_speeds(shost) |= FC_PORTSPEED_8GBIT; | ||
| 1774 | if (phba->lmt & LMT_4Gb) | 1782 | if (phba->lmt & LMT_4Gb) |
| 1775 | fc_host_supported_speeds(shost) |= FC_PORTSPEED_4GBIT; | 1783 | fc_host_supported_speeds(shost) |= FC_PORTSPEED_4GBIT; |
| 1776 | if (phba->lmt & LMT_2Gb) | 1784 | if (phba->lmt & LMT_2Gb) |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index bba1fb6103f6..c654c787c3e6 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
| @@ -287,6 +287,24 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 287 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 287 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
| 288 | lp = (uint32_t *) pcmd->virt; | 288 | lp = (uint32_t *) pcmd->virt; |
| 289 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); | 289 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); |
| 290 | if (wwn_to_u64(sp->portName.u.wwn) == 0) { | ||
| 291 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
| 292 | "0140 PLOGI Reject: invalid nname\n"); | ||
| 293 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
| 294 | stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_PNAME; | ||
| 295 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, | ||
| 296 | NULL); | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | if (wwn_to_u64(sp->nodeName.u.wwn) == 0) { | ||
| 300 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
| 301 | "0141 PLOGI Reject: invalid pname\n"); | ||
| 302 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
| 303 | stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_NNAME; | ||
| 304 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, | ||
| 305 | NULL); | ||
| 306 | return 0; | ||
| 307 | } | ||
| 290 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) { | 308 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) { |
| 291 | /* Reject this request because invalid parameters */ | 309 | /* Reject this request because invalid parameters */ |
| 292 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 310 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| @@ -821,6 +839,12 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, | |||
| 821 | 839 | ||
| 822 | lp = (uint32_t *) prsp->virt; | 840 | lp = (uint32_t *) prsp->virt; |
| 823 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); | 841 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); |
| 842 | if (wwn_to_u64(sp->portName.u.wwn) == 0 || | ||
| 843 | wwn_to_u64(sp->nodeName.u.wwn) == 0) { | ||
| 844 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
| 845 | "0142 PLOGI RSP: Invalid WWN.\n"); | ||
| 846 | goto out; | ||
| 847 | } | ||
| 824 | if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3)) | 848 | if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3)) |
| 825 | goto out; | 849 | goto out; |
| 826 | /* PLOGI chkparm OK */ | 850 | /* PLOGI chkparm OK */ |
| @@ -906,9 +930,7 @@ out: | |||
| 906 | "0261 Cannot Register NameServer login\n"); | 930 | "0261 Cannot Register NameServer login\n"); |
| 907 | } | 931 | } |
| 908 | 932 | ||
| 909 | /* Free this node since the driver cannot login or has the wrong | 933 | ndlp->nlp_flag |= NLP_DEFER_RM; |
| 910 | sparm */ | ||
| 911 | lpfc_nlp_not_used(ndlp); | ||
| 912 | return NLP_STE_FREED_NODE; | 934 | return NLP_STE_FREED_NODE; |
| 913 | } | 935 | } |
| 914 | 936 | ||
| @@ -1795,7 +1817,7 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1795 | 1817 | ||
| 1796 | irsp = &rspiocb->iocb; | 1818 | irsp = &rspiocb->iocb; |
| 1797 | if (irsp->ulpStatus) { | 1819 | if (irsp->ulpStatus) { |
| 1798 | lpfc_nlp_not_used(ndlp); | 1820 | ndlp->nlp_flag |= NLP_DEFER_RM; |
| 1799 | return NLP_STE_FREED_NODE; | 1821 | return NLP_STE_FREED_NODE; |
| 1800 | } | 1822 | } |
| 1801 | return ndlp->nlp_state; | 1823 | return ndlp->nlp_state; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 49f2fdd2ba2b..c3743d6f445b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -540,6 +540,7 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) | |||
| 540 | list_del(&hbq_buf->dbuf.list); | 540 | list_del(&hbq_buf->dbuf.list); |
| 541 | (phba->hbqs[i].hbq_free_buffer)(phba, hbq_buf); | 541 | (phba->hbqs[i].hbq_free_buffer)(phba, hbq_buf); |
| 542 | } | 542 | } |
| 543 | phba->hbqs[i].buffer_count = 0; | ||
| 543 | } | 544 | } |
| 544 | } | 545 | } |
| 545 | 546 | ||
| @@ -608,8 +609,8 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) | |||
| 608 | return 0; | 609 | return 0; |
| 609 | } | 610 | } |
| 610 | 611 | ||
| 611 | start = lpfc_hbq_defs[hbqno]->buffer_count; | 612 | start = phba->hbqs[hbqno].buffer_count; |
| 612 | end = count + lpfc_hbq_defs[hbqno]->buffer_count; | 613 | end = count + start; |
| 613 | if (end > lpfc_hbq_defs[hbqno]->entry_count) { | 614 | if (end > lpfc_hbq_defs[hbqno]->entry_count) { |
| 614 | end = lpfc_hbq_defs[hbqno]->entry_count; | 615 | end = lpfc_hbq_defs[hbqno]->entry_count; |
| 615 | } | 616 | } |
| @@ -621,7 +622,7 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) | |||
| 621 | return 1; | 622 | return 1; |
| 622 | hbq_buffer->tag = (i | (hbqno << 16)); | 623 | hbq_buffer->tag = (i | (hbqno << 16)); |
| 623 | if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) | 624 | if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) |
| 624 | lpfc_hbq_defs[hbqno]->buffer_count++; | 625 | phba->hbqs[hbqno].buffer_count++; |
| 625 | else | 626 | else |
| 626 | (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer); | 627 | (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer); |
| 627 | } | 628 | } |
| @@ -661,7 +662,7 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) | |||
| 661 | } | 662 | } |
| 662 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT, | 663 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT, |
| 663 | "1803 Bad hbq tag. Data: x%x x%x\n", | 664 | "1803 Bad hbq tag. Data: x%x x%x\n", |
| 664 | tag, lpfc_hbq_defs[tag >> 16]->buffer_count); | 665 | tag, phba->hbqs[tag >> 16].buffer_count); |
| 665 | return NULL; | 666 | return NULL; |
| 666 | } | 667 | } |
| 667 | 668 | ||
| @@ -687,6 +688,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) | |||
| 687 | case MBX_LOAD_SM: | 688 | case MBX_LOAD_SM: |
| 688 | case MBX_READ_NV: | 689 | case MBX_READ_NV: |
| 689 | case MBX_WRITE_NV: | 690 | case MBX_WRITE_NV: |
| 691 | case MBX_WRITE_VPARMS: | ||
| 690 | case MBX_RUN_BIU_DIAG: | 692 | case MBX_RUN_BIU_DIAG: |
| 691 | case MBX_INIT_LINK: | 693 | case MBX_INIT_LINK: |
| 692 | case MBX_DOWN_LINK: | 694 | case MBX_DOWN_LINK: |
