diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-08-02 11:10:31 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-08-01 13:24:10 -0400 |
commit | 51ef4c26891a734bc8416b639ad460a8162926bc (patch) | |
tree | 8279e11bf1a0a3200e8aa9bb3d956345ef73533c /drivers/scsi/lpfc | |
parent | 78b2d852a88cd2a55e3ab632109de045d58b83e3 (diff) |
[SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes
- Fix vport ndlp ref counting errors
- Fix use after free of ndlp structure
- Use the correct flag to check for LOADING setting.
- Fix driver unload bugs (related to shost references) after link down or rscn
- Fix up HBQ initialization
- Fix port_list locking around driver unload.
- Fix references to hostdata as a phba
- Fix GFFID type offset to work correctly with big endian structure.
- Only call pci_disable_msi if the pci_enable_msi succeeded
- Fix vport_delete wait/fail if in discovery
- Put a reference on the nameservers ndlp when performing CT traffic.
- Remove unbalanced hba unlock.
- Fix up HBQ processing
- Fix lpfc debugfs discovery trace output for ELS rsp cmpl
- Send ADISC when rpi is 0
- Stop FDISC retrying forever
- Unable to retrieve correct config parameter for vport
- Fix sli_validate_fcp_iocb, sli_sum_iocb, sli_abort_iocb to be vport-aware.
- Fix index-out-of-range error in iocb. Spotted by Coverity.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 33 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 29 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 18 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 19 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 11 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 64 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 53 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 86 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mem.c | 32 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 31 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 26 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 128 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 40 |
16 files changed, 342 insertions, 246 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index a6dd13e05ab2..c28db0521c01 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -78,6 +78,7 @@ struct lpfc_dma_pool { | |||
78 | 78 | ||
79 | struct hbq_dmabuf { | 79 | struct hbq_dmabuf { |
80 | struct lpfc_dmabuf dbuf; | 80 | struct lpfc_dmabuf dbuf; |
81 | uint32_t size; | ||
81 | uint32_t tag; | 82 | uint32_t tag; |
82 | }; | 83 | }; |
83 | 84 | ||
@@ -329,15 +330,7 @@ struct lpfc_vport { | |||
329 | #define FC_LOADING 0x1 /* HBA in process of loading drvr */ | 330 | #define FC_LOADING 0x1 /* HBA in process of loading drvr */ |
330 | #define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */ | 331 | #define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */ |
331 | char *vname; /* Application assigned name */ | 332 | char *vname; /* Application assigned name */ |
332 | struct fc_vport *fc_vport; | ||
333 | 333 | ||
334 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
335 | struct dentry *debug_disc_trc; | ||
336 | struct dentry *debug_nodelist; | ||
337 | struct dentry *vport_debugfs_root; | ||
338 | struct lpfc_debugfs_trc *disc_trc; | ||
339 | atomic_t disc_trc_cnt; | ||
340 | #endif | ||
341 | /* Vport Config Parameters */ | 334 | /* Vport Config Parameters */ |
342 | uint32_t cfg_scan_down; | 335 | uint32_t cfg_scan_down; |
343 | uint32_t cfg_lun_queue_depth; | 336 | uint32_t cfg_lun_queue_depth; |
@@ -353,6 +346,16 @@ struct lpfc_vport { | |||
353 | uint32_t cfg_max_luns; | 346 | uint32_t cfg_max_luns; |
354 | 347 | ||
355 | uint32_t dev_loss_tmo_changed; | 348 | uint32_t dev_loss_tmo_changed; |
349 | |||
350 | struct fc_vport *fc_vport; | ||
351 | |||
352 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
353 | struct dentry *debug_disc_trc; | ||
354 | struct dentry *debug_nodelist; | ||
355 | struct dentry *vport_debugfs_root; | ||
356 | struct lpfc_debugfs_trc *disc_trc; | ||
357 | atomic_t disc_trc_cnt; | ||
358 | #endif | ||
356 | }; | 359 | }; |
357 | 360 | ||
358 | struct hbq_s { | 361 | struct hbq_s { |
@@ -360,11 +363,19 @@ struct hbq_s { | |||
360 | uint32_t next_hbqPutIdx; /* Index to next HBQ slot to use */ | 363 | uint32_t next_hbqPutIdx; /* Index to next HBQ slot to use */ |
361 | uint32_t hbqPutIdx; /* HBQ slot to use */ | 364 | uint32_t hbqPutIdx; /* HBQ slot to use */ |
362 | uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */ | 365 | uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */ |
366 | void *hbq_virt; /* Virtual ptr to this hbq */ | ||
367 | struct list_head hbq_buffer_list; /* buffers assigned to this HBQ */ | ||
368 | /* Callback for HBQ buffer allocation */ | ||
369 | struct hbq_dmabuf *(*hbq_alloc_buffer) (struct lpfc_hba *); | ||
370 | /* Callback for HBQ buffer free */ | ||
371 | void (*hbq_free_buffer) (struct lpfc_hba *, | ||
372 | struct hbq_dmabuf *); | ||
363 | }; | 373 | }; |
364 | 374 | ||
365 | #define LPFC_MAX_HBQS 16 | 375 | #define LPFC_MAX_HBQS 4 |
366 | /* this matches the possition in the lpfc_hbq_defs array */ | 376 | /* this matches the position in the lpfc_hbq_defs array */ |
367 | #define LPFC_ELS_HBQ 0 | 377 | #define LPFC_ELS_HBQ 0 |
378 | #define LPFC_EXTRA_HBQ 1 | ||
368 | 379 | ||
369 | struct lpfc_hba { | 380 | struct lpfc_hba { |
370 | struct lpfc_sli sli; | 381 | struct lpfc_sli sli; |
@@ -460,7 +471,6 @@ struct lpfc_hba { | |||
460 | wait_queue_head_t *work_wait; | 471 | wait_queue_head_t *work_wait; |
461 | struct task_struct *worker_thread; | 472 | struct task_struct *worker_thread; |
462 | 473 | ||
463 | struct list_head hbq_buffer_list; | ||
464 | uint32_t hbq_count; /* Count of configured HBQs */ | 474 | uint32_t hbq_count; /* Count of configured HBQs */ |
465 | struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */ | 475 | struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */ |
466 | 476 | ||
@@ -529,6 +539,7 @@ struct lpfc_hba { | |||
529 | mempool_t *nlp_mem_pool; | 539 | mempool_t *nlp_mem_pool; |
530 | 540 | ||
531 | struct fc_host_statistics link_stats; | 541 | struct fc_host_statistics link_stats; |
542 | uint8_t using_msi; | ||
532 | 543 | ||
533 | struct list_head port_list; | 544 | struct list_head port_list; |
534 | struct lpfc_vport *pport; /* physical lpfc_vport pointer */ | 545 | struct lpfc_vport *pport; /* physical lpfc_vport pointer */ |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 0a7f06ba77c0..09743d7b6bab 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -1027,8 +1027,8 @@ static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ | |||
1027 | static ssize_t | 1027 | static ssize_t |
1028 | lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) | 1028 | lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) |
1029 | { | 1029 | { |
1030 | struct Scsi_Host *host = class_to_shost(cdev); | 1030 | struct Scsi_Host *shost = class_to_shost(cdev); |
1031 | struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; | 1031 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
1032 | return snprintf(buf, PAGE_SIZE, "0x%llx\n", | 1032 | return snprintf(buf, PAGE_SIZE, "0x%llx\n", |
1033 | (unsigned long long)phba->cfg_soft_wwnn); | 1033 | (unsigned long long)phba->cfg_soft_wwnn); |
1034 | } | 1034 | } |
@@ -1037,8 +1037,8 @@ lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) | |||
1037 | static ssize_t | 1037 | static ssize_t |
1038 | lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count) | 1038 | lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count) |
1039 | { | 1039 | { |
1040 | struct Scsi_Host *host = class_to_shost(cdev); | 1040 | struct Scsi_Host *shost = class_to_shost(cdev); |
1041 | struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; | 1041 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
1042 | unsigned int i, j, cnt=count; | 1042 | unsigned int i, j, cnt=count; |
1043 | u8 wwnn[8]; | 1043 | u8 wwnn[8]; |
1044 | 1044 | ||
@@ -1153,24 +1153,15 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val) | |||
1153 | static void | 1153 | static void |
1154 | lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) | 1154 | lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) |
1155 | { | 1155 | { |
1156 | struct lpfc_vport **vports; | ||
1157 | struct Scsi_Host *shost; | 1156 | struct Scsi_Host *shost; |
1158 | struct lpfc_nodelist *ndlp; | 1157 | struct lpfc_nodelist *ndlp; |
1159 | int i; | ||
1160 | 1158 | ||
1161 | vports = lpfc_create_vport_work_array(vport->phba); | 1159 | shost = lpfc_shost_from_vport(vport); |
1162 | if (vports != NULL) | 1160 | spin_lock_irq(shost->host_lock); |
1163 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { | 1161 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) |
1164 | shost = lpfc_shost_from_vport(vports[i]); | 1162 | if (ndlp->rport) |
1165 | spin_lock_irq(shost->host_lock); | 1163 | ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo; |
1166 | list_for_each_entry(ndlp, &vports[i]->fc_nodes, | 1164 | spin_unlock_irq(shost->host_lock); |
1167 | nlp_listp) | ||
1168 | if (ndlp->rport) | ||
1169 | ndlp->rport->dev_loss_tmo = | ||
1170 | vport->cfg_devloss_tmo; | ||
1171 | spin_unlock_irq(shost->host_lock); | ||
1172 | } | ||
1173 | lpfc_destroy_vport_work_array(vports); | ||
1174 | } | 1165 | } |
1175 | 1166 | ||
1176 | static int | 1167 | static int |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index ef86345ced6e..b789355fedf5 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -102,7 +102,7 @@ int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); | |||
102 | int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); | 102 | int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); |
103 | int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); | 103 | int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); |
104 | int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, | 104 | int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, |
105 | struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t); | 105 | struct lpfc_nodelist *, LPFC_MBOXQ_t *); |
106 | int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, | 106 | int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, |
107 | struct lpfc_nodelist *, LPFC_MBOXQ_t *); | 107 | struct lpfc_nodelist *, LPFC_MBOXQ_t *); |
108 | int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *, | 108 | int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *, |
@@ -163,9 +163,11 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); | |||
163 | void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *); | 163 | void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *); |
164 | int lpfc_mbox_tmo_val(struct lpfc_hba *, int); | 164 | int lpfc_mbox_tmo_val(struct lpfc_hba *, int); |
165 | 165 | ||
166 | void lpfc_config_hbq(struct lpfc_hba *, struct lpfc_hbq_init *, uint32_t , | 166 | void lpfc_config_hbq(struct lpfc_hba *, uint32_t, struct lpfc_hbq_init *, |
167 | LPFC_MBOXQ_t *); | 167 | uint32_t , LPFC_MBOXQ_t *); |
168 | struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t); | 168 | struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t); |
169 | struct hbq_dmabuf *lpfc_els_hbq_alloc(struct lpfc_hba *); | ||
170 | void lpfc_els_hbq_free(struct lpfc_hba *, struct hbq_dmabuf *); | ||
169 | 171 | ||
170 | int lpfc_mem_alloc(struct lpfc_hba *); | 172 | int lpfc_mem_alloc(struct lpfc_hba *); |
171 | void lpfc_mem_free(struct lpfc_hba *); | 173 | void lpfc_mem_free(struct lpfc_hba *); |
@@ -202,6 +204,7 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, | |||
202 | struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, | 204 | struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, |
203 | struct lpfc_sli_ring *, | 205 | struct lpfc_sli_ring *, |
204 | dma_addr_t); | 206 | dma_addr_t); |
207 | int lpfc_sli_hbq_count(void); | ||
205 | int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t); | 208 | int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t); |
206 | int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t); | 209 | int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t); |
207 | void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *); | 210 | void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *); |
@@ -209,10 +212,9 @@ struct hbq_dmabuf *lpfc_sli_hbqbuf_find(struct lpfc_hba *, uint32_t); | |||
209 | int lpfc_sli_hbq_size(void); | 212 | int lpfc_sli_hbq_size(void); |
210 | int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *, | 213 | int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *, |
211 | struct lpfc_iocbq *); | 214 | struct lpfc_iocbq *); |
212 | int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, | 215 | int lpfc_sli_sum_iocb(struct lpfc_vport *, uint16_t, uint64_t, lpfc_ctx_cmd); |
213 | uint64_t, lpfc_ctx_cmd); | 216 | int lpfc_sli_abort_iocb(struct lpfc_vport *, struct lpfc_sli_ring *, uint16_t, |
214 | int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, | 217 | uint64_t, lpfc_ctx_cmd); |
215 | uint64_t, uint32_t, lpfc_ctx_cmd); | ||
216 | 218 | ||
217 | void lpfc_mbox_timeout(unsigned long); | 219 | void lpfc_mbox_timeout(unsigned long); |
218 | void lpfc_mbox_timeout_handler(struct lpfc_hba *); | 220 | void lpfc_mbox_timeout_handler(struct lpfc_hba *); |
@@ -236,8 +238,6 @@ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, | |||
236 | struct lpfc_iocbq * cmdiocb, | 238 | struct lpfc_iocbq * cmdiocb, |
237 | struct lpfc_iocbq * rspiocb); | 239 | struct lpfc_iocbq * rspiocb); |
238 | 240 | ||
239 | void *lpfc_hbq_alloc(struct lpfc_hba *, int, dma_addr_t *); | ||
240 | void lpfc_hbq_free(struct lpfc_hba *, void *, dma_addr_t); | ||
241 | void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *); | 241 | void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *); |
242 | 242 | ||
243 | void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *); | 243 | void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *); |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index ad7f33a31567..6f187f3b3048 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -257,6 +257,10 @@ lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) | |||
257 | { | 257 | { |
258 | struct lpfc_dmabuf *buf_ptr; | 258 | struct lpfc_dmabuf *buf_ptr; |
259 | 259 | ||
260 | if (ctiocb->context_un.ndlp) { | ||
261 | lpfc_nlp_put(ctiocb->context_un.ndlp); | ||
262 | ctiocb->context_un.ndlp = NULL; | ||
263 | } | ||
260 | if (ctiocb->context1) { | 264 | if (ctiocb->context1) { |
261 | buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1; | 265 | buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1; |
262 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); | 266 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); |
@@ -314,6 +318,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, | |||
314 | /* Save for completion so we can release these resources */ | 318 | /* Save for completion so we can release these resources */ |
315 | geniocb->context1 = (uint8_t *) inp; | 319 | geniocb->context1 = (uint8_t *) inp; |
316 | geniocb->context2 = (uint8_t *) outp; | 320 | geniocb->context2 = (uint8_t *) outp; |
321 | geniocb->context_un.ndlp = ndlp; | ||
317 | 322 | ||
318 | /* Fill in payload, bp points to frame payload */ | 323 | /* Fill in payload, bp points to frame payload */ |
319 | icmd->ulpCommand = CMD_GEN_REQUEST64_CR; | 324 | icmd->ulpCommand = CMD_GEN_REQUEST64_CR; |
@@ -548,8 +553,12 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
548 | struct lpfc_dmabuf *bmp; | 553 | struct lpfc_dmabuf *bmp; |
549 | struct lpfc_dmabuf *outp; | 554 | struct lpfc_dmabuf *outp; |
550 | struct lpfc_sli_ct_request *CTrsp; | 555 | struct lpfc_sli_ct_request *CTrsp; |
556 | struct lpfc_nodelist *ndlp; | ||
551 | int rc; | 557 | int rc; |
552 | 558 | ||
559 | /* First save ndlp, before we overwrite it */ | ||
560 | ndlp = cmdiocb->context_un.ndlp; | ||
561 | |||
553 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 562 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
554 | cmdiocb->context_un.rsp_iocb = rspiocb; | 563 | cmdiocb->context_un.rsp_iocb = rspiocb; |
555 | 564 | ||
@@ -674,6 +683,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
674 | lpfc_disc_start(vport); | 683 | lpfc_disc_start(vport); |
675 | } | 684 | } |
676 | out: | 685 | out: |
686 | cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */ | ||
677 | lpfc_ct_free_iocb(phba, cmdiocb); | 687 | lpfc_ct_free_iocb(phba, cmdiocb); |
678 | return; | 688 | return; |
679 | } | 689 | } |
@@ -776,10 +786,14 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
776 | struct lpfc_dmabuf *outp; | 786 | struct lpfc_dmabuf *outp; |
777 | IOCB_t *irsp; | 787 | IOCB_t *irsp; |
778 | struct lpfc_sli_ct_request *CTrsp; | 788 | struct lpfc_sli_ct_request *CTrsp; |
789 | struct lpfc_nodelist *ndlp; | ||
779 | int cmdcode, rc; | 790 | int cmdcode, rc; |
780 | uint8_t retry; | 791 | uint8_t retry; |
781 | uint32_t latt; | 792 | uint32_t latt; |
782 | 793 | ||
794 | /* First save ndlp, before we overwrite it */ | ||
795 | ndlp = cmdiocb->context_un.ndlp; | ||
796 | |||
783 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 797 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
784 | cmdiocb->context_un.rsp_iocb = rspiocb; | 798 | cmdiocb->context_un.rsp_iocb = rspiocb; |
785 | 799 | ||
@@ -828,6 +842,7 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
828 | } | 842 | } |
829 | 843 | ||
830 | out: | 844 | out: |
845 | cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */ | ||
831 | lpfc_ct_free_iocb(phba, cmdiocb); | 846 | lpfc_ct_free_iocb(phba, cmdiocb); |
832 | return; | 847 | return; |
833 | } | 848 | } |
@@ -1066,6 +1081,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1066 | cmpl = lpfc_cmpl_ct_cmd_rff_id; | 1081 | cmpl = lpfc_cmpl_ct_cmd_rff_id; |
1067 | break; | 1082 | break; |
1068 | } | 1083 | } |
1084 | lpfc_nlp_get(ndlp); | ||
1069 | 1085 | ||
1070 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) { | 1086 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) { |
1071 | /* On success, The cmpl function will free the buffers */ | 1087 | /* On success, The cmpl function will free the buffers */ |
@@ -1076,6 +1092,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1076 | } | 1092 | } |
1077 | 1093 | ||
1078 | rc=6; | 1094 | rc=6; |
1095 | lpfc_nlp_put(ndlp); | ||
1079 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 1096 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
1080 | ns_cmd_free_bmp: | 1097 | ns_cmd_free_bmp: |
1081 | kfree(bmp); | 1098 | kfree(bmp); |
@@ -1501,10 +1518,12 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | |||
1501 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 1518 | bpl->tus.w = le32_to_cpu(bpl->tus.w); |
1502 | 1519 | ||
1503 | cmpl = lpfc_cmpl_ct_cmd_fdmi; | 1520 | cmpl = lpfc_cmpl_ct_cmd_fdmi; |
1521 | lpfc_nlp_get(ndlp); | ||
1504 | 1522 | ||
1505 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0)) | 1523 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0)) |
1506 | return 0; | 1524 | return 0; |
1507 | 1525 | ||
1526 | lpfc_nlp_put(ndlp); | ||
1508 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 1527 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
1509 | fdmi_cmd_free_bmp: | 1528 | fdmi_cmd_free_bmp: |
1510 | kfree(bmp); | 1529 | kfree(bmp); |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index f334761d04df..697a09dccb6f 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -71,7 +71,7 @@ | |||
71 | * lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in | 71 | * lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in |
72 | * lpfc_debugfs.h . | 72 | * lpfc_debugfs.h . |
73 | */ | 73 | */ |
74 | static int lpfc_debugfs_enable = 0; | 74 | static int lpfc_debugfs_enable = 1; |
75 | module_param(lpfc_debugfs_enable, int, 0); | 75 | module_param(lpfc_debugfs_enable, int, 0); |
76 | MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services"); | 76 | MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services"); |
77 | 77 | ||
@@ -113,7 +113,6 @@ struct lpfc_debug { | |||
113 | }; | 113 | }; |
114 | 114 | ||
115 | extern struct lpfc_hbq_init *lpfc_hbq_defs[]; | 115 | extern struct lpfc_hbq_init *lpfc_hbq_defs[]; |
116 | extern int lpfc_sli_hbq_count(void); | ||
117 | 116 | ||
118 | atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); | 117 | atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); |
119 | unsigned long lpfc_debugfs_start_time = 0L; | 118 | unsigned long lpfc_debugfs_start_time = 0L; |
@@ -233,8 +232,9 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) | |||
233 | 232 | ||
234 | len += snprintf(buf+len, size-len, "HBQ %d Info\n", i); | 233 | len += snprintf(buf+len, size-len, "HBQ %d Info\n", i); |
235 | 234 | ||
235 | hbqs = &phba->hbqs[i]; | ||
236 | posted = 0; | 236 | posted = 0; |
237 | list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) | 237 | list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) |
238 | posted++; | 238 | posted++; |
239 | 239 | ||
240 | hip = lpfc_hbq_defs[i]; | 240 | hip = lpfc_hbq_defs[i]; |
@@ -243,7 +243,6 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) | |||
243 | hip->hbq_index, hip->profile, hip->rn, | 243 | hip->hbq_index, hip->profile, hip->rn, |
244 | hip->buffer_count, hip->init_count, hip->add_count, posted); | 244 | hip->buffer_count, hip->init_count, hip->add_count, posted); |
245 | 245 | ||
246 | hbqs = &phba->hbqs[i]; | ||
247 | raw_index = phba->hbq_get[i]; | 246 | raw_index = phba->hbq_get[i]; |
248 | getidx = le32_to_cpu(raw_index); | 247 | getidx = le32_to_cpu(raw_index); |
249 | len += snprintf(buf+len, size-len, | 248 | len += snprintf(buf+len, size-len, |
@@ -251,7 +250,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) | |||
251 | hbqs->entry_count, hbqs->hbqPutIdx, hbqs->next_hbqPutIdx, | 250 | hbqs->entry_count, hbqs->hbqPutIdx, hbqs->next_hbqPutIdx, |
252 | hbqs->local_hbqGetIdx, getidx); | 251 | hbqs->local_hbqGetIdx, getidx); |
253 | 252 | ||
254 | hbqe = (struct lpfc_hbq_entry *) phba->hbqslimp.virt; | 253 | hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt; |
255 | for (j=0; j<hbqs->entry_count; j++) { | 254 | for (j=0; j<hbqs->entry_count; j++) { |
256 | len += snprintf(buf+len, size-len, | 255 | len += snprintf(buf+len, size-len, |
257 | "%03d: %08x %04x %05x ", j, | 256 | "%03d: %08x %04x %05x ", j, |
@@ -277,7 +276,7 @@ lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) | |||
277 | } | 276 | } |
278 | 277 | ||
279 | /* Get the Buffer info for the posted buffer */ | 278 | /* Get the Buffer info for the posted buffer */ |
280 | list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) { | 279 | list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) { |
281 | hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); | 280 | hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); |
282 | phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); | 281 | phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); |
283 | if (phys == hbqe->bde.addrLow) { | 282 | if (phys == hbqe->bde.addrLow) { |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 9365e19696e2..8085900635d4 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -196,9 +196,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
196 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 196 | bpl->tus.w = le32_to_cpu(bpl->tus.w); |
197 | } | 197 | } |
198 | 198 | ||
199 | /* Save for completion so we can release these resources */ | 199 | elsiocb->context1 = lpfc_nlp_get(ndlp); |
200 | if (elscmd != ELS_CMD_LS_RJT) | ||
201 | elsiocb->context1 = lpfc_nlp_get(ndlp); | ||
202 | elsiocb->context2 = pcmd; | 200 | elsiocb->context2 = pcmd; |
203 | elsiocb->context3 = pbuflist; | 201 | elsiocb->context3 = pbuflist; |
204 | elsiocb->retry = retry; | 202 | elsiocb->retry = retry; |
@@ -1809,8 +1807,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1809 | "retrying...\n"); | 1807 | "retrying...\n"); |
1810 | lpfc_mbx_unreg_vpi(vport); | 1808 | lpfc_mbx_unreg_vpi(vport); |
1811 | retry = 1; | 1809 | retry = 1; |
1812 | /* Always retry for this case */ | 1810 | /* FDISC retry policy */ |
1813 | cmdiocb->retry = 0; | 1811 | maxretry = 48; |
1812 | if (cmdiocb->retry >= 32) | ||
1813 | delay = 1000; | ||
1814 | } | 1814 | } |
1815 | break; | 1815 | break; |
1816 | 1816 | ||
@@ -1886,8 +1886,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1886 | delay = 1000; | 1886 | delay = 1000; |
1887 | maxretry = 48; | 1887 | maxretry = 48; |
1888 | } else if (cmd == ELS_CMD_FDISC) { | 1888 | } else if (cmd == ELS_CMD_FDISC) { |
1889 | /* Always retry for this case */ | 1889 | /* FDISC retry policy */ |
1890 | cmdiocb->retry = 0; | 1890 | maxretry = 48; |
1891 | if (cmdiocb->retry >= 32) | ||
1892 | delay = 1000; | ||
1891 | } | 1893 | } |
1892 | retry = 1; | 1894 | retry = 1; |
1893 | break; | 1895 | break; |
@@ -2121,9 +2123,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2121 | } | 2123 | } |
2122 | 2124 | ||
2123 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | 2125 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, |
2124 | "ACC cmpl: status:x%x/x%x did:x%x", | 2126 | "ELS rsp cmpl: status:x%x/x%x did:x%x", |
2125 | irsp->ulpStatus, irsp->un.ulpWord[4], | 2127 | irsp->ulpStatus, irsp->un.ulpWord[4], |
2126 | irsp->un.rcvels.remoteID); | 2128 | cmdiocb->iocb.un.elsreq64.remoteID); |
2127 | /* ELS response tag <ulpIoTag> completes */ | 2129 | /* ELS response tag <ulpIoTag> completes */ |
2128 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2130 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
2129 | "0110 ELS response tag x%x completes " | 2131 | "0110 ELS response tag x%x completes " |
@@ -2184,7 +2186,7 @@ out: | |||
2184 | int | 2186 | int |
2185 | lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | 2187 | lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, |
2186 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, | 2188 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, |
2187 | LPFC_MBOXQ_t *mbox, uint8_t newnode) | 2189 | LPFC_MBOXQ_t *mbox) |
2188 | { | 2190 | { |
2189 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2191 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2190 | struct lpfc_hba *phba = vport->phba; | 2192 | struct lpfc_hba *phba = vport->phba; |
@@ -2270,11 +2272,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | |||
2270 | default: | 2272 | default: |
2271 | return 1; | 2273 | return 1; |
2272 | } | 2274 | } |
2273 | |||
2274 | if (newnode) { | ||
2275 | lpfc_nlp_put(ndlp); | ||
2276 | elsiocb->context1 = NULL; | ||
2277 | } | ||
2278 | /* Xmit ELS ACC response tag <ulpIoTag> */ | 2275 | /* Xmit ELS ACC response tag <ulpIoTag> */ |
2279 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2276 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
2280 | "0128 Xmit ELS ACC response tag x%x, XRI: x%x, " | 2277 | "0128 Xmit ELS ACC response tag x%x, XRI: x%x, " |
@@ -2333,10 +2330,8 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, | |||
2333 | pcmd += sizeof(uint32_t); | 2330 | pcmd += sizeof(uint32_t); |
2334 | *((uint32_t *) (pcmd)) = rejectError; | 2331 | *((uint32_t *) (pcmd)) = rejectError; |
2335 | 2332 | ||
2336 | if (mbox) { | 2333 | if (mbox) |
2337 | elsiocb->context_un.mbox = mbox; | 2334 | elsiocb->context_un.mbox = mbox; |
2338 | elsiocb->context1 = lpfc_nlp_get(ndlp); | ||
2339 | } | ||
2340 | 2335 | ||
2341 | /* Xmit ELS RJT <err> response tag <ulpIoTag> */ | 2336 | /* Xmit ELS RJT <err> response tag <ulpIoTag> */ |
2342 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2337 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
@@ -2353,6 +2348,15 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, | |||
2353 | phba->fc_stat.elsXmitLSRJT++; | 2348 | phba->fc_stat.elsXmitLSRJT++; |
2354 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; | 2349 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
2355 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2350 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
2351 | |||
2352 | /* If the node is in the UNUSED state, and we are sending | ||
2353 | * a reject, we are done with it. Release driver reference | ||
2354 | * count here. The outstanding els will release its reference on | ||
2355 | * completion and the node can be freed then. | ||
2356 | */ | ||
2357 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | ||
2358 | lpfc_nlp_put(ndlp); | ||
2359 | |||
2356 | if (rc == IOCB_ERROR) { | 2360 | if (rc == IOCB_ERROR) { |
2357 | lpfc_els_free_iocb(phba, elsiocb); | 2361 | lpfc_els_free_iocb(phba, elsiocb); |
2358 | return 1; | 2362 | return 1; |
@@ -2747,7 +2751,7 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) | |||
2747 | 2751 | ||
2748 | static int | 2752 | static int |
2749 | lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | 2753 | lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2750 | struct lpfc_nodelist *ndlp, uint8_t newnode) | 2754 | struct lpfc_nodelist *ndlp) |
2751 | { | 2755 | { |
2752 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2756 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2753 | struct lpfc_hba *phba = vport->phba; | 2757 | struct lpfc_hba *phba = vport->phba; |
@@ -2781,8 +2785,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2781 | "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x", | 2785 | "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x", |
2782 | ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); | 2786 | ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); |
2783 | 2787 | ||
2784 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, | 2788 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
2785 | newnode); | ||
2786 | return 0; | 2789 | return 0; |
2787 | } | 2790 | } |
2788 | 2791 | ||
@@ -2814,7 +2817,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2814 | ndlp->nlp_flag); | 2817 | ndlp->nlp_flag); |
2815 | 2818 | ||
2816 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, | 2819 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, |
2817 | ndlp, NULL, newnode); | 2820 | ndlp, NULL); |
2818 | return 0; | 2821 | return 0; |
2819 | } | 2822 | } |
2820 | } | 2823 | } |
@@ -2870,8 +2873,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2870 | vport->port_state); | 2873 | vport->port_state); |
2871 | } | 2874 | } |
2872 | /* Send back ACC */ | 2875 | /* Send back ACC */ |
2873 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, | 2876 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
2874 | newnode); | ||
2875 | 2877 | ||
2876 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 2878 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
2877 | lpfc_rscn_recovery_check(vport); | 2879 | lpfc_rscn_recovery_check(vport); |
@@ -2896,7 +2898,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
2896 | lpfc_set_disctmo(vport); | 2898 | lpfc_set_disctmo(vport); |
2897 | 2899 | ||
2898 | /* Send back ACC */ | 2900 | /* Send back ACC */ |
2899 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode); | 2901 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
2900 | 2902 | ||
2901 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 2903 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
2902 | lpfc_rscn_recovery_check(vport); | 2904 | lpfc_rscn_recovery_check(vport); |
@@ -2965,7 +2967,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) | |||
2965 | 2967 | ||
2966 | static int | 2968 | static int |
2967 | lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | 2969 | lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2968 | struct lpfc_nodelist *ndlp, uint8_t newnode) | 2970 | struct lpfc_nodelist *ndlp) |
2969 | { | 2971 | { |
2970 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2972 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2971 | struct lpfc_hba *phba = vport->phba; | 2973 | struct lpfc_hba *phba = vport->phba; |
@@ -3048,7 +3050,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3048 | } | 3050 | } |
3049 | 3051 | ||
3050 | /* Send back ACC */ | 3052 | /* Send back ACC */ |
3051 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode); | 3053 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); |
3052 | 3054 | ||
3053 | return 0; | 3055 | return 0; |
3054 | } | 3056 | } |
@@ -3409,7 +3411,7 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3409 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 3411 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
3410 | "0600 FARP-RSP received from DID x%x\n", did); | 3412 | "0600 FARP-RSP received from DID x%x\n", did); |
3411 | /* ACCEPT the Farp resp request */ | 3413 | /* ACCEPT the Farp resp request */ |
3412 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 3414 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
3413 | 3415 | ||
3414 | return 0; | 3416 | return 0; |
3415 | } | 3417 | } |
@@ -3791,7 +3793,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3791 | did, vport->port_state, ndlp->nlp_flag); | 3793 | did, vport->port_state, ndlp->nlp_flag); |
3792 | 3794 | ||
3793 | phba->fc_stat.elsRcvFLOGI++; | 3795 | phba->fc_stat.elsRcvFLOGI++; |
3794 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode); | 3796 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp); |
3795 | if (newnode) | 3797 | if (newnode) |
3796 | lpfc_drop_node(vport, ndlp); | 3798 | lpfc_drop_node(vport, ndlp); |
3797 | break; | 3799 | break; |
@@ -3821,7 +3823,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3821 | break; | 3823 | break; |
3822 | case ELS_CMD_RSCN: | 3824 | case ELS_CMD_RSCN: |
3823 | phba->fc_stat.elsRcvRSCN++; | 3825 | phba->fc_stat.elsRcvRSCN++; |
3824 | lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode); | 3826 | lpfc_els_rcv_rscn(vport, elsiocb, ndlp); |
3825 | if (newnode) | 3827 | if (newnode) |
3826 | lpfc_drop_node(vport, ndlp); | 3828 | lpfc_drop_node(vport, ndlp); |
3827 | break; | 3829 | break; |
@@ -3951,8 +3953,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3951 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | 3953 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; |
3952 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp, | 3954 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp, |
3953 | NULL); | 3955 | NULL); |
3954 | if (newnode) | ||
3955 | lpfc_drop_node(vport, ndlp); | ||
3956 | } | 3956 | } |
3957 | 3957 | ||
3958 | return; | 3958 | return; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f96ab75ba637..8788f14b1dec 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -83,10 +83,17 @@ lpfc_terminate_rport_io(struct fc_rport *rport) | |||
83 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); | 83 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); |
84 | 84 | ||
85 | if (ndlp->nlp_sid != NLP_NO_SID) { | 85 | if (ndlp->nlp_sid != NLP_NO_SID) { |
86 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 86 | lpfc_sli_abort_iocb(ndlp->vport, |
87 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 87 | &phba->sli.ring[phba->sli.fcp_ring], |
88 | ndlp->nlp_sid, 0, LPFC_CTX_TGT); | ||
88 | } | 89 | } |
89 | 90 | ||
91 | /* | ||
92 | * A device is normally blocked for rediscovery and unblocked when | ||
93 | * devloss timeout happens. In case a vport is removed or driver | ||
94 | * unloaded before devloss timeout happens, we need to unblock here. | ||
95 | */ | ||
96 | scsi_target_unblock(&rport->dev); | ||
90 | return; | 97 | return; |
91 | } | 98 | } |
92 | 99 | ||
@@ -194,8 +201,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
194 | if (ndlp->nlp_sid != NLP_NO_SID) { | 201 | if (ndlp->nlp_sid != NLP_NO_SID) { |
195 | warn_on = 1; | 202 | warn_on = 1; |
196 | /* flush the target */ | 203 | /* flush the target */ |
197 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 204 | lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], |
198 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 205 | ndlp->nlp_sid, 0, LPFC_CTX_TGT); |
199 | } | 206 | } |
200 | if (vport->load_flag & FC_UNLOADING) | 207 | if (vport->load_flag & FC_UNLOADING) |
201 | warn_on = 0; | 208 | warn_on = 0; |
@@ -348,6 +355,7 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
348 | struct lpfc_sli_ring *pring; | 355 | struct lpfc_sli_ring *pring; |
349 | uint32_t ha_copy, status, control, work_port_events; | 356 | uint32_t ha_copy, status, control, work_port_events; |
350 | struct lpfc_vport **vports; | 357 | struct lpfc_vport **vports; |
358 | struct lpfc_vport *vport; | ||
351 | int i; | 359 | int i; |
352 | 360 | ||
353 | spin_lock_irq(&phba->hbalock); | 361 | spin_lock_irq(&phba->hbalock); |
@@ -365,12 +373,22 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
365 | lpfc_handle_latt(phba); | 373 | lpfc_handle_latt(phba); |
366 | vports = lpfc_create_vport_work_array(phba); | 374 | vports = lpfc_create_vport_work_array(phba); |
367 | if (vports != NULL) | 375 | if (vports != NULL) |
368 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { | 376 | for(i = 0; i < LPFC_MAX_VPORTS; i++) { |
369 | work_port_events = vports[i]->work_port_events; | 377 | /* |
378 | * We could have no vports in array if unloading, so if | ||
379 | * this happens then just use the pport | ||
380 | */ | ||
381 | if (vports[i] == NULL && i == 0) | ||
382 | vport = phba->pport; | ||
383 | else | ||
384 | vport = vports[i]; | ||
385 | if (vport == NULL) | ||
386 | break; | ||
387 | work_port_events = vport->work_port_events; | ||
370 | if (work_port_events & WORKER_DISC_TMO) | 388 | if (work_port_events & WORKER_DISC_TMO) |
371 | lpfc_disc_timeout_handler(vports[i]); | 389 | lpfc_disc_timeout_handler(vport); |
372 | if (work_port_events & WORKER_ELS_TMO) | 390 | if (work_port_events & WORKER_ELS_TMO) |
373 | lpfc_els_timeout_handler(vports[i]); | 391 | lpfc_els_timeout_handler(vport); |
374 | if (work_port_events & WORKER_HB_TMO) | 392 | if (work_port_events & WORKER_HB_TMO) |
375 | lpfc_hb_timeout_handler(phba); | 393 | lpfc_hb_timeout_handler(phba); |
376 | if (work_port_events & WORKER_MBOX_TMO) | 394 | if (work_port_events & WORKER_MBOX_TMO) |
@@ -378,14 +396,14 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
378 | if (work_port_events & WORKER_FABRIC_BLOCK_TMO) | 396 | if (work_port_events & WORKER_FABRIC_BLOCK_TMO) |
379 | lpfc_unblock_fabric_iocbs(phba); | 397 | lpfc_unblock_fabric_iocbs(phba); |
380 | if (work_port_events & WORKER_FDMI_TMO) | 398 | if (work_port_events & WORKER_FDMI_TMO) |
381 | lpfc_fdmi_timeout_handler(vports[i]); | 399 | lpfc_fdmi_timeout_handler(vport); |
382 | if (work_port_events & WORKER_RAMP_DOWN_QUEUE) | 400 | if (work_port_events & WORKER_RAMP_DOWN_QUEUE) |
383 | lpfc_ramp_down_queue_handler(phba); | 401 | lpfc_ramp_down_queue_handler(phba); |
384 | if (work_port_events & WORKER_RAMP_UP_QUEUE) | 402 | if (work_port_events & WORKER_RAMP_UP_QUEUE) |
385 | lpfc_ramp_up_queue_handler(phba); | 403 | lpfc_ramp_up_queue_handler(phba); |
386 | spin_lock_irq(&vports[i]->work_port_lock); | 404 | spin_lock_irq(&vport->work_port_lock); |
387 | vports[i]->work_port_events &= ~work_port_events; | 405 | vport->work_port_events &= ~work_port_events; |
388 | spin_unlock_irq(&vports[i]->work_port_lock); | 406 | spin_unlock_irq(&vport->work_port_lock); |
389 | } | 407 | } |
390 | lpfc_destroy_vport_work_array(vports); | 408 | lpfc_destroy_vport_work_array(vports); |
391 | 409 | ||
@@ -1638,16 +1656,7 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1638 | void | 1656 | void |
1639 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 1657 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
1640 | { | 1658 | { |
1641 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1659 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
1642 | |||
1643 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) | ||
1644 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
1645 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) | ||
1646 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); | ||
1647 | spin_lock_irq(shost->host_lock); | ||
1648 | list_del_init(&ndlp->nlp_listp); | ||
1649 | ndlp->nlp_flag &= ~NLP_TARGET_REMOVE; | ||
1650 | spin_unlock_irq(shost->host_lock); | ||
1651 | lpfc_nlp_put(ndlp); | 1660 | lpfc_nlp_put(ndlp); |
1652 | } | 1661 | } |
1653 | 1662 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index c2fb59f595f3..a90b1fd9c760 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -150,7 +150,11 @@ struct lpfc_sli_ct_request { | |||
150 | struct gff_acc { | 150 | struct gff_acc { |
151 | uint8_t fbits[128]; | 151 | uint8_t fbits[128]; |
152 | } gff_acc; | 152 | } gff_acc; |
153 | #ifdef __BIG_ENDIAN_BITFIELD | ||
154 | #define FCP_TYPE_FEATURE_OFFSET 7 | ||
155 | #else /* __LITTLE_ENDIAN_BITFIELD */ | ||
153 | #define FCP_TYPE_FEATURE_OFFSET 4 | 156 | #define FCP_TYPE_FEATURE_OFFSET 4 |
157 | #endif | ||
154 | struct rff { | 158 | struct rff { |
155 | uint32_t PortId; | 159 | uint32_t PortId; |
156 | uint8_t reserved[2]; | 160 | uint8_t reserved[2]; |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7e5ea0774e58..21f8f7a56e23 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -55,6 +55,8 @@ static DEFINE_IDR(lpfc_hba_index); | |||
55 | 55 | ||
56 | 56 | ||
57 | 57 | ||
58 | extern struct lpfc_hbq_init *lpfc_hbq_defs[]; | ||
59 | |||
58 | /************************************************************************/ | 60 | /************************************************************************/ |
59 | /* */ | 61 | /* */ |
60 | /* lpfc_config_port_prep */ | 62 | /* lpfc_config_port_prep */ |
@@ -429,18 +431,11 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
429 | int | 431 | int |
430 | lpfc_hba_down_prep(struct lpfc_hba *phba) | 432 | lpfc_hba_down_prep(struct lpfc_hba *phba) |
431 | { | 433 | { |
432 | struct lpfc_vport **vports; | ||
433 | int i; | ||
434 | |||
435 | /* Disable interrupts */ | 434 | /* Disable interrupts */ |
436 | writel(0, phba->HCregaddr); | 435 | writel(0, phba->HCregaddr); |
437 | readl(phba->HCregaddr); /* flush */ | 436 | readl(phba->HCregaddr); /* flush */ |
438 | 437 | ||
439 | vports = lpfc_create_vport_work_array(phba); | 438 | lpfc_cleanup_discovery_resources(phba->pport); |
440 | if (vports != NULL) | ||
441 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) | ||
442 | lpfc_cleanup_discovery_resources(vports[i]); | ||
443 | lpfc_destroy_vport_work_array(vports); | ||
444 | return 0; | 439 | return 0; |
445 | } | 440 | } |
446 | 441 | ||
@@ -512,7 +507,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) | |||
512 | mempool_free(pmboxq, phba->mbox_mem_pool); | 507 | mempool_free(pmboxq, phba->mbox_mem_pool); |
513 | if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) && | 508 | if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) && |
514 | !(phba->link_state == LPFC_HBA_ERROR) && | 509 | !(phba->link_state == LPFC_HBA_ERROR) && |
515 | !(phba->pport->fc_flag & FC_UNLOADING)) | 510 | !(phba->pport->load_flag & FC_UNLOADING)) |
516 | mod_timer(&phba->hb_tmofunc, | 511 | mod_timer(&phba->hb_tmofunc, |
517 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | 512 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); |
518 | return; | 513 | return; |
@@ -526,7 +521,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
526 | struct lpfc_sli *psli = &phba->sli; | 521 | struct lpfc_sli *psli = &phba->sli; |
527 | 522 | ||
528 | if ((phba->link_state == LPFC_HBA_ERROR) || | 523 | if ((phba->link_state == LPFC_HBA_ERROR) || |
529 | (phba->pport->fc_flag & FC_UNLOADING) || | 524 | (phba->pport->load_flag & FC_UNLOADING) || |
530 | (phba->pport->fc_flag & FC_OFFLINE_MODE)) | 525 | (phba->pport->fc_flag & FC_OFFLINE_MODE)) |
531 | return; | 526 | return; |
532 | 527 | ||
@@ -1340,16 +1335,9 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport) | |||
1340 | static void | 1335 | static void |
1341 | lpfc_stop_phba_timers(struct lpfc_hba *phba) | 1336 | lpfc_stop_phba_timers(struct lpfc_hba *phba) |
1342 | { | 1337 | { |
1343 | struct lpfc_vport **vports; | ||
1344 | int i; | ||
1345 | |||
1346 | del_timer_sync(&phba->fcp_poll_timer); | 1338 | del_timer_sync(&phba->fcp_poll_timer); |
1347 | del_timer_sync(&phba->fc_estabtmo); | 1339 | del_timer_sync(&phba->fc_estabtmo); |
1348 | vports = lpfc_create_vport_work_array(phba); | 1340 | lpfc_stop_vport_timers(phba->pport); |
1349 | if (vports != NULL) | ||
1350 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) | ||
1351 | lpfc_stop_vport_timers(vports[i]); | ||
1352 | lpfc_destroy_vport_work_array(vports); | ||
1353 | del_timer_sync(&phba->sli.mbox_tmo); | 1341 | del_timer_sync(&phba->sli.mbox_tmo); |
1354 | del_timer_sync(&phba->fabric_block_timer); | 1342 | del_timer_sync(&phba->fabric_block_timer); |
1355 | phba->hb_outstanding = 0; | 1343 | phba->hb_outstanding = 0; |
@@ -1455,6 +1443,11 @@ lpfc_offline(struct lpfc_hba *phba) | |||
1455 | 1443 | ||
1456 | /* stop all timers associated with this hba */ | 1444 | /* stop all timers associated with this hba */ |
1457 | lpfc_stop_phba_timers(phba); | 1445 | lpfc_stop_phba_timers(phba); |
1446 | vports = lpfc_create_vport_work_array(phba); | ||
1447 | if (vports != NULL) | ||
1448 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) | ||
1449 | lpfc_stop_vport_timers(vports[i]); | ||
1450 | lpfc_destroy_vport_work_array(vports); | ||
1458 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | 1451 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, |
1459 | "0460 Bring Adapter offline\n"); | 1452 | "0460 Bring Adapter offline\n"); |
1460 | /* Bring down the SLI Layer and cleanup. The HBA is offline | 1453 | /* Bring down the SLI Layer and cleanup. The HBA is offline |
@@ -1629,7 +1622,7 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) | |||
1629 | 1622 | ||
1630 | spin_lock_irq(shost->host_lock); | 1623 | spin_lock_irq(shost->host_lock); |
1631 | 1624 | ||
1632 | if (vport->fc_flag & FC_UNLOADING) { | 1625 | if (vport->load_flag & FC_UNLOADING) { |
1633 | stat = 1; | 1626 | stat = 1; |
1634 | goto finished; | 1627 | goto finished; |
1635 | } | 1628 | } |
@@ -1706,7 +1699,7 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost) | |||
1706 | 1699 | ||
1707 | fc_host_max_npiv_vports(shost) = phba->max_vpi; | 1700 | fc_host_max_npiv_vports(shost) = phba->max_vpi; |
1708 | spin_lock_irq(shost->host_lock); | 1701 | spin_lock_irq(shost->host_lock); |
1709 | vport->fc_flag &= ~FC_LOADING; | 1702 | vport->load_flag &= ~FC_LOADING; |
1710 | spin_unlock_irq(shost->host_lock); | 1703 | spin_unlock_irq(shost->host_lock); |
1711 | } | 1704 | } |
1712 | 1705 | ||
@@ -1718,9 +1711,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1718 | struct lpfc_sli *psli; | 1711 | struct lpfc_sli *psli; |
1719 | struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL; | 1712 | struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL; |
1720 | struct Scsi_Host *shost = NULL; | 1713 | struct Scsi_Host *shost = NULL; |
1714 | void *ptr; | ||
1721 | unsigned long bar0map_len, bar2map_len; | 1715 | unsigned long bar0map_len, bar2map_len; |
1722 | int error = -ENODEV; | 1716 | int error = -ENODEV; |
1723 | int i; | 1717 | int i, hbq_count; |
1724 | uint16_t iotag; | 1718 | uint16_t iotag; |
1725 | 1719 | ||
1726 | if (pci_enable_device(pdev)) | 1720 | if (pci_enable_device(pdev)) |
@@ -1741,7 +1735,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1741 | goto out_free_phba; | 1735 | goto out_free_phba; |
1742 | 1736 | ||
1743 | INIT_LIST_HEAD(&phba->port_list); | 1737 | INIT_LIST_HEAD(&phba->port_list); |
1744 | INIT_LIST_HEAD(&phba->hbq_buffer_list); | ||
1745 | /* | 1738 | /* |
1746 | * Get all the module params for configuring this host and then | 1739 | * Get all the module params for configuring this host and then |
1747 | * establish the host. | 1740 | * establish the host. |
@@ -1819,6 +1812,17 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1819 | if (!phba->hbqslimp.virt) | 1812 | if (!phba->hbqslimp.virt) |
1820 | goto out_free_slim; | 1813 | goto out_free_slim; |
1821 | 1814 | ||
1815 | hbq_count = lpfc_sli_hbq_count(); | ||
1816 | ptr = phba->hbqslimp.virt; | ||
1817 | for (i = 0; i < hbq_count; ++i) { | ||
1818 | phba->hbqs[i].hbq_virt = ptr; | ||
1819 | INIT_LIST_HEAD(&phba->hbqs[i].hbq_buffer_list); | ||
1820 | ptr += (lpfc_hbq_defs[i]->entry_count * | ||
1821 | sizeof(struct lpfc_hbq_entry)); | ||
1822 | } | ||
1823 | phba->hbqs[LPFC_ELS_HBQ].hbq_alloc_buffer = lpfc_els_hbq_alloc; | ||
1824 | phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer = lpfc_els_hbq_free; | ||
1825 | |||
1822 | memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size()); | 1826 | memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size()); |
1823 | 1827 | ||
1824 | /* Initialize the SLI Layer to run with lpfc HBAs. */ | 1828 | /* Initialize the SLI Layer to run with lpfc HBAs. */ |
@@ -1894,7 +1898,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1894 | 1898 | ||
1895 | if (phba->cfg_use_msi) { | 1899 | if (phba->cfg_use_msi) { |
1896 | error = pci_enable_msi(phba->pcidev); | 1900 | error = pci_enable_msi(phba->pcidev); |
1897 | if (error) | 1901 | if (!error) |
1902 | phba->using_msi = 1; | ||
1903 | else | ||
1898 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 1904 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
1899 | "0452 Enable MSI failed, continuing " | 1905 | "0452 Enable MSI failed, continuing " |
1900 | "with IRQ\n"); | 1906 | "with IRQ\n"); |
@@ -1941,14 +1947,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1941 | out_remove_device: | 1947 | out_remove_device: |
1942 | lpfc_free_sysfs_attr(vport); | 1948 | lpfc_free_sysfs_attr(vport); |
1943 | spin_lock_irq(shost->host_lock); | 1949 | spin_lock_irq(shost->host_lock); |
1944 | vport->fc_flag |= FC_UNLOADING; | 1950 | vport->load_flag |= FC_UNLOADING; |
1945 | spin_unlock_irq(shost->host_lock); | 1951 | spin_unlock_irq(shost->host_lock); |
1946 | out_free_irq: | 1952 | out_free_irq: |
1947 | lpfc_stop_phba_timers(phba); | 1953 | lpfc_stop_phba_timers(phba); |
1948 | phba->pport->work_port_events = 0; | 1954 | phba->pport->work_port_events = 0; |
1949 | free_irq(phba->pcidev->irq, phba); | 1955 | free_irq(phba->pcidev->irq, phba); |
1950 | out_disable_msi: | 1956 | out_disable_msi: |
1951 | pci_disable_msi(phba->pcidev); | 1957 | if (phba->using_msi) |
1958 | pci_disable_msi(phba->pcidev); | ||
1952 | destroy_port(vport); | 1959 | destroy_port(vport); |
1953 | out_kthread_stop: | 1960 | out_kthread_stop: |
1954 | kthread_stop(phba->worker_thread); | 1961 | kthread_stop(phba->worker_thread); |
@@ -1990,10 +1997,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
1990 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 1997 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
1991 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | 1998 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; |
1992 | struct lpfc_hba *phba = vport->phba; | 1999 | struct lpfc_hba *phba = vport->phba; |
1993 | struct lpfc_vport *port_iterator; | ||
1994 | spin_lock_irq(&phba->hbalock); | 2000 | spin_lock_irq(&phba->hbalock); |
1995 | list_for_each_entry(port_iterator, &phba->port_list, listentry) | 2001 | vport->load_flag |= FC_UNLOADING; |
1996 | port_iterator->load_flag |= FC_UNLOADING; | ||
1997 | spin_unlock_irq(&phba->hbalock); | 2002 | spin_unlock_irq(&phba->hbalock); |
1998 | 2003 | ||
1999 | kfree(vport->vname); | 2004 | kfree(vport->vname); |
@@ -2001,7 +2006,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2001 | 2006 | ||
2002 | fc_remove_host(shost); | 2007 | fc_remove_host(shost); |
2003 | scsi_remove_host(shost); | 2008 | scsi_remove_host(shost); |
2004 | |||
2005 | /* | 2009 | /* |
2006 | * Bring down the SLI Layer. This step disable all interrupts, | 2010 | * Bring down the SLI Layer. This step disable all interrupts, |
2007 | * clears the rings, discards all mailbox commands, and resets | 2011 | * clears the rings, discards all mailbox commands, and resets |
@@ -2022,7 +2026,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2022 | 2026 | ||
2023 | /* Release the irq reservation */ | 2027 | /* Release the irq reservation */ |
2024 | free_irq(phba->pcidev->irq, phba); | 2028 | free_irq(phba->pcidev->irq, phba); |
2025 | pci_disable_msi(phba->pcidev); | 2029 | if (phba->using_msi) |
2030 | pci_disable_msi(phba->pcidev); | ||
2026 | 2031 | ||
2027 | pci_set_drvdata(pdev, NULL); | 2032 | pci_set_drvdata(pdev, NULL); |
2028 | scsi_host_put(shost); | 2033 | scsi_host_put(shost); |
@@ -2064,8 +2069,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2064 | static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, | 2069 | static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, |
2065 | pci_channel_state_t state) | 2070 | pci_channel_state_t state) |
2066 | { | 2071 | { |
2067 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 2072 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
2068 | struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; | 2073 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
2069 | struct lpfc_sli *psli = &phba->sli; | 2074 | struct lpfc_sli *psli = &phba->sli; |
2070 | struct lpfc_sli_ring *pring; | 2075 | struct lpfc_sli_ring *pring; |
2071 | 2076 | ||
@@ -2081,6 +2086,11 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, | |||
2081 | pring = &psli->ring[psli->fcp_ring]; | 2086 | pring = &psli->ring[psli->fcp_ring]; |
2082 | lpfc_sli_abort_iocb_ring(phba, pring); | 2087 | lpfc_sli_abort_iocb_ring(phba, pring); |
2083 | 2088 | ||
2089 | /* Release the irq reservation */ | ||
2090 | free_irq(phba->pcidev->irq, phba); | ||
2091 | if (phba->using_msi) | ||
2092 | pci_disable_msi(phba->pcidev); | ||
2093 | |||
2084 | /* Request a slot reset. */ | 2094 | /* Request a slot reset. */ |
2085 | return PCI_ERS_RESULT_NEED_RESET; | 2095 | return PCI_ERS_RESULT_NEED_RESET; |
2086 | } | 2096 | } |
@@ -2093,8 +2103,8 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, | |||
2093 | */ | 2103 | */ |
2094 | static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | 2104 | static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) |
2095 | { | 2105 | { |
2096 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 2106 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
2097 | struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; | 2107 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
2098 | struct lpfc_sli *psli = &phba->sli; | 2108 | struct lpfc_sli *psli = &phba->sli; |
2099 | int bars = pci_select_bars(pdev, IORESOURCE_MEM); | 2109 | int bars = pci_select_bars(pdev, IORESOURCE_MEM); |
2100 | 2110 | ||
@@ -2108,9 +2118,9 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | |||
2108 | pci_set_master(pdev); | 2118 | pci_set_master(pdev); |
2109 | 2119 | ||
2110 | /* Re-establishing Link */ | 2120 | /* Re-establishing Link */ |
2111 | spin_lock_irq(host->host_lock); | 2121 | spin_lock_irq(shost->host_lock); |
2112 | phba->pport->fc_flag |= FC_ESTABLISH_LINK; | 2122 | phba->pport->fc_flag |= FC_ESTABLISH_LINK; |
2113 | spin_unlock_irq(host->host_lock); | 2123 | spin_unlock_irq(shost->host_lock); |
2114 | 2124 | ||
2115 | spin_lock_irq(&phba->hbalock); | 2125 | spin_lock_irq(&phba->hbalock); |
2116 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | 2126 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; |
@@ -2133,8 +2143,8 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | |||
2133 | */ | 2143 | */ |
2134 | static void lpfc_io_resume(struct pci_dev *pdev) | 2144 | static void lpfc_io_resume(struct pci_dev *pdev) |
2135 | { | 2145 | { |
2136 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 2146 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
2137 | struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; | 2147 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
2138 | 2148 | ||
2139 | if (lpfc_online(phba) == 0) { | 2149 | if (lpfc_online(phba) == 0) { |
2140 | mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); | 2150 | mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 09ecdcb63a74..a592733664e9 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -560,7 +560,8 @@ lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb, | |||
560 | } | 560 | } |
561 | 561 | ||
562 | void | 562 | void |
563 | lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc, | 563 | lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id, |
564 | struct lpfc_hbq_init *hbq_desc, | ||
564 | uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb) | 565 | uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb) |
565 | { | 566 | { |
566 | int i; | 567 | int i; |
@@ -568,6 +569,7 @@ lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc, | |||
568 | struct config_hbq_var *hbqmb = &mb->un.varCfgHbq; | 569 | struct config_hbq_var *hbqmb = &mb->un.varCfgHbq; |
569 | 570 | ||
570 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 571 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
572 | hbqmb->hbqId = id; | ||
571 | hbqmb->entry_count = hbq_desc->entry_count; /* # entries in HBQ */ | 573 | hbqmb->entry_count = hbq_desc->entry_count; /* # entries in HBQ */ |
572 | hbqmb->recvNotify = hbq_desc->rn; /* Receive | 574 | hbqmb->recvNotify = hbq_desc->rn; /* Receive |
573 | * Notification */ | 575 | * Notification */ |
@@ -687,7 +689,7 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
687 | 689 | ||
688 | if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { | 690 | if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { |
689 | mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ | 691 | mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ |
690 | mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */ | 692 | mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count(); |
691 | if (phba->max_vpi && phba->cfg_enable_npiv && | 693 | if (phba->max_vpi && phba->cfg_enable_npiv && |
692 | phba->vpd.sli3Feat.cmv) { | 694 | phba->vpd.sli3Feat.cmv) { |
693 | mb->un.varCfgPort.max_vpi = phba->max_vpi; | 695 | mb->un.varCfgPort.max_vpi = phba->max_vpi; |
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 3594c469494f..43c3b8a0d76a 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
@@ -231,21 +231,34 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) | |||
231 | return; | 231 | return; |
232 | } | 232 | } |
233 | 233 | ||
234 | void * | 234 | struct hbq_dmabuf * |
235 | lpfc_hbq_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) | 235 | lpfc_els_hbq_alloc(struct lpfc_hba *phba) |
236 | { | 236 | { |
237 | void *ret; | 237 | struct hbq_dmabuf *hbqbp; |
238 | ret = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_ATOMIC, handle); | 238 | |
239 | return ret; | 239 | hbqbp = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); |
240 | if (!hbqbp) | ||
241 | return NULL; | ||
242 | |||
243 | hbqbp->dbuf.virt = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_KERNEL, | ||
244 | &hbqbp->dbuf.phys); | ||
245 | if (!hbqbp->dbuf.virt) { | ||
246 | kfree(hbqbp); | ||
247 | return NULL; | ||
248 | } | ||
249 | hbqbp->size = LPFC_BPL_SIZE; | ||
250 | return hbqbp; | ||
240 | } | 251 | } |
241 | 252 | ||
242 | void | 253 | void |
243 | lpfc_hbq_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma) | 254 | lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp) |
244 | { | 255 | { |
245 | pci_pool_free(phba->lpfc_hbq_pool, virt, dma); | 256 | pci_pool_free(phba->lpfc_hbq_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys); |
257 | kfree(hbqbp); | ||
246 | return; | 258 | return; |
247 | } | 259 | } |
248 | 260 | ||
261 | /* This is ONLY called for the LPFC_ELS_HBQ */ | ||
249 | void | 262 | void |
250 | lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) | 263 | lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) |
251 | { | 264 | { |
@@ -254,9 +267,8 @@ lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) | |||
254 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { | 267 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { |
255 | hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); | 268 | hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); |
256 | if (hbq_entry->tag == -1) { | 269 | if (hbq_entry->tag == -1) { |
257 | lpfc_hbq_free(phba, hbq_entry->dbuf.virt, | 270 | (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer) |
258 | hbq_entry->dbuf.phys); | 271 | (phba, hbq_entry); |
259 | kfree(hbq_entry); | ||
260 | } else { | 272 | } else { |
261 | lpfc_sli_free_hbq(phba, hbq_entry); | 273 | lpfc_sli_free_hbq(phba, hbq_entry); |
262 | } | 274 | } |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 66ba51cbeb50..880af0cd463d 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -329,7 +329,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
329 | case NLP_STE_PRLI_ISSUE: | 329 | case NLP_STE_PRLI_ISSUE: |
330 | case NLP_STE_UNMAPPED_NODE: | 330 | case NLP_STE_UNMAPPED_NODE: |
331 | case NLP_STE_MAPPED_NODE: | 331 | case NLP_STE_MAPPED_NODE: |
332 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0); | 332 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); |
333 | return 1; | 333 | return 1; |
334 | } | 334 | } |
335 | 335 | ||
@@ -407,7 +407,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
407 | ndlp, mbox); | 407 | ndlp, mbox); |
408 | return 1; | 408 | return 1; |
409 | } | 409 | } |
410 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); | 410 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); |
411 | return 1; | 411 | return 1; |
412 | 412 | ||
413 | out: | 413 | out: |
@@ -451,7 +451,7 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
451 | lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp); | 451 | lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp); |
452 | } else { | 452 | } else { |
453 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, | 453 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, |
454 | NULL, 0); | 454 | NULL); |
455 | } | 455 | } |
456 | return 1; | 456 | return 1; |
457 | } | 457 | } |
@@ -488,9 +488,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
488 | ndlp->nlp_flag |= NLP_LOGO_ACC; | 488 | ndlp->nlp_flag |= NLP_LOGO_ACC; |
489 | spin_unlock_irq(shost->host_lock); | 489 | spin_unlock_irq(shost->host_lock); |
490 | if (els_cmd == ELS_CMD_PRLO) | 490 | if (els_cmd == ELS_CMD_PRLO) |
491 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); | 491 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); |
492 | else | 492 | else |
493 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 493 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
494 | 494 | ||
495 | if (!(ndlp->nlp_type & NLP_FABRIC) || | 495 | if (!(ndlp->nlp_type & NLP_FABRIC) || |
496 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { | 496 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { |
@@ -564,6 +564,11 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
564 | { | 564 | { |
565 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 565 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
566 | 566 | ||
567 | if (!ndlp->nlp_rpi) { | ||
568 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | ||
569 | return 0; | ||
570 | } | ||
571 | |||
567 | /* Check config parameter use-adisc or FCP-2 */ | 572 | /* Check config parameter use-adisc or FCP-2 */ |
568 | if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || | 573 | if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || |
569 | ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { | 574 | ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { |
@@ -627,7 +632,7 @@ lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
627 | spin_lock_irq(shost->host_lock); | 632 | spin_lock_irq(shost->host_lock); |
628 | ndlp->nlp_flag |= NLP_LOGO_ACC; | 633 | ndlp->nlp_flag |= NLP_LOGO_ACC; |
629 | spin_unlock_irq(shost->host_lock); | 634 | spin_unlock_irq(shost->host_lock); |
630 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 635 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
631 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 636 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
632 | 637 | ||
633 | return ndlp->nlp_state; | 638 | return ndlp->nlp_state; |
@@ -723,7 +728,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
723 | lpfc_els_abort(phba, ndlp); | 728 | lpfc_els_abort(phba, ndlp); |
724 | 729 | ||
725 | if (evt == NLP_EVT_RCV_LOGO) { | 730 | if (evt == NLP_EVT_RCV_LOGO) { |
726 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 731 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
727 | } else { | 732 | } else { |
728 | lpfc_issue_els_logo(vport, ndlp, 0); | 733 | lpfc_issue_els_logo(vport, ndlp, 0); |
729 | } | 734 | } |
@@ -1167,7 +1172,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport, | |||
1167 | struct lpfc_iocbq *cmdiocb; | 1172 | struct lpfc_iocbq *cmdiocb; |
1168 | 1173 | ||
1169 | cmdiocb = (struct lpfc_iocbq *) arg; | 1174 | cmdiocb = (struct lpfc_iocbq *) arg; |
1170 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); | 1175 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); |
1171 | return ndlp->nlp_state; | 1176 | return ndlp->nlp_state; |
1172 | } | 1177 | } |
1173 | 1178 | ||
@@ -1322,7 +1327,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1322 | { | 1327 | { |
1323 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 1328 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1324 | 1329 | ||
1325 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); | 1330 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); |
1326 | return ndlp->nlp_state; | 1331 | return ndlp->nlp_state; |
1327 | } | 1332 | } |
1328 | 1333 | ||
@@ -1514,7 +1519,7 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1514 | { | 1519 | { |
1515 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 1520 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1516 | 1521 | ||
1517 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); | 1522 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); |
1518 | return ndlp->nlp_state; | 1523 | return ndlp->nlp_state; |
1519 | } | 1524 | } |
1520 | 1525 | ||
@@ -1585,8 +1590,8 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1585 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 1590 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1586 | 1591 | ||
1587 | /* flush the target */ | 1592 | /* flush the target */ |
1588 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 1593 | lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], |
1589 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 1594 | ndlp->nlp_sid, 0, LPFC_CTX_TGT); |
1590 | 1595 | ||
1591 | /* Treat like rcv logo */ | 1596 | /* Treat like rcv logo */ |
1592 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); | 1597 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); |
@@ -1719,7 +1724,7 @@ lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1719 | ndlp->nlp_flag |= NLP_LOGO_ACC; | 1724 | ndlp->nlp_flag |= NLP_LOGO_ACC; |
1720 | spin_unlock_irq(shost->host_lock); | 1725 | spin_unlock_irq(shost->host_lock); |
1721 | 1726 | ||
1722 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 1727 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
1723 | 1728 | ||
1724 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) { | 1729 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) { |
1725 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 1730 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 9ee2927ad82a..94458d7a8f7f 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -152,7 +152,6 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) | |||
152 | } | 152 | } |
153 | } | 153 | } |
154 | lpfc_destroy_vport_work_array(vports); | 154 | lpfc_destroy_vport_work_array(vports); |
155 | spin_unlock_irq(&phba->hbalock); | ||
156 | atomic_set(&phba->num_rsrc_err, 0); | 155 | atomic_set(&phba->num_rsrc_err, 0); |
157 | atomic_set(&phba->num_cmd_success, 0); | 156 | atomic_set(&phba->num_cmd_success, 0); |
158 | } | 157 | } |
@@ -1195,14 +1194,12 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) | |||
1195 | * Unfortunately, some targets do not abide by this forcing the driver | 1194 | * Unfortunately, some targets do not abide by this forcing the driver |
1196 | * to double check. | 1195 | * to double check. |
1197 | */ | 1196 | */ |
1198 | cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 1197 | cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id, cmnd->device->lun, |
1199 | cmnd->device->id, cmnd->device->lun, | ||
1200 | LPFC_CTX_LUN); | 1198 | LPFC_CTX_LUN); |
1201 | if (cnt) | 1199 | if (cnt) |
1202 | lpfc_sli_abort_iocb(phba, | 1200 | lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], |
1203 | &phba->sli.ring[phba->sli.fcp_ring], | ||
1204 | cmnd->device->id, cmnd->device->lun, | 1201 | cmnd->device->id, cmnd->device->lun, |
1205 | 0, LPFC_CTX_LUN); | 1202 | LPFC_CTX_LUN); |
1206 | loopcnt = 0; | 1203 | loopcnt = 0; |
1207 | while(cnt) { | 1204 | while(cnt) { |
1208 | schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); | 1205 | schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); |
@@ -1211,10 +1208,8 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) | |||
1211 | > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT) | 1208 | > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT) |
1212 | break; | 1209 | break; |
1213 | 1210 | ||
1214 | cnt = lpfc_sli_sum_iocb(phba, | 1211 | cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id, |
1215 | &phba->sli.ring[phba->sli.fcp_ring], | 1212 | cmnd->device->lun, LPFC_CTX_LUN); |
1216 | cmnd->device->id, cmnd->device->lun, | ||
1217 | LPFC_CTX_LUN); | ||
1218 | } | 1213 | } |
1219 | 1214 | ||
1220 | if (cnt) { | 1215 | if (cnt) { |
@@ -1304,11 +1299,10 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) | |||
1304 | * the targets. Unfortunately, some targets do not abide by | 1299 | * the targets. Unfortunately, some targets do not abide by |
1305 | * this forcing the driver to double check. | 1300 | * this forcing the driver to double check. |
1306 | */ | 1301 | */ |
1307 | cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 1302 | cnt = lpfc_sli_sum_iocb(vport, 0, 0, LPFC_CTX_HOST); |
1308 | 0, 0, LPFC_CTX_HOST); | ||
1309 | if (cnt) | 1303 | if (cnt) |
1310 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 1304 | lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], |
1311 | 0, 0, 0, LPFC_CTX_HOST); | 1305 | 0, 0, LPFC_CTX_HOST); |
1312 | loopcnt = 0; | 1306 | loopcnt = 0; |
1313 | while(cnt) { | 1307 | while(cnt) { |
1314 | schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); | 1308 | schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); |
@@ -1317,9 +1311,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) | |||
1317 | > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT) | 1311 | > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT) |
1318 | break; | 1312 | break; |
1319 | 1313 | ||
1320 | cnt = lpfc_sli_sum_iocb(phba, | 1314 | cnt = lpfc_sli_sum_iocb(vport, 0, 0, LPFC_CTX_HOST); |
1321 | &phba->sli.ring[phba->sli.fcp_ring], | ||
1322 | 0, 0, LPFC_CTX_HOST); | ||
1323 | } | 1315 | } |
1324 | 1316 | ||
1325 | if (cnt) { | 1317 | if (cnt) { |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 5417bc26f181..c54a9ea336a6 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -545,7 +545,8 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno) | |||
545 | return NULL; | 545 | return NULL; |
546 | } | 546 | } |
547 | 547 | ||
548 | return (struct lpfc_hbq_entry *) phba->hbqslimp.virt + hbqp->hbqPutIdx; | 548 | return (struct lpfc_hbq_entry *) phba->hbqs[hbqno].hbq_virt + |
549 | hbqp->hbqPutIdx; | ||
549 | } | 550 | } |
550 | 551 | ||
551 | void | 552 | void |
@@ -553,18 +554,21 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) | |||
553 | { | 554 | { |
554 | struct lpfc_dmabuf *dmabuf, *next_dmabuf; | 555 | struct lpfc_dmabuf *dmabuf, *next_dmabuf; |
555 | struct hbq_dmabuf *hbq_buf; | 556 | struct hbq_dmabuf *hbq_buf; |
557 | int i, hbq_count; | ||
556 | 558 | ||
559 | hbq_count = lpfc_sli_hbq_count(); | ||
557 | /* Return all memory used by all HBQs */ | 560 | /* Return all memory used by all HBQs */ |
558 | list_for_each_entry_safe(dmabuf, next_dmabuf, | 561 | for (i = 0; i < hbq_count; ++i) { |
559 | &phba->hbq_buffer_list, list) { | 562 | list_for_each_entry_safe(dmabuf, next_dmabuf, |
560 | hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf); | 563 | &phba->hbqs[i].hbq_buffer_list, list) { |
561 | list_del(&hbq_buf->dbuf.list); | 564 | hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf); |
562 | lpfc_hbq_free(phba, hbq_buf->dbuf.virt, hbq_buf->dbuf.phys); | 565 | list_del(&hbq_buf->dbuf.list); |
563 | kfree(hbq_buf); | 566 | (phba->hbqs[i].hbq_free_buffer)(phba, hbq_buf); |
567 | } | ||
564 | } | 568 | } |
565 | } | 569 | } |
566 | 570 | ||
567 | static void | 571 | static struct lpfc_hbq_entry * |
568 | lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, | 572 | lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, |
569 | struct hbq_dmabuf *hbq_buf) | 573 | struct hbq_dmabuf *hbq_buf) |
570 | { | 574 | { |
@@ -578,7 +582,7 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, | |||
578 | 582 | ||
579 | hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr)); | 583 | hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr)); |
580 | hbqe->bde.addrLow = le32_to_cpu(putPaddrLow(physaddr)); | 584 | hbqe->bde.addrLow = le32_to_cpu(putPaddrLow(physaddr)); |
581 | hbqe->bde.tus.f.bdeSize = FCELSSIZE; | 585 | hbqe->bde.tus.f.bdeSize = hbq_buf->size; |
582 | hbqe->bde.tus.f.bdeFlags = 0; | 586 | hbqe->bde.tus.f.bdeFlags = 0; |
583 | hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w); | 587 | hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w); |
584 | hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag); | 588 | hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag); |
@@ -587,8 +591,9 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, | |||
587 | writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno); | 591 | writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno); |
588 | /* flush */ | 592 | /* flush */ |
589 | readl(phba->hbq_put + hbqno); | 593 | readl(phba->hbq_put + hbqno); |
590 | list_add_tail(&hbq_buf->dbuf.list, &phba->hbq_buffer_list); | 594 | list_add_tail(&hbq_buf->dbuf.list, &hbqp->hbq_buffer_list); |
591 | } | 595 | } |
596 | return hbqe; | ||
592 | } | 597 | } |
593 | 598 | ||
594 | static struct lpfc_hbq_init lpfc_els_hbq = { | 599 | static struct lpfc_hbq_init lpfc_els_hbq = { |
@@ -596,14 +601,26 @@ static struct lpfc_hbq_init lpfc_els_hbq = { | |||
596 | .entry_count = 200, | 601 | .entry_count = 200, |
597 | .mask_count = 0, | 602 | .mask_count = 0, |
598 | .profile = 0, | 603 | .profile = 0, |
599 | .ring_mask = 1 << LPFC_ELS_RING, | 604 | .ring_mask = (1 << LPFC_ELS_RING), |
600 | .buffer_count = 0, | 605 | .buffer_count = 0, |
601 | .init_count = 20, | 606 | .init_count = 20, |
602 | .add_count = 5, | 607 | .add_count = 5, |
603 | }; | 608 | }; |
604 | 609 | ||
610 | static struct lpfc_hbq_init lpfc_extra_hbq = { | ||
611 | .rn = 1, | ||
612 | .entry_count = 200, | ||
613 | .mask_count = 0, | ||
614 | .profile = 0, | ||
615 | .ring_mask = (1 << LPFC_EXTRA_RING), | ||
616 | .buffer_count = 0, | ||
617 | .init_count = 0, | ||
618 | .add_count = 5, | ||
619 | }; | ||
620 | |||
605 | struct lpfc_hbq_init *lpfc_hbq_defs[] = { | 621 | struct lpfc_hbq_init *lpfc_hbq_defs[] = { |
606 | &lpfc_els_hbq, | 622 | &lpfc_els_hbq, |
623 | &lpfc_extra_hbq, | ||
607 | }; | 624 | }; |
608 | 625 | ||
609 | int | 626 | int |
@@ -612,6 +629,10 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) | |||
612 | uint32_t i, start, end; | 629 | uint32_t i, start, end; |
613 | struct hbq_dmabuf *hbq_buffer; | 630 | struct hbq_dmabuf *hbq_buffer; |
614 | 631 | ||
632 | if (!phba->hbqs[hbqno].hbq_alloc_buffer) { | ||
633 | return 0; | ||
634 | } | ||
635 | |||
615 | start = lpfc_hbq_defs[hbqno]->buffer_count; | 636 | start = lpfc_hbq_defs[hbqno]->buffer_count; |
616 | end = count + lpfc_hbq_defs[hbqno]->buffer_count; | 637 | end = count + lpfc_hbq_defs[hbqno]->buffer_count; |
617 | if (end > lpfc_hbq_defs[hbqno]->entry_count) { | 638 | if (end > lpfc_hbq_defs[hbqno]->entry_count) { |
@@ -620,17 +641,14 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) | |||
620 | 641 | ||
621 | /* Populate HBQ entries */ | 642 | /* Populate HBQ entries */ |
622 | for (i = start; i < end; i++) { | 643 | for (i = start; i < end; i++) { |
623 | hbq_buffer = kmalloc(sizeof(struct hbq_dmabuf), | 644 | hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba); |
624 | GFP_KERNEL); | ||
625 | if (!hbq_buffer) | 645 | if (!hbq_buffer) |
626 | return 1; | 646 | return 1; |
627 | hbq_buffer->dbuf.virt = lpfc_hbq_alloc(phba, MEM_PRI, | ||
628 | &hbq_buffer->dbuf.phys); | ||
629 | if (hbq_buffer->dbuf.virt == NULL) | ||
630 | return 1; | ||
631 | hbq_buffer->tag = (i | (hbqno << 16)); | 647 | hbq_buffer->tag = (i | (hbqno << 16)); |
632 | lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer); | 648 | if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) |
633 | lpfc_hbq_defs[hbqno]->buffer_count++; | 649 | lpfc_hbq_defs[hbqno]->buffer_count++; |
650 | else | ||
651 | (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer); | ||
634 | } | 652 | } |
635 | return 0; | 653 | return 0; |
636 | } | 654 | } |
@@ -654,10 +672,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) | |||
654 | { | 672 | { |
655 | struct lpfc_dmabuf *d_buf; | 673 | struct lpfc_dmabuf *d_buf; |
656 | struct hbq_dmabuf *hbq_buf; | 674 | struct hbq_dmabuf *hbq_buf; |
675 | uint32_t hbqno; | ||
676 | |||
677 | hbqno = tag >> 16; | ||
678 | if (hbqno > LPFC_MAX_HBQS) | ||
679 | return NULL; | ||
657 | 680 | ||
658 | list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) { | 681 | list_for_each_entry(d_buf, &phba->hbqs[hbqno].hbq_buffer_list, list) { |
659 | hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); | 682 | hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); |
660 | if ((hbq_buf->tag & 0xffff) == tag) { | 683 | if (hbq_buf->tag == tag) { |
661 | return hbq_buf; | 684 | return hbq_buf; |
662 | } | 685 | } |
663 | } | 686 | } |
@@ -668,13 +691,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) | |||
668 | } | 691 | } |
669 | 692 | ||
670 | void | 693 | void |
671 | lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *sp) | 694 | lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer) |
672 | { | 695 | { |
673 | uint32_t hbqno; | 696 | uint32_t hbqno; |
674 | 697 | ||
675 | if (sp) { | 698 | if (hbq_buffer) { |
676 | hbqno = sp->tag >> 16; | 699 | hbqno = hbq_buffer->tag >> 16; |
677 | lpfc_sli_hbq_to_firmware(phba, hbqno, sp); | 700 | if (!lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) { |
701 | (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer); | ||
702 | } | ||
678 | } | 703 | } |
679 | } | 704 | } |
680 | 705 | ||
@@ -904,21 +929,26 @@ static struct lpfc_dmabuf * | |||
904 | lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) | 929 | lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) |
905 | { | 930 | { |
906 | struct hbq_dmabuf *hbq_entry, *new_hbq_entry; | 931 | struct hbq_dmabuf *hbq_entry, *new_hbq_entry; |
932 | uint32_t hbqno; | ||
933 | void *virt; /* virtual address ptr */ | ||
934 | dma_addr_t phys; /* mapped address */ | ||
907 | 935 | ||
908 | hbq_entry = lpfc_sli_hbqbuf_find(phba, tag); | 936 | hbq_entry = lpfc_sli_hbqbuf_find(phba, tag); |
909 | if (hbq_entry == NULL) | 937 | if (hbq_entry == NULL) |
910 | return NULL; | 938 | return NULL; |
911 | list_del(&hbq_entry->dbuf.list); | 939 | list_del(&hbq_entry->dbuf.list); |
912 | new_hbq_entry = kmalloc(sizeof(struct hbq_dmabuf), GFP_ATOMIC); | 940 | |
941 | hbqno = tag >> 16; | ||
942 | new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba); | ||
913 | if (new_hbq_entry == NULL) | 943 | if (new_hbq_entry == NULL) |
914 | return &hbq_entry->dbuf; | 944 | return &hbq_entry->dbuf; |
915 | new_hbq_entry->dbuf = hbq_entry->dbuf; | ||
916 | new_hbq_entry->tag = -1; | 945 | new_hbq_entry->tag = -1; |
917 | hbq_entry->dbuf.virt = lpfc_hbq_alloc(phba, 0, &hbq_entry->dbuf.phys); | 946 | phys = new_hbq_entry->dbuf.phys; |
918 | if (hbq_entry->dbuf.virt == NULL) { | 947 | virt = new_hbq_entry->dbuf.virt; |
919 | kfree(new_hbq_entry); | 948 | new_hbq_entry->dbuf.phys = hbq_entry->dbuf.phys; |
920 | return &hbq_entry->dbuf; | 949 | new_hbq_entry->dbuf.virt = hbq_entry->dbuf.virt; |
921 | } | 950 | hbq_entry->dbuf.phys = phys; |
951 | hbq_entry->dbuf.virt = virt; | ||
922 | lpfc_sli_free_hbq(phba, hbq_entry); | 952 | lpfc_sli_free_hbq(phba, hbq_entry); |
923 | return &new_hbq_entry->dbuf; | 953 | return &new_hbq_entry->dbuf; |
924 | } | 954 | } |
@@ -964,7 +994,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
964 | irsp->un.ulpWord[3]); | 994 | irsp->un.ulpWord[3]); |
965 | if (irsp->ulpBdeCount == 2) | 995 | if (irsp->ulpBdeCount == 2) |
966 | saveq->context3 = lpfc_sli_replace_hbqbuff(phba, | 996 | saveq->context3 = lpfc_sli_replace_hbqbuff(phba, |
967 | irsp->un.ulpWord[15]); | 997 | irsp->unsli3.sli3Words[7]); |
968 | } | 998 | } |
969 | 999 | ||
970 | /* unSolicited Responses */ | 1000 | /* unSolicited Responses */ |
@@ -2189,8 +2219,8 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba) | |||
2189 | phba->hbqs[hbqno].local_hbqGetIdx = 0; | 2219 | phba->hbqs[hbqno].local_hbqGetIdx = 0; |
2190 | phba->hbqs[hbqno].entry_count = | 2220 | phba->hbqs[hbqno].entry_count = |
2191 | lpfc_hbq_defs[hbqno]->entry_count; | 2221 | lpfc_hbq_defs[hbqno]->entry_count; |
2192 | lpfc_config_hbq(phba, lpfc_hbq_defs[hbqno], hbq_entry_index, | 2222 | lpfc_config_hbq(phba, hbqno, lpfc_hbq_defs[hbqno], |
2193 | pmb); | 2223 | hbq_entry_index, pmb); |
2194 | hbq_entry_index += phba->hbqs[hbqno].entry_count; | 2224 | hbq_entry_index += phba->hbqs[hbqno].entry_count; |
2195 | 2225 | ||
2196 | if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { | 2226 | if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { |
@@ -3433,8 +3463,8 @@ abort_iotag_exit: | |||
3433 | } | 3463 | } |
3434 | 3464 | ||
3435 | static int | 3465 | static int |
3436 | lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, | 3466 | lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, |
3437 | uint64_t lun_id, uint32_t ctx, | 3467 | uint16_t tgt_id, uint64_t lun_id, |
3438 | lpfc_ctx_cmd ctx_cmd) | 3468 | lpfc_ctx_cmd ctx_cmd) |
3439 | { | 3469 | { |
3440 | struct lpfc_scsi_buf *lpfc_cmd; | 3470 | struct lpfc_scsi_buf *lpfc_cmd; |
@@ -3444,6 +3474,9 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, | |||
3444 | if (!(iocbq->iocb_flag & LPFC_IO_FCP)) | 3474 | if (!(iocbq->iocb_flag & LPFC_IO_FCP)) |
3445 | return rc; | 3475 | return rc; |
3446 | 3476 | ||
3477 | if (iocbq->vport != vport) | ||
3478 | return rc; | ||
3479 | |||
3447 | lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); | 3480 | lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); |
3448 | cmnd = lpfc_cmd->pCmd; | 3481 | cmnd = lpfc_cmd->pCmd; |
3449 | 3482 | ||
@@ -3460,10 +3493,6 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, | |||
3460 | if (cmnd->device->id == tgt_id) | 3493 | if (cmnd->device->id == tgt_id) |
3461 | rc = 0; | 3494 | rc = 0; |
3462 | break; | 3495 | break; |
3463 | case LPFC_CTX_CTX: | ||
3464 | if (iocbq->iocb.ulpContext == ctx) | ||
3465 | rc = 0; | ||
3466 | break; | ||
3467 | case LPFC_CTX_HOST: | 3496 | case LPFC_CTX_HOST: |
3468 | rc = 0; | 3497 | rc = 0; |
3469 | break; | 3498 | break; |
@@ -3477,17 +3506,18 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, | |||
3477 | } | 3506 | } |
3478 | 3507 | ||
3479 | int | 3508 | int |
3480 | lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 3509 | lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, |
3481 | uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) | 3510 | lpfc_ctx_cmd ctx_cmd) |
3482 | { | 3511 | { |
3512 | struct lpfc_hba *phba = vport->phba; | ||
3483 | struct lpfc_iocbq *iocbq; | 3513 | struct lpfc_iocbq *iocbq; |
3484 | int sum, i; | 3514 | int sum, i; |
3485 | 3515 | ||
3486 | for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) { | 3516 | for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) { |
3487 | iocbq = phba->sli.iocbq_lookup[i]; | 3517 | iocbq = phba->sli.iocbq_lookup[i]; |
3488 | 3518 | ||
3489 | if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id, | 3519 | if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id, |
3490 | 0, ctx_cmd) == 0) | 3520 | ctx_cmd) == 0) |
3491 | sum++; | 3521 | sum++; |
3492 | } | 3522 | } |
3493 | 3523 | ||
@@ -3503,10 +3533,10 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
3503 | } | 3533 | } |
3504 | 3534 | ||
3505 | int | 3535 | int |
3506 | lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 3536 | lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, |
3507 | uint16_t tgt_id, uint64_t lun_id, uint32_t ctx, | 3537 | uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd abort_cmd) |
3508 | lpfc_ctx_cmd abort_cmd) | ||
3509 | { | 3538 | { |
3539 | struct lpfc_hba *phba = vport->phba; | ||
3510 | struct lpfc_iocbq *iocbq; | 3540 | struct lpfc_iocbq *iocbq; |
3511 | struct lpfc_iocbq *abtsiocb; | 3541 | struct lpfc_iocbq *abtsiocb; |
3512 | IOCB_t *cmd = NULL; | 3542 | IOCB_t *cmd = NULL; |
@@ -3516,7 +3546,7 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3516 | for (i = 1; i <= phba->sli.last_iotag; i++) { | 3546 | for (i = 1; i <= phba->sli.last_iotag; i++) { |
3517 | iocbq = phba->sli.iocbq_lookup[i]; | 3547 | iocbq = phba->sli.iocbq_lookup[i]; |
3518 | 3548 | ||
3519 | if (lpfc_sli_validate_fcp_iocb(iocbq, tgt_id, lun_id, 0, | 3549 | if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id, |
3520 | abort_cmd) != 0) | 3550 | abort_cmd) != 0) |
3521 | continue; | 3551 | continue; |
3522 | 3552 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 76058505795e..50f6d627da2e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -26,7 +26,6 @@ struct lpfc_vport; | |||
26 | typedef enum _lpfc_ctx_cmd { | 26 | typedef enum _lpfc_ctx_cmd { |
27 | LPFC_CTX_LUN, | 27 | LPFC_CTX_LUN, |
28 | LPFC_CTX_TGT, | 28 | LPFC_CTX_TGT, |
29 | LPFC_CTX_CTX, | ||
30 | LPFC_CTX_HOST | 29 | LPFC_CTX_HOST |
31 | } lpfc_ctx_cmd; | 30 | } lpfc_ctx_cmd; |
32 | 31 | ||
@@ -54,9 +53,10 @@ struct lpfc_iocbq { | |||
54 | void *context2; /* caller context information */ | 53 | void *context2; /* caller context information */ |
55 | void *context3; /* caller context information */ | 54 | void *context3; /* caller context information */ |
56 | union { | 55 | union { |
57 | wait_queue_head_t *wait_queue; | 56 | wait_queue_head_t *wait_queue; |
58 | struct lpfc_iocbq *rsp_iocb; | 57 | struct lpfc_iocbq *rsp_iocb; |
59 | struct lpfcMboxq *mbox; | 58 | struct lpfcMboxq *mbox; |
59 | struct lpfc_nodelist *ndlp; | ||
60 | } context_un; | 60 | } context_un; |
61 | 61 | ||
62 | void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, | 62 | void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 77067d17c39d..7f0c263d1bd3 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -432,8 +432,29 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
432 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; | 432 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; |
433 | struct lpfc_hba *phba = vport->phba; | 433 | struct lpfc_hba *phba = vport->phba; |
434 | long timeout; | 434 | long timeout; |
435 | int rc = VPORT_ERROR; | ||
436 | 435 | ||
436 | if (vport->port_type == LPFC_PHYSICAL_PORT) { | ||
437 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | ||
438 | "1812 vport_delete failed: Cannot delete " | ||
439 | "physical host\n"); | ||
440 | return VPORT_ERROR; | ||
441 | } | ||
442 | /* | ||
443 | * If we are not unloading the driver then prevent the vport_delete | ||
444 | * from happening until after this vport's discovery is finished. | ||
445 | */ | ||
446 | if (!(phba->pport->load_flag & FC_UNLOADING)) { | ||
447 | int check_count = 0; | ||
448 | while (check_count < ((phba->fc_ratov * 3) + 3) && | ||
449 | vport->port_state > LPFC_VPORT_FAILED && | ||
450 | vport->port_state < LPFC_VPORT_READY) { | ||
451 | check_count++; | ||
452 | msleep(1000); | ||
453 | } | ||
454 | if (vport->port_state > LPFC_VPORT_FAILED && | ||
455 | vport->port_state < LPFC_VPORT_READY) | ||
456 | return -EAGAIN; | ||
457 | } | ||
437 | /* | 458 | /* |
438 | * This is a bit of a mess. We want to ensure the shost doesn't get | 459 | * This is a bit of a mess. We want to ensure the shost doesn't get |
439 | * torn down until we're done with the embedded lpfc_vport structure. | 460 | * torn down until we're done with the embedded lpfc_vport structure. |
@@ -451,16 +472,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
451 | */ | 472 | */ |
452 | if (!scsi_host_get(shost) || !scsi_host_get(shost)) | 473 | if (!scsi_host_get(shost) || !scsi_host_get(shost)) |
453 | return VPORT_INVAL; | 474 | return VPORT_INVAL; |
454 | 475 | spin_lock_irq(&phba->hbalock); | |
455 | if (vport->port_type == LPFC_PHYSICAL_PORT) { | ||
456 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | ||
457 | "1812 vport_delete failed: Cannot delete " | ||
458 | "physical host\n"); | ||
459 | goto out; | ||
460 | } | ||
461 | |||
462 | vport->load_flag |= FC_UNLOADING; | 476 | vport->load_flag |= FC_UNLOADING; |
463 | 477 | spin_unlock_irq(&phba->hbalock); | |
464 | kfree(vport->vname); | 478 | kfree(vport->vname); |
465 | lpfc_debugfs_terminate(vport); | 479 | lpfc_debugfs_terminate(vport); |
466 | fc_remove_host(lpfc_shost_from_vport(vport)); | 480 | fc_remove_host(lpfc_shost_from_vport(vport)); |
@@ -514,10 +528,8 @@ skip_logo: | |||
514 | spin_unlock_irq(&phba->hbalock); | 528 | spin_unlock_irq(&phba->hbalock); |
515 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | 529 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, |
516 | "1828 Vport Deleted.\n"); | 530 | "1828 Vport Deleted.\n"); |
517 | rc = VPORT_OK; | ||
518 | out: | ||
519 | scsi_host_put(shost); | 531 | scsi_host_put(shost); |
520 | return rc; | 532 | return VPORT_OK; |
521 | } | 533 | } |
522 | 534 | ||
523 | EXPORT_SYMBOL(lpfc_vport_create); | 535 | EXPORT_SYMBOL(lpfc_vport_create); |
@@ -536,7 +548,7 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) | |||
536 | spin_lock_irq(&phba->hbalock); | 548 | spin_lock_irq(&phba->hbalock); |
537 | list_for_each_entry(port_iterator, &phba->port_list, listentry) { | 549 | list_for_each_entry(port_iterator, &phba->port_list, listentry) { |
538 | if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) { | 550 | if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) { |
539 | lpfc_printf_vlog(port_iterator, KERN_ERR, LOG_VPORT, | 551 | lpfc_printf_vlog(port_iterator, KERN_WARNING, LOG_VPORT, |
540 | "1801 Create vport work array FAILED: " | 552 | "1801 Create vport work array FAILED: " |
541 | "cannot do scsi_host_get\n"); | 553 | "cannot do scsi_host_get\n"); |
542 | continue; | 554 | continue; |