diff options
author | James Bottomley <jejb@mulgrave.(none)> | 2005-10-29 11:28:33 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-10-29 11:28:33 -0400 |
commit | 604a3e3042eb89ffaa4f735ef9208281aae786c7 (patch) | |
tree | 54c4ad58274b0bb79386c6c57b4849bfb92d4118 /drivers | |
parent | 21568f5387636fe2bfb9ee42383d76de11ed99c7 (diff) |
[SCSI] lpfc: Fix for "command completion for iotax x?? not found"
From: James Smart <James.Smart@emulex.com>
There were scenarios where the error handlers could reuse an iotag
value of an active io. Remove all possibility of this by
pre-assigning iotag resources to command resources.
Signed-off-by: James Smart <James.Smart@emulex.com>
Rejections fixed up and
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 30 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 17 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 27 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 281 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 8 |
9 files changed, 187 insertions, 206 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index ffc58f9a5a59..25f2650f098c 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -143,6 +143,8 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); | |||
143 | int lpfc_mem_alloc(struct lpfc_hba *); | 143 | int lpfc_mem_alloc(struct lpfc_hba *); |
144 | void lpfc_mem_free(struct lpfc_hba *); | 144 | void lpfc_mem_free(struct lpfc_hba *); |
145 | 145 | ||
146 | void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); | ||
147 | uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); | ||
146 | int lpfc_sli_hba_setup(struct lpfc_hba *); | 148 | int lpfc_sli_hba_setup(struct lpfc_hba *); |
147 | int lpfc_sli_hba_down(struct lpfc_hba *); | 149 | int lpfc_sli_hba_down(struct lpfc_hba *); |
148 | int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); | 150 | int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 1280f0e54636..40c34a30a94a 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -235,7 +235,6 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp, | |||
235 | 235 | ||
236 | if (geniocb == NULL) | 236 | if (geniocb == NULL) |
237 | return 1; | 237 | return 1; |
238 | memset(geniocb, 0, sizeof (struct lpfc_iocbq)); | ||
239 | 238 | ||
240 | icmd = &geniocb->iocb; | 239 | icmd = &geniocb->iocb; |
241 | icmd->un.genreq64.bdl.ulpIoTag32 = 0; | 240 | icmd->un.genreq64.bdl.ulpIoTag32 = 0; |
@@ -279,7 +278,7 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp, | |||
279 | geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; | 278 | geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; |
280 | spin_lock_irq(phba->host->host_lock); | 279 | spin_lock_irq(phba->host->host_lock); |
281 | if (lpfc_sli_issue_iocb(phba, pring, geniocb, 0) == IOCB_ERROR) { | 280 | if (lpfc_sli_issue_iocb(phba, pring, geniocb, 0) == IOCB_ERROR) { |
282 | list_add_tail(&geniocb->list, lpfc_iocb_list); | 281 | lpfc_sli_release_iocbq(phba, geniocb); |
283 | spin_unlock_irq(phba->host->host_lock); | 282 | spin_unlock_irq(phba->host->host_lock); |
284 | return 1; | 283 | return 1; |
285 | } | 284 | } |
@@ -487,7 +486,7 @@ out: | |||
487 | kfree(inp); | 486 | kfree(inp); |
488 | kfree(bmp); | 487 | kfree(bmp); |
489 | spin_lock_irq(phba->host->host_lock); | 488 | spin_lock_irq(phba->host->host_lock); |
490 | list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list); | 489 | lpfc_sli_release_iocbq(phba, cmdiocb); |
491 | spin_unlock_irq(phba->host->host_lock); | 490 | spin_unlock_irq(phba->host->host_lock); |
492 | return; | 491 | return; |
493 | } | 492 | } |
@@ -526,7 +525,7 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
526 | kfree(inp); | 525 | kfree(inp); |
527 | kfree(bmp); | 526 | kfree(bmp); |
528 | spin_lock_irq(phba->host->host_lock); | 527 | spin_lock_irq(phba->host->host_lock); |
529 | list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list); | 528 | lpfc_sli_release_iocbq(phba, cmdiocb); |
530 | spin_unlock_irq(phba->host->host_lock); | 529 | spin_unlock_irq(phba->host->host_lock); |
531 | return; | 530 | return; |
532 | } | 531 | } |
@@ -735,7 +734,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba, | |||
735 | kfree(inp); | 734 | kfree(inp); |
736 | kfree(bmp); | 735 | kfree(bmp); |
737 | spin_lock_irq(phba->host->host_lock); | 736 | spin_lock_irq(phba->host->host_lock); |
738 | list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list); | 737 | lpfc_sli_release_iocbq(phba, cmdiocb); |
739 | spin_unlock_irq(phba->host->host_lock); | 738 | spin_unlock_irq(phba->host->host_lock); |
740 | return; | 739 | return; |
741 | } | 740 | } |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 63caf7fe9725..e931ae6e7464 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -122,7 +122,6 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, | |||
122 | 122 | ||
123 | if (elsiocb == NULL) | 123 | if (elsiocb == NULL) |
124 | return NULL; | 124 | return NULL; |
125 | memset(elsiocb, 0, sizeof (struct lpfc_iocbq)); | ||
126 | icmd = &elsiocb->iocb; | 125 | icmd = &elsiocb->iocb; |
127 | 126 | ||
128 | /* fill in BDEs for command */ | 127 | /* fill in BDEs for command */ |
@@ -133,7 +132,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, | |||
133 | if (pcmd) | 132 | if (pcmd) |
134 | kfree(pcmd); | 133 | kfree(pcmd); |
135 | 134 | ||
136 | list_add_tail(&elsiocb->list, lpfc_iocb_list); | 135 | spin_lock_irq(phba->host->host_lock); |
136 | lpfc_sli_release_iocbq(phba, elsiocb); | ||
137 | spin_unlock_irq(phba->host->host_lock); | ||
137 | return NULL; | 138 | return NULL; |
138 | } | 139 | } |
139 | 140 | ||
@@ -150,7 +151,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, | |||
150 | kfree(prsp); | 151 | kfree(prsp); |
151 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); | 152 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); |
152 | kfree(pcmd); | 153 | kfree(pcmd); |
153 | list_add_tail(&elsiocb->list, lpfc_iocb_list); | 154 | spin_lock_irq(phba->host->host_lock); |
155 | lpfc_sli_release_iocbq(phba, elsiocb); | ||
156 | spin_unlock_irq(phba->host->host_lock); | ||
154 | return NULL; | 157 | return NULL; |
155 | } | 158 | } |
156 | INIT_LIST_HEAD(&prsp->list); | 159 | INIT_LIST_HEAD(&prsp->list); |
@@ -164,7 +167,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, | |||
164 | pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, | 167 | pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, |
165 | &pbuflist->phys); | 168 | &pbuflist->phys); |
166 | if (pbuflist == 0 || pbuflist->virt == 0) { | 169 | if (pbuflist == 0 || pbuflist->virt == 0) { |
167 | list_add_tail(&elsiocb->list, lpfc_iocb_list); | 170 | spin_lock_irq(phba->host->host_lock); |
171 | lpfc_sli_release_iocbq(phba, elsiocb); | ||
172 | spin_unlock_irq(phba->host->host_lock); | ||
168 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); | 173 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); |
169 | lpfc_mbuf_free(phba, prsp->virt, prsp->phys); | 174 | lpfc_mbuf_free(phba, prsp->virt, prsp->phys); |
170 | kfree(pcmd); | 175 | kfree(pcmd); |
@@ -596,10 +601,8 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba) | |||
596 | spin_unlock_irq(phba->host->host_lock); | 601 | spin_unlock_irq(phba->host->host_lock); |
597 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 602 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
598 | spin_lock_irq(phba->host->host_lock); | 603 | spin_lock_irq(phba->host->host_lock); |
599 | } else { | 604 | } else |
600 | list_add_tail(&iocb->list, | 605 | lpfc_sli_release_iocbq(phba, iocb); |
601 | &phba->lpfc_iocb_list); | ||
602 | } | ||
603 | } | 606 | } |
604 | } | 607 | } |
605 | } | 608 | } |
@@ -1713,7 +1716,7 @@ lpfc_els_free_iocb(struct lpfc_hba * phba, struct lpfc_iocbq * elsiocb) | |||
1713 | kfree(buf_ptr); | 1716 | kfree(buf_ptr); |
1714 | } | 1717 | } |
1715 | spin_lock_irq(phba->host->host_lock); | 1718 | spin_lock_irq(phba->host->host_lock); |
1716 | list_add_tail(&elsiocb->list, &phba->lpfc_iocb_list); | 1719 | lpfc_sli_release_iocbq(phba, elsiocb); |
1717 | spin_unlock_irq(phba->host->host_lock); | 1720 | spin_unlock_irq(phba->host->host_lock); |
1718 | return 0; | 1721 | return 0; |
1719 | } | 1722 | } |
@@ -2929,9 +2932,8 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
2929 | spin_unlock_irq(phba->host->host_lock); | 2932 | spin_unlock_irq(phba->host->host_lock); |
2930 | (piocb->iocb_cmpl) (phba, piocb, piocb); | 2933 | (piocb->iocb_cmpl) (phba, piocb, piocb); |
2931 | spin_lock_irq(phba->host->host_lock); | 2934 | spin_lock_irq(phba->host->host_lock); |
2932 | } else { | 2935 | } else |
2933 | list_add_tail(&piocb->list, &phba->lpfc_iocb_list); | 2936 | lpfc_sli_release_iocbq(phba, piocb); |
2934 | } | ||
2935 | } | 2937 | } |
2936 | if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) { | 2938 | if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) { |
2937 | phba->els_tmofunc.expires = jiffies + HZ * timeout; | 2939 | phba->els_tmofunc.expires = jiffies + HZ * timeout; |
@@ -2996,7 +2998,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
2996 | spin_lock_irq(phba->host->host_lock); | 2998 | spin_lock_irq(phba->host->host_lock); |
2997 | } | 2999 | } |
2998 | else | 3000 | else |
2999 | list_add_tail(&piocb->list, &phba->lpfc_iocb_list); | 3001 | lpfc_sli_release_iocbq(phba, piocb); |
3000 | } | 3002 | } |
3001 | 3003 | ||
3002 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | 3004 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { |
@@ -3033,7 +3035,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba) | |||
3033 | spin_lock_irq(phba->host->host_lock); | 3035 | spin_lock_irq(phba->host->host_lock); |
3034 | } | 3036 | } |
3035 | else | 3037 | else |
3036 | list_add_tail(&piocb->list, &phba->lpfc_iocb_list); | 3038 | lpfc_sli_release_iocbq(phba, piocb); |
3037 | } | 3039 | } |
3038 | spin_unlock_irq(phba->host->host_lock); | 3040 | spin_unlock_irq(phba->host->host_lock); |
3039 | return; | 3041 | return; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index cd06d4c471ac..259eeb161b82 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -1445,10 +1445,9 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1445 | iocb, iocb); | 1445 | iocb, iocb); |
1446 | spin_lock_irq(phba->host-> | 1446 | spin_lock_irq(phba->host-> |
1447 | host_lock); | 1447 | host_lock); |
1448 | } else { | 1448 | } else |
1449 | list_add_tail(&iocb->list, | 1449 | lpfc_sli_release_iocbq(phba, |
1450 | &phba->lpfc_iocb_list); | 1450 | iocb); |
1451 | } | ||
1452 | } | 1451 | } |
1453 | } | 1452 | } |
1454 | spin_unlock_irq(phba->host->host_lock); | 1453 | spin_unlock_irq(phba->host->host_lock); |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index e591611f98e2..59e244f04c32 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -886,7 +886,6 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt, | |||
886 | pring->missbufcnt = cnt; | 886 | pring->missbufcnt = cnt; |
887 | return cnt; | 887 | return cnt; |
888 | } | 888 | } |
889 | memset(iocb, 0, sizeof (struct lpfc_iocbq)); | ||
890 | icmd = &iocb->iocb; | 889 | icmd = &iocb->iocb; |
891 | 890 | ||
892 | /* 2 buffers can be posted per command */ | 891 | /* 2 buffers can be posted per command */ |
@@ -899,7 +898,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt, | |||
899 | if (mp1) | 898 | if (mp1) |
900 | kfree(mp1); | 899 | kfree(mp1); |
901 | spin_lock_irq(phba->host->host_lock); | 900 | spin_lock_irq(phba->host->host_lock); |
902 | list_add_tail(&iocb->list, lpfc_iocb_list); | 901 | lpfc_sli_release_iocbq(phba, iocb); |
903 | spin_unlock_irq(phba->host->host_lock); | 902 | spin_unlock_irq(phba->host->host_lock); |
904 | pring->missbufcnt = cnt; | 903 | pring->missbufcnt = cnt; |
905 | return cnt; | 904 | return cnt; |
@@ -918,7 +917,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt, | |||
918 | lpfc_mbuf_free(phba, mp1->virt, mp1->phys); | 917 | lpfc_mbuf_free(phba, mp1->virt, mp1->phys); |
919 | kfree(mp1); | 918 | kfree(mp1); |
920 | spin_lock_irq(phba->host->host_lock); | 919 | spin_lock_irq(phba->host->host_lock); |
921 | list_add_tail(&iocb->list, lpfc_iocb_list); | 920 | lpfc_sli_release_iocbq(phba, iocb); |
922 | spin_unlock_irq(phba->host->host_lock); | 921 | spin_unlock_irq(phba->host->host_lock); |
923 | pring->missbufcnt = cnt; | 922 | pring->missbufcnt = cnt; |
924 | return cnt; | 923 | return cnt; |
@@ -955,7 +954,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt, | |||
955 | kfree(mp2); | 954 | kfree(mp2); |
956 | cnt++; | 955 | cnt++; |
957 | } | 956 | } |
958 | list_add_tail(&iocb->list, lpfc_iocb_list); | 957 | lpfc_sli_release_iocbq(phba, iocb); |
959 | pring->missbufcnt = cnt; | 958 | pring->missbufcnt = cnt; |
960 | spin_unlock_irq(phba->host->host_lock); | 959 | spin_unlock_irq(phba->host->host_lock); |
961 | return cnt; | 960 | return cnt; |
@@ -1328,6 +1327,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1328 | unsigned long bar0map_len, bar2map_len; | 1327 | unsigned long bar0map_len, bar2map_len; |
1329 | int error = -ENODEV, retval; | 1328 | int error = -ENODEV, retval; |
1330 | int i; | 1329 | int i; |
1330 | uint16_t iotag; | ||
1331 | 1331 | ||
1332 | if (pci_enable_device(pdev)) | 1332 | if (pci_enable_device(pdev)) |
1333 | goto out; | 1333 | goto out; |
@@ -1452,6 +1452,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1452 | } | 1452 | } |
1453 | 1453 | ||
1454 | memset(iocbq_entry, 0, sizeof(struct lpfc_iocbq)); | 1454 | memset(iocbq_entry, 0, sizeof(struct lpfc_iocbq)); |
1455 | iotag = lpfc_sli_next_iotag(phba, iocbq_entry); | ||
1456 | if (iotag == 0) { | ||
1457 | kfree (iocbq_entry); | ||
1458 | printk(KERN_ERR "%s: failed to allocate IOTAG. " | ||
1459 | "Unloading driver.\n", | ||
1460 | __FUNCTION__); | ||
1461 | error = -ENOMEM; | ||
1462 | goto out_free_iocbq; | ||
1463 | } | ||
1455 | spin_lock_irq(phba->host->host_lock); | 1464 | spin_lock_irq(phba->host->host_lock); |
1456 | list_add(&iocbq_entry->list, &phba->lpfc_iocb_list); | 1465 | list_add(&iocbq_entry->list, &phba->lpfc_iocb_list); |
1457 | phba->total_iocbq_bufs++; | 1466 | phba->total_iocbq_bufs++; |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 9a58de876d40..507a6af56f42 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -187,10 +187,8 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
187 | spin_unlock_irq(phba->host->host_lock); | 187 | spin_unlock_irq(phba->host->host_lock); |
188 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 188 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
189 | spin_lock_irq(phba->host->host_lock); | 189 | spin_lock_irq(phba->host->host_lock); |
190 | } else { | 190 | } else |
191 | list_add_tail(&iocb->list, | 191 | lpfc_sli_release_iocbq(phba, iocb); |
192 | &phba->lpfc_iocb_list); | ||
193 | } | ||
194 | break; | 192 | break; |
195 | } | 193 | } |
196 | } | 194 | } |
@@ -232,10 +230,8 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
232 | spin_unlock_irq(phba->host->host_lock); | 230 | spin_unlock_irq(phba->host->host_lock); |
233 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 231 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
234 | spin_lock_irq(phba->host->host_lock); | 232 | spin_lock_irq(phba->host->host_lock); |
235 | } else { | 233 | } else |
236 | list_add_tail(&iocb->list, | 234 | lpfc_sli_release_iocbq(phba, iocb); |
237 | &phba->lpfc_iocb_list); | ||
238 | } | ||
239 | break; | 235 | break; |
240 | } | 236 | } |
241 | } | 237 | } |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c55ab1a630e5..51c6b677490c 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -56,6 +56,7 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) | |||
56 | struct ulp_bde64 *bpl; | 56 | struct ulp_bde64 *bpl; |
57 | IOCB_t *iocb; | 57 | IOCB_t *iocb; |
58 | dma_addr_t pdma_phys; | 58 | dma_addr_t pdma_phys; |
59 | uint16_t iotag; | ||
59 | 60 | ||
60 | psb = kmalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); | 61 | psb = kmalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); |
61 | if (!psb) | 62 | if (!psb) |
@@ -79,6 +80,15 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) | |||
79 | /* Initialize virtual ptrs to dma_buf region. */ | 80 | /* Initialize virtual ptrs to dma_buf region. */ |
80 | memset(psb->data, 0, phba->cfg_sg_dma_buf_size); | 81 | memset(psb->data, 0, phba->cfg_sg_dma_buf_size); |
81 | 82 | ||
83 | /* Allocate iotag for psb->cur_iocbq. */ | ||
84 | iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq); | ||
85 | if (iotag == 0) { | ||
86 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, | ||
87 | psb->data, psb->dma_handle); | ||
88 | kfree (psb); | ||
89 | return NULL; | ||
90 | } | ||
91 | |||
82 | psb->fcp_cmnd = psb->data; | 92 | psb->fcp_cmnd = psb->data; |
83 | psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd); | 93 | psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd); |
84 | psb->fcp_bpl = psb->data + sizeof(struct fcp_cmnd) + | 94 | psb->fcp_bpl = psb->data + sizeof(struct fcp_cmnd) + |
@@ -626,7 +636,6 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba) | |||
626 | list_remove_head(lpfc_iocb_list, iocbqrsp, struct lpfc_iocbq, list); | 636 | list_remove_head(lpfc_iocb_list, iocbqrsp, struct lpfc_iocbq, list); |
627 | if (!iocbqrsp) | 637 | if (!iocbqrsp) |
628 | return FAILED; | 638 | return FAILED; |
629 | memset(iocbqrsp, 0, sizeof (struct lpfc_iocbq)); | ||
630 | 639 | ||
631 | iocbq->iocb_flag |= LPFC_IO_POLL; | 640 | iocbq->iocb_flag |= LPFC_IO_POLL; |
632 | ret = lpfc_sli_issue_iocb_wait_high_priority(phba, | 641 | ret = lpfc_sli_issue_iocb_wait_high_priority(phba, |
@@ -655,8 +664,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba) | |||
655 | lpfc_cmd->pCmd->device->id, | 664 | lpfc_cmd->pCmd->device->id, |
656 | lpfc_cmd->pCmd->device->lun, 0, LPFC_CTX_TGT); | 665 | lpfc_cmd->pCmd->device->lun, 0, LPFC_CTX_TGT); |
657 | 666 | ||
658 | /* Return response IOCB to free list. */ | 667 | lpfc_sli_release_iocbq(phba, iocbqrsp); |
659 | list_add_tail(&iocbqrsp->list, lpfc_iocb_list); | ||
660 | return ret; | 668 | return ret; |
661 | } | 669 | } |
662 | 670 | ||
@@ -818,9 +826,8 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
818 | 826 | ||
819 | list_del_init(&iocb->list); | 827 | list_del_init(&iocb->list); |
820 | pring->txq_cnt--; | 828 | pring->txq_cnt--; |
821 | if (!iocb->iocb_cmpl) { | 829 | if (!iocb->iocb_cmpl) |
822 | list_add_tail(&iocb->list, lpfc_iocb_list); | 830 | lpfc_sli_release_iocbq(phba, iocb); |
823 | } | ||
824 | else { | 831 | else { |
825 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | 832 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; |
826 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | 833 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; |
@@ -834,8 +841,6 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
834 | if (abtsiocb == NULL) | 841 | if (abtsiocb == NULL) |
835 | return FAILED; | 842 | return FAILED; |
836 | 843 | ||
837 | memset(abtsiocb, 0, sizeof (struct lpfc_iocbq)); | ||
838 | |||
839 | /* | 844 | /* |
840 | * The scsi command was not in the txq. Check the txcmplq and if it is | 845 | * The scsi command was not in the txq. Check the txcmplq and if it is |
841 | * found, send an abort to the FW. | 846 | * found, send an abort to the FW. |
@@ -861,7 +866,7 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
861 | abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; | 866 | abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; |
862 | if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == | 867 | if (lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0) == |
863 | IOCB_ERROR) { | 868 | IOCB_ERROR) { |
864 | list_add_tail(&abtsiocb->list, lpfc_iocb_list); | 869 | lpfc_sli_release_iocbq(phba, abtsiocb); |
865 | ret = IOCB_ERROR; | 870 | ret = IOCB_ERROR; |
866 | break; | 871 | break; |
867 | } | 872 | } |
@@ -964,8 +969,6 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
964 | if (iocbqrsp == NULL) | 969 | if (iocbqrsp == NULL) |
965 | goto out_free_scsi_buf; | 970 | goto out_free_scsi_buf; |
966 | 971 | ||
967 | memset(iocbqrsp, 0, sizeof (struct lpfc_iocbq)); | ||
968 | |||
969 | iocbq->iocb_flag |= LPFC_IO_POLL; | 972 | iocbq->iocb_flag |= LPFC_IO_POLL; |
970 | iocbq->iocb_cmpl = lpfc_sli_wake_iocb_high_priority; | 973 | iocbq->iocb_cmpl = lpfc_sli_wake_iocb_high_priority; |
971 | 974 | ||
@@ -1011,7 +1014,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
1011 | phba->brd_no, cnt); | 1014 | phba->brd_no, cnt); |
1012 | } | 1015 | } |
1013 | 1016 | ||
1014 | list_add_tail(&iocbqrsp->list, lpfc_iocb_list); | 1017 | lpfc_sli_release_iocbq(phba, iocbqrsp); |
1015 | 1018 | ||
1016 | out_free_scsi_buf: | 1019 | out_free_scsi_buf: |
1017 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 1020 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 71ff2b6a642f..a8097e6c9dce 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -65,6 +65,18 @@ typedef enum _lpfc_iocb_type { | |||
65 | LPFC_ABORT_IOCB | 65 | LPFC_ABORT_IOCB |
66 | } lpfc_iocb_type; | 66 | } lpfc_iocb_type; |
67 | 67 | ||
68 | void | ||
69 | lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq) | ||
70 | { | ||
71 | size_t start_clean = (size_t)(&((struct lpfc_iocbq *)NULL)->iocb); | ||
72 | |||
73 | /* | ||
74 | * Clean all volatile data fields, preserve iotag and node struct. | ||
75 | */ | ||
76 | memset((char*)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean); | ||
77 | list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); | ||
78 | } | ||
79 | |||
68 | /* | 80 | /* |
69 | * Translate the iocb command to an iocb command type used to decide the final | 81 | * Translate the iocb command to an iocb command type used to decide the final |
70 | * disposition of each completed IOCB. | 82 | * disposition of each completed IOCB. |
@@ -265,41 +277,69 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
265 | return iocb; | 277 | return iocb; |
266 | } | 278 | } |
267 | 279 | ||
268 | static uint32_t | 280 | uint16_t |
269 | lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_sli_ring * pring) | 281 | lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq) |
270 | { | 282 | { |
271 | uint32_t search_start; | 283 | struct lpfc_iocbq ** new_arr; |
284 | struct lpfc_iocbq ** old_arr; | ||
285 | size_t new_len; | ||
286 | struct lpfc_sli *psli = &phba->sli; | ||
287 | uint16_t iotag; | ||
272 | 288 | ||
273 | if (pring->fast_lookup == NULL) { | 289 | spin_lock_irq(phba->host->host_lock); |
274 | pring->iotag_ctr++; | 290 | iotag = psli->last_iotag; |
275 | if (pring->iotag_ctr >= pring->iotag_max) | 291 | if(++iotag < psli->iocbq_lookup_len) { |
276 | pring->iotag_ctr = 1; | 292 | psli->last_iotag = iotag; |
277 | return pring->iotag_ctr; | 293 | psli->iocbq_lookup[iotag] = iocbq; |
294 | spin_unlock_irq(phba->host->host_lock); | ||
295 | iocbq->iotag = iotag; | ||
296 | return iotag; | ||
297 | } | ||
298 | else if (psli->iocbq_lookup_len < (0xffff | ||
299 | - LPFC_IOCBQ_LOOKUP_INCREMENT)) { | ||
300 | new_len = psli->iocbq_lookup_len + LPFC_IOCBQ_LOOKUP_INCREMENT; | ||
301 | spin_unlock_irq(phba->host->host_lock); | ||
302 | new_arr = kmalloc(new_len * sizeof (struct lpfc_iocbq *), | ||
303 | GFP_KERNEL); | ||
304 | if (new_arr) { | ||
305 | memset((char *)new_arr, 0, | ||
306 | new_len * sizeof (struct lpfc_iocbq *)); | ||
307 | spin_lock_irq(phba->host->host_lock); | ||
308 | old_arr = psli->iocbq_lookup; | ||
309 | if (new_len <= psli->iocbq_lookup_len) { | ||
310 | /* highly unprobable case */ | ||
311 | kfree(new_arr); | ||
312 | iotag = psli->last_iotag; | ||
313 | if(++iotag < psli->iocbq_lookup_len) { | ||
314 | psli->last_iotag = iotag; | ||
315 | psli->iocbq_lookup[iotag] = iocbq; | ||
316 | spin_unlock_irq(phba->host->host_lock); | ||
317 | iocbq->iotag = iotag; | ||
318 | return iotag; | ||
319 | } | ||
320 | spin_unlock_irq(phba->host->host_lock); | ||
321 | return 0; | ||
322 | } | ||
323 | if (psli->iocbq_lookup) | ||
324 | memcpy(new_arr, old_arr, | ||
325 | ((psli->last_iotag + 1) * | ||
326 | sizeof (struct lpfc_iocbq *))); | ||
327 | psli->iocbq_lookup = new_arr; | ||
328 | psli->iocbq_lookup_len = new_len; | ||
329 | psli->last_iotag = iotag; | ||
330 | psli->iocbq_lookup[iotag] = iocbq; | ||
331 | spin_unlock_irq(phba->host->host_lock); | ||
332 | iocbq->iotag = iotag; | ||
333 | kfree(old_arr); | ||
334 | return iotag; | ||
335 | } | ||
278 | } | 336 | } |
279 | 337 | ||
280 | search_start = pring->iotag_ctr; | 338 | lpfc_printf_log(phba, KERN_ERR,LOG_SLI, |
281 | 339 | "%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n", | |
282 | do { | 340 | phba->brd_no, psli->last_iotag); |
283 | pring->iotag_ctr++; | ||
284 | if (pring->iotag_ctr >= pring->fast_iotag) | ||
285 | pring->iotag_ctr = 1; | ||
286 | |||
287 | if (*(pring->fast_lookup + pring->iotag_ctr) == NULL) | ||
288 | return pring->iotag_ctr; | ||
289 | |||
290 | } while (pring->iotag_ctr != search_start); | ||
291 | 341 | ||
292 | /* | 342 | return 0; |
293 | * Outstanding I/O count for ring <ringno> is at max <fast_iotag> | ||
294 | */ | ||
295 | lpfc_printf_log(phba, | ||
296 | KERN_ERR, | ||
297 | LOG_SLI, | ||
298 | "%d:0318 Outstanding I/O count for ring %d is at max x%x\n", | ||
299 | phba->brd_no, | ||
300 | pring->ringno, | ||
301 | pring->fast_iotag); | ||
302 | return (0); | ||
303 | } | 343 | } |
304 | 344 | ||
305 | static void | 345 | static void |
@@ -307,10 +347,9 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
307 | IOCB_t *iocb, struct lpfc_iocbq *nextiocb) | 347 | IOCB_t *iocb, struct lpfc_iocbq *nextiocb) |
308 | { | 348 | { |
309 | /* | 349 | /* |
310 | * Allocate and set up an iotag | 350 | * Set up an iotag |
311 | */ | 351 | */ |
312 | nextiocb->iocb.ulpIoTag = | 352 | nextiocb->iocb.ulpIoTag = (nextiocb->iocb_cmpl) ? nextiocb->iotag : 0; |
313 | lpfc_sli_next_iotag(phba, &phba->sli.ring[phba->sli.fcp_ring]); | ||
314 | 353 | ||
315 | /* | 354 | /* |
316 | * Issue iocb command to adapter | 355 | * Issue iocb command to adapter |
@@ -326,9 +365,8 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
326 | */ | 365 | */ |
327 | if (nextiocb->iocb_cmpl) | 366 | if (nextiocb->iocb_cmpl) |
328 | lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb); | 367 | lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb); |
329 | else { | 368 | else |
330 | list_add_tail(&nextiocb->list, &phba->lpfc_iocb_list); | 369 | lpfc_sli_release_iocbq(phba, nextiocb); |
331 | } | ||
332 | 370 | ||
333 | /* | 371 | /* |
334 | * Let the HBA know what IOCB slot will be the next one the | 372 | * Let the HBA know what IOCB slot will be the next one the |
@@ -752,80 +790,28 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
752 | } | 790 | } |
753 | 791 | ||
754 | static struct lpfc_iocbq * | 792 | static struct lpfc_iocbq * |
755 | lpfc_sli_txcmpl_ring_search_slow(struct lpfc_sli_ring * pring, | 793 | lpfc_sli_iocbq_lookup(struct lpfc_hba * phba, |
756 | struct lpfc_iocbq * prspiocb) | 794 | struct lpfc_sli_ring * pring, |
795 | struct lpfc_iocbq * prspiocb) | ||
757 | { | 796 | { |
758 | IOCB_t *icmd = NULL; | ||
759 | IOCB_t *irsp = NULL; | ||
760 | struct lpfc_iocbq *cmd_iocb; | ||
761 | struct lpfc_iocbq *iocb, *next_iocb; | ||
762 | uint16_t iotag; | ||
763 | |||
764 | irsp = &prspiocb->iocb; | ||
765 | iotag = irsp->ulpIoTag; | ||
766 | cmd_iocb = NULL; | ||
767 | |||
768 | /* Search through txcmpl from the begining */ | ||
769 | list_for_each_entry_safe(iocb, next_iocb, &(pring->txcmplq), list) { | ||
770 | icmd = &iocb->iocb; | ||
771 | if (iotag == icmd->ulpIoTag) { | ||
772 | /* Found a match. */ | ||
773 | cmd_iocb = iocb; | ||
774 | list_del(&iocb->list); | ||
775 | pring->txcmplq_cnt--; | ||
776 | break; | ||
777 | } | ||
778 | } | ||
779 | |||
780 | return (cmd_iocb); | ||
781 | } | ||
782 | |||
783 | static struct lpfc_iocbq * | ||
784 | lpfc_sli_txcmpl_ring_iotag_lookup(struct lpfc_hba * phba, | ||
785 | struct lpfc_sli_ring * pring, | ||
786 | struct lpfc_iocbq * prspiocb) | ||
787 | { | ||
788 | IOCB_t *irsp = NULL; | ||
789 | struct lpfc_iocbq *cmd_iocb = NULL; | 797 | struct lpfc_iocbq *cmd_iocb = NULL; |
790 | uint16_t iotag; | 798 | uint16_t iotag; |
791 | 799 | ||
792 | if (unlikely(pring->fast_lookup == NULL)) | 800 | iotag = prspiocb->iocb.ulpIoTag; |
793 | return NULL; | 801 | |
794 | 802 | if (iotag != 0 && iotag <= phba->sli.last_iotag) { | |
795 | /* Use fast lookup based on iotag for completion */ | 803 | cmd_iocb = phba->sli.iocbq_lookup[iotag]; |
796 | irsp = &prspiocb->iocb; | 804 | list_del(&cmd_iocb->list); |
797 | iotag = irsp->ulpIoTag; | 805 | pring->txcmplq_cnt--; |
798 | if (iotag < pring->fast_iotag) { | 806 | return cmd_iocb; |
799 | cmd_iocb = *(pring->fast_lookup + iotag); | ||
800 | *(pring->fast_lookup + iotag) = NULL; | ||
801 | if (cmd_iocb) { | ||
802 | list_del(&cmd_iocb->list); | ||
803 | pring->txcmplq_cnt--; | ||
804 | return cmd_iocb; | ||
805 | } else { | ||
806 | /* | ||
807 | * This is clearly an error. A ring that uses iotags | ||
808 | * should never have a interrupt for a completion that | ||
809 | * is not on the ring. Return NULL and log a error. | ||
810 | */ | ||
811 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
812 | "%d:0327 Rsp ring %d error - command " | ||
813 | "completion for iotag x%x not found\n", | ||
814 | phba->brd_no, pring->ringno, iotag); | ||
815 | return NULL; | ||
816 | } | ||
817 | } | 807 | } |
818 | 808 | ||
819 | /* | ||
820 | * Rsp ring <ringno> get: iotag <iotag> greater then | ||
821 | * configured max <fast_iotag> wd0 <irsp>. This is an | ||
822 | * error. Just return NULL. | ||
823 | */ | ||
824 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 809 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
825 | "%d:0317 Rsp ring %d get: iotag x%x greater then " | 810 | "%d:0317 iotag x%x is out off " |
826 | "configured max x%x wd0 x%x\n", | 811 | "range: max iotag x%x wd0 x%x\n", |
827 | phba->brd_no, pring->ringno, iotag, pring->fast_iotag, | 812 | phba->brd_no, iotag, |
828 | *(((uint32_t *) irsp) + 7)); | 813 | phba->sli.last_iotag, |
814 | *(((uint32_t *) &prspiocb->iocb) + 7)); | ||
829 | return NULL; | 815 | return NULL; |
830 | } | 816 | } |
831 | 817 | ||
@@ -839,7 +825,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, | |||
839 | 825 | ||
840 | /* Based on the iotag field, get the cmd IOCB from the txcmplq */ | 826 | /* Based on the iotag field, get the cmd IOCB from the txcmplq */ |
841 | spin_lock_irqsave(phba->host->host_lock, iflag); | 827 | spin_lock_irqsave(phba->host->host_lock, iflag); |
842 | cmdiocbp = lpfc_sli_txcmpl_ring_search_slow(pring, saveq); | 828 | cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq); |
843 | if (cmdiocbp) { | 829 | if (cmdiocbp) { |
844 | if (cmdiocbp->iocb_cmpl) { | 830 | if (cmdiocbp->iocb_cmpl) { |
845 | /* | 831 | /* |
@@ -861,9 +847,8 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, | |||
861 | (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); | 847 | (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); |
862 | spin_lock_irqsave(phba->host->host_lock, iflag); | 848 | spin_lock_irqsave(phba->host->host_lock, iflag); |
863 | } | 849 | } |
864 | } else { | 850 | } else |
865 | list_add_tail(&cmdiocbp->list, &phba->lpfc_iocb_list); | 851 | lpfc_sli_release_iocbq(phba, cmdiocbp); |
866 | } | ||
867 | } else { | 852 | } else { |
868 | /* | 853 | /* |
869 | * Unknown initiating command based on the response iotag. | 854 | * Unknown initiating command based on the response iotag. |
@@ -990,9 +975,8 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, | |||
990 | break; | 975 | break; |
991 | } | 976 | } |
992 | 977 | ||
993 | cmdiocbq = lpfc_sli_txcmpl_ring_iotag_lookup(phba, | 978 | cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring, |
994 | pring, | 979 | &rspiocbq); |
995 | &rspiocbq); | ||
996 | if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) { | 980 | if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) { |
997 | spin_unlock_irqrestore( | 981 | spin_unlock_irqrestore( |
998 | phba->host->host_lock, iflag); | 982 | phba->host->host_lock, iflag); |
@@ -1213,8 +1197,8 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, | |||
1213 | } else if (type == LPFC_ABORT_IOCB) { | 1197 | } else if (type == LPFC_ABORT_IOCB) { |
1214 | if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) && | 1198 | if ((irsp->ulpCommand != CMD_XRI_ABORTED_CX) && |
1215 | ((cmdiocbp = | 1199 | ((cmdiocbp = |
1216 | lpfc_sli_txcmpl_ring_search_slow(pring, | 1200 | lpfc_sli_iocbq_lookup(phba, pring, |
1217 | saveq)))) { | 1201 | saveq)))) { |
1218 | /* Call the specified completion | 1202 | /* Call the specified completion |
1219 | routine */ | 1203 | routine */ |
1220 | if (cmdiocbp->iocb_cmpl) { | 1204 | if (cmdiocbp->iocb_cmpl) { |
@@ -1226,10 +1210,9 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, | |||
1226 | spin_lock_irqsave( | 1210 | spin_lock_irqsave( |
1227 | phba->host->host_lock, | 1211 | phba->host->host_lock, |
1228 | iflag); | 1212 | iflag); |
1229 | } else { | 1213 | } else |
1230 | list_add_tail(&cmdiocbp->list, | 1214 | lpfc_sli_release_iocbq(phba, |
1231 | lpfc_iocb_list); | 1215 | cmdiocbp); |
1232 | } | ||
1233 | } | 1216 | } |
1234 | } else if (type == LPFC_UNKNOWN_IOCB) { | 1217 | } else if (type == LPFC_UNKNOWN_IOCB) { |
1235 | if (irsp->ulpCommand == CMD_ADAPTER_MSG) { | 1218 | if (irsp->ulpCommand == CMD_ADAPTER_MSG) { |
@@ -1264,12 +1247,12 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, | |||
1264 | next_iocb, | 1247 | next_iocb, |
1265 | &saveq->list, | 1248 | &saveq->list, |
1266 | list) { | 1249 | list) { |
1267 | list_add_tail(&rspiocbp->list, | 1250 | lpfc_sli_release_iocbq(phba, |
1268 | lpfc_iocb_list); | 1251 | rspiocbp); |
1269 | } | 1252 | } |
1270 | } | 1253 | } |
1271 | 1254 | ||
1272 | list_add_tail(&saveq->list, lpfc_iocb_list); | 1255 | lpfc_sli_release_iocbq(phba, saveq); |
1273 | } | 1256 | } |
1274 | } | 1257 | } |
1275 | 1258 | ||
@@ -1314,7 +1297,6 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
1314 | struct lpfc_iocbq *iocb, *next_iocb; | 1297 | struct lpfc_iocbq *iocb, *next_iocb; |
1315 | IOCB_t *icmd = NULL, *cmd = NULL; | 1298 | IOCB_t *icmd = NULL, *cmd = NULL; |
1316 | int errcnt; | 1299 | int errcnt; |
1317 | uint16_t iotag; | ||
1318 | 1300 | ||
1319 | errcnt = 0; | 1301 | errcnt = 0; |
1320 | 1302 | ||
@@ -1331,9 +1313,8 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
1331 | spin_unlock_irq(phba->host->host_lock); | 1313 | spin_unlock_irq(phba->host->host_lock); |
1332 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 1314 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
1333 | spin_lock_irq(phba->host->host_lock); | 1315 | spin_lock_irq(phba->host->host_lock); |
1334 | } else { | 1316 | } else |
1335 | list_add_tail(&iocb->list, &phba->lpfc_iocb_list); | 1317 | lpfc_sli_release_iocbq(phba, iocb); |
1336 | } | ||
1337 | } | 1318 | } |
1338 | pring->txq_cnt = 0; | 1319 | pring->txq_cnt = 0; |
1339 | INIT_LIST_HEAD(&(pring->txq)); | 1320 | INIT_LIST_HEAD(&(pring->txq)); |
@@ -1343,13 +1324,8 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
1343 | cmd = &iocb->iocb; | 1324 | cmd = &iocb->iocb; |
1344 | 1325 | ||
1345 | /* | 1326 | /* |
1346 | * Imediate abort of IOCB, clear fast_lookup entry, | 1327 | * Imediate abort of IOCB, deque and call compl |
1347 | * if any, deque and call compl | ||
1348 | */ | 1328 | */ |
1349 | iotag = cmd->ulpIoTag; | ||
1350 | if (iotag && pring->fast_lookup && | ||
1351 | (iotag < pring->fast_iotag)) | ||
1352 | pring->fast_lookup[iotag] = NULL; | ||
1353 | 1329 | ||
1354 | list_del_init(&iocb->list); | 1330 | list_del_init(&iocb->list); |
1355 | pring->txcmplq_cnt--; | 1331 | pring->txcmplq_cnt--; |
@@ -1360,9 +1336,8 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
1360 | spin_unlock_irq(phba->host->host_lock); | 1336 | spin_unlock_irq(phba->host->host_lock); |
1361 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 1337 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
1362 | spin_lock_irq(phba->host->host_lock); | 1338 | spin_lock_irq(phba->host->host_lock); |
1363 | } else { | 1339 | } else |
1364 | list_add_tail(&iocb->list, &phba->lpfc_iocb_list); | 1340 | lpfc_sli_release_iocbq(phba, iocb); |
1365 | } | ||
1366 | } | 1341 | } |
1367 | 1342 | ||
1368 | INIT_LIST_HEAD(&pring->txcmplq); | 1343 | INIT_LIST_HEAD(&pring->txcmplq); |
@@ -2147,6 +2122,10 @@ lpfc_sli_setup(struct lpfc_hba *phba) | |||
2147 | psli->next_ring = LPFC_FCP_NEXT_RING; | 2122 | psli->next_ring = LPFC_FCP_NEXT_RING; |
2148 | psli->ip_ring = LPFC_IP_RING; | 2123 | psli->ip_ring = LPFC_IP_RING; |
2149 | 2124 | ||
2125 | psli->iocbq_lookup = NULL; | ||
2126 | psli->iocbq_lookup_len = 0; | ||
2127 | psli->last_iotag = 0; | ||
2128 | |||
2150 | for (i = 0; i < psli->num_rings; i++) { | 2129 | for (i = 0; i < psli->num_rings; i++) { |
2151 | pring = &psli->ring[i]; | 2130 | pring = &psli->ring[i]; |
2152 | switch (i) { | 2131 | switch (i) { |
@@ -2222,7 +2201,7 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba) | |||
2222 | { | 2201 | { |
2223 | struct lpfc_sli *psli; | 2202 | struct lpfc_sli *psli; |
2224 | struct lpfc_sli_ring *pring; | 2203 | struct lpfc_sli_ring *pring; |
2225 | int i, cnt; | 2204 | int i; |
2226 | 2205 | ||
2227 | psli = &phba->sli; | 2206 | psli = &phba->sli; |
2228 | spin_lock_irq(phba->host->host_lock); | 2207 | spin_lock_irq(phba->host->host_lock); |
@@ -2238,19 +2217,6 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba) | |||
2238 | INIT_LIST_HEAD(&pring->txcmplq); | 2217 | INIT_LIST_HEAD(&pring->txcmplq); |
2239 | INIT_LIST_HEAD(&pring->iocb_continueq); | 2218 | INIT_LIST_HEAD(&pring->iocb_continueq); |
2240 | INIT_LIST_HEAD(&pring->postbufq); | 2219 | INIT_LIST_HEAD(&pring->postbufq); |
2241 | cnt = pring->fast_iotag; | ||
2242 | spin_unlock_irq(phba->host->host_lock); | ||
2243 | if (cnt) { | ||
2244 | pring->fast_lookup = | ||
2245 | kmalloc(cnt * sizeof (struct lpfc_iocbq *), | ||
2246 | GFP_KERNEL); | ||
2247 | if (pring->fast_lookup == 0) { | ||
2248 | return (0); | ||
2249 | } | ||
2250 | memset((char *)pring->fast_lookup, 0, | ||
2251 | cnt * sizeof (struct lpfc_iocbq *)); | ||
2252 | } | ||
2253 | spin_lock_irq(phba->host->host_lock); | ||
2254 | } | 2220 | } |
2255 | spin_unlock_irq(phba->host->host_lock); | 2221 | spin_unlock_irq(phba->host->host_lock); |
2256 | return (1); | 2222 | return (1); |
@@ -2292,10 +2258,8 @@ lpfc_sli_hba_down(struct lpfc_hba * phba) | |||
2292 | flags); | 2258 | flags); |
2293 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 2259 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
2294 | spin_lock_irqsave(phba->host->host_lock, flags); | 2260 | spin_lock_irqsave(phba->host->host_lock, flags); |
2295 | } else { | 2261 | } else |
2296 | list_add_tail(&iocb->list, | 2262 | lpfc_sli_release_iocbq(phba, iocb); |
2297 | &phba->lpfc_iocb_list); | ||
2298 | } | ||
2299 | } | 2263 | } |
2300 | 2264 | ||
2301 | INIT_LIST_HEAD(&(pring->txq)); | 2265 | INIT_LIST_HEAD(&(pring->txq)); |
@@ -2436,7 +2400,7 @@ lpfc_sli_abort_elsreq_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
2436 | kfree(buf_ptr); | 2400 | kfree(buf_ptr); |
2437 | } | 2401 | } |
2438 | 2402 | ||
2439 | list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list); | 2403 | lpfc_sli_release_iocbq(phba, cmdiocb); |
2440 | return; | 2404 | return; |
2441 | } | 2405 | } |
2442 | 2406 | ||
@@ -2454,7 +2418,6 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba, | |||
2454 | list_remove_head(lpfc_iocb_list, abtsiocbp, struct lpfc_iocbq, list); | 2418 | list_remove_head(lpfc_iocb_list, abtsiocbp, struct lpfc_iocbq, list); |
2455 | if (abtsiocbp == NULL) | 2419 | if (abtsiocbp == NULL) |
2456 | return 0; | 2420 | return 0; |
2457 | memset(abtsiocbp, 0, sizeof (struct lpfc_iocbq)); | ||
2458 | 2421 | ||
2459 | iabt = &abtsiocbp->iocb; | 2422 | iabt = &abtsiocbp->iocb; |
2460 | icmd = &cmdiocb->iocb; | 2423 | icmd = &cmdiocb->iocb; |
@@ -2473,7 +2436,7 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba, | |||
2473 | abtsiocbp->iocb_cmpl = lpfc_sli_abort_elsreq_cmpl; | 2436 | abtsiocbp->iocb_cmpl = lpfc_sli_abort_elsreq_cmpl; |
2474 | break; | 2437 | break; |
2475 | default: | 2438 | default: |
2476 | list_add_tail(&abtsiocbp->list, lpfc_iocb_list); | 2439 | lpfc_sli_release_iocbq(phba, abtsiocbp); |
2477 | return 0; | 2440 | return 0; |
2478 | } | 2441 | } |
2479 | 2442 | ||
@@ -2485,7 +2448,7 @@ lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba, | |||
2485 | iabt->ulpCommand = CMD_ABORT_MXRI64_CN; | 2448 | iabt->ulpCommand = CMD_ABORT_MXRI64_CN; |
2486 | 2449 | ||
2487 | if (lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0) == IOCB_ERROR) { | 2450 | if (lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0) == IOCB_ERROR) { |
2488 | list_add_tail(&abtsiocbp->list, lpfc_iocb_list); | 2451 | lpfc_sli_release_iocbq(phba, abtsiocbp); |
2489 | return 0; | 2452 | return 0; |
2490 | } | 2453 | } |
2491 | 2454 | ||
@@ -2563,7 +2526,7 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
2563 | struct lpfc_iocbq * rspiocb) | 2526 | struct lpfc_iocbq * rspiocb) |
2564 | { | 2527 | { |
2565 | spin_lock_irq(phba->host->host_lock); | 2528 | spin_lock_irq(phba->host->host_lock); |
2566 | list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list); | 2529 | lpfc_sli_release_iocbq(phba, cmdiocb); |
2567 | spin_unlock_irq(phba->host->host_lock); | 2530 | spin_unlock_irq(phba->host->host_lock); |
2568 | return; | 2531 | return; |
2569 | } | 2532 | } |
@@ -2604,7 +2567,6 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
2604 | errcnt++; | 2567 | errcnt++; |
2605 | continue; | 2568 | continue; |
2606 | } | 2569 | } |
2607 | memset(abtsiocb, 0, sizeof (struct lpfc_iocbq)); | ||
2608 | 2570 | ||
2609 | abtsiocb->iocb.un.acxri.abortType = ABORT_TYPE_ABTS; | 2571 | abtsiocb->iocb.un.acxri.abortType = ABORT_TYPE_ABTS; |
2610 | abtsiocb->iocb.un.acxri.abortContextTag = cmd->ulpContext; | 2572 | abtsiocb->iocb.un.acxri.abortContextTag = cmd->ulpContext; |
@@ -2621,7 +2583,7 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
2621 | abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; | 2583 | abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; |
2622 | ret_val = lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0); | 2584 | ret_val = lpfc_sli_issue_iocb(phba, pring, abtsiocb, 0); |
2623 | if (ret_val == IOCB_ERROR) { | 2585 | if (ret_val == IOCB_ERROR) { |
2624 | list_add_tail(&abtsiocb->list, lpfc_iocb_list); | 2586 | lpfc_sli_release_iocbq(phba, abtsiocb); |
2625 | errcnt++; | 2587 | errcnt++; |
2626 | continue; | 2588 | continue; |
2627 | } | 2589 | } |
@@ -2635,8 +2597,9 @@ lpfc_sli_wake_iocb_high_priority(struct lpfc_hba * phba, | |||
2635 | struct lpfc_iocbq * queue1, | 2597 | struct lpfc_iocbq * queue1, |
2636 | struct lpfc_iocbq * queue2) | 2598 | struct lpfc_iocbq * queue2) |
2637 | { | 2599 | { |
2638 | if (queue1->context2 && queue2) | 2600 | struct lpfc_iocbq *save_iocbq = queue1->context2; |
2639 | memcpy(queue1->context2, queue2, sizeof (struct lpfc_iocbq)); | 2601 | if (save_iocbq && queue2) |
2602 | memcpy(&save_iocbq->iocb, &queue2->iocb, sizeof(queue2->iocb)); | ||
2640 | 2603 | ||
2641 | /* The waiter is looking for LPFC_IO_HIPRI bit to be set | 2604 | /* The waiter is looking for LPFC_IO_HIPRI bit to be set |
2642 | as a signal to wake up */ | 2605 | as a signal to wake up */ |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 2d5b0670415c..5d8911de4faa 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -33,6 +33,9 @@ typedef enum _lpfc_ctx_cmd { | |||
33 | struct lpfc_iocbq { | 33 | struct lpfc_iocbq { |
34 | /* lpfc_iocbqs are used in double linked lists */ | 34 | /* lpfc_iocbqs are used in double linked lists */ |
35 | struct list_head list; | 35 | struct list_head list; |
36 | uint16_t iotag; /* pre-assigned IO tag */ | ||
37 | uint16_t rsvd1; | ||
38 | |||
36 | IOCB_t iocb; /* IOCB cmd */ | 39 | IOCB_t iocb; /* IOCB cmd */ |
37 | uint8_t retry; /* retry counter for IOCB cmd - if needed */ | 40 | uint8_t retry; /* retry counter for IOCB cmd - if needed */ |
38 | uint8_t iocb_flag; | 41 | uint8_t iocb_flag; |
@@ -200,6 +203,11 @@ struct lpfc_sli { | |||
200 | cmd */ | 203 | cmd */ |
201 | 204 | ||
202 | uint32_t *MBhostaddr; /* virtual address for mbox cmds */ | 205 | uint32_t *MBhostaddr; /* virtual address for mbox cmds */ |
206 | |||
207 | #define LPFC_IOCBQ_LOOKUP_INCREMENT 1024 | ||
208 | struct lpfc_iocbq ** iocbq_lookup; /* array to lookup IOCB by IOTAG */ | ||
209 | size_t iocbq_lookup_len; /* current lengs of the array */ | ||
210 | uint16_t last_iotag; /* last allocated IOTAG */ | ||
203 | }; | 211 | }; |
204 | 212 | ||
205 | /* Given a pointer to the start of the ring, and the slot number of | 213 | /* Given a pointer to the start of the ring, and the slot number of |