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/scsi/lpfc/lpfc_sli.c | |
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/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 281 |
1 files changed, 122 insertions, 159 deletions
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 */ |