diff options
Diffstat (limited to 'drivers/scsi')
| -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 |
