diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-02-08 18:50:25 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-11 18:52:58 -0500 |
commit | 3163f725a5d071eea1830bbbfab78cfe3fc9baaf (patch) | |
tree | c9c7904bcfade4e1ea45c3a6e47fbd83e77d348e /drivers/scsi | |
parent | 7f5f3d0d02aa2f124e764aee5c775589ce72fd42 (diff) |
[SCSI] lpfc 8.2.5 : Fix buffer leaks
Fix buffer leaks:
- HBQ dma buffer leak at dma_pool_destroy when unloading driver
- Fix missing buffer free in slow ring buffer handling
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 17 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 17 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mem.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 97 |
6 files changed, 137 insertions, 7 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 6c178f1c8786..2ab2d24dcc15 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -495,6 +495,8 @@ struct lpfc_hba { | |||
495 | wait_queue_head_t *work_wait; | 495 | wait_queue_head_t *work_wait; |
496 | struct task_struct *worker_thread; | 496 | struct task_struct *worker_thread; |
497 | 497 | ||
498 | uint32_t hbq_in_use; /* HBQs in use flag */ | ||
499 | struct list_head hbqbuf_in_list; /* in-fly hbq buffer list */ | ||
498 | uint32_t hbq_count; /* Count of configured HBQs */ | 500 | uint32_t hbq_count; /* Count of configured HBQs */ |
499 | struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */ | 501 | struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */ |
500 | 502 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 25892671bfb0..bd572d6b60af 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -629,9 +629,8 @@ lpfc_linkdown(struct lpfc_hba *phba) | |||
629 | LPFC_MBOXQ_t *mb; | 629 | LPFC_MBOXQ_t *mb; |
630 | int i; | 630 | int i; |
631 | 631 | ||
632 | if (phba->link_state == LPFC_LINK_DOWN) { | 632 | if (phba->link_state == LPFC_LINK_DOWN) |
633 | return 0; | 633 | return 0; |
634 | } | ||
635 | spin_lock_irq(&phba->hbalock); | 634 | spin_lock_irq(&phba->hbalock); |
636 | if (phba->link_state > LPFC_LINK_DOWN) { | 635 | if (phba->link_state > LPFC_LINK_DOWN) { |
637 | phba->link_state = LPFC_LINK_DOWN; | 636 | phba->link_state = LPFC_LINK_DOWN; |
@@ -1122,7 +1121,7 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1122 | if (la->attType == AT_LINK_UP) { | 1121 | if (la->attType == AT_LINK_UP) { |
1123 | phba->fc_stat.LinkUp++; | 1122 | phba->fc_stat.LinkUp++; |
1124 | if (phba->link_flag & LS_LOOPBACK_MODE) { | 1123 | if (phba->link_flag & LS_LOOPBACK_MODE) { |
1125 | lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, | 1124 | lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, |
1126 | "1306 Link Up Event in loop back mode " | 1125 | "1306 Link Up Event in loop back mode " |
1127 | "x%x received Data: x%x x%x x%x x%x\n", | 1126 | "x%x received Data: x%x x%x x%x x%x\n", |
1128 | la->eventTag, phba->fc_eventTag, | 1127 | la->eventTag, phba->fc_eventTag, |
@@ -1139,11 +1138,21 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1139 | lpfc_mbx_process_link_up(phba, la); | 1138 | lpfc_mbx_process_link_up(phba, la); |
1140 | } else { | 1139 | } else { |
1141 | phba->fc_stat.LinkDown++; | 1140 | phba->fc_stat.LinkDown++; |
1142 | lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, | 1141 | if (phba->link_flag & LS_LOOPBACK_MODE) { |
1142 | lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, | ||
1143 | "1308 Link Down Event in loop back mode " | ||
1144 | "x%x received " | ||
1145 | "Data: x%x x%x x%x\n", | ||
1146 | la->eventTag, phba->fc_eventTag, | ||
1147 | phba->pport->port_state, vport->fc_flag); | ||
1148 | } | ||
1149 | else { | ||
1150 | lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, | ||
1143 | "1305 Link Down Event x%x received " | 1151 | "1305 Link Down Event x%x received " |
1144 | "Data: x%x x%x x%x\n", | 1152 | "Data: x%x x%x x%x\n", |
1145 | la->eventTag, phba->fc_eventTag, | 1153 | la->eventTag, phba->fc_eventTag, |
1146 | phba->pport->port_state, vport->fc_flag); | 1154 | phba->pport->port_state, vport->fc_flag); |
1155 | } | ||
1147 | lpfc_mbx_issue_link_down(phba); | 1156 | lpfc_mbx_issue_link_down(phba); |
1148 | } | 1157 | } |
1149 | 1158 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 543ed3ca8b76..7773b949aa7c 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2007 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2008 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -1377,11 +1377,26 @@ typedef struct { /* FireFly BIU registers */ | |||
1377 | #define CMD_QUE_XRI64_CX 0xB3 | 1377 | #define CMD_QUE_XRI64_CX 0xB3 |
1378 | #define CMD_IOCB_RCV_SEQ64_CX 0xB5 | 1378 | #define CMD_IOCB_RCV_SEQ64_CX 0xB5 |
1379 | #define CMD_IOCB_RCV_ELS64_CX 0xB7 | 1379 | #define CMD_IOCB_RCV_ELS64_CX 0xB7 |
1380 | #define CMD_IOCB_RET_XRI64_CX 0xB9 | ||
1380 | #define CMD_IOCB_RCV_CONT64_CX 0xBB | 1381 | #define CMD_IOCB_RCV_CONT64_CX 0xBB |
1381 | 1382 | ||
1382 | #define CMD_GEN_REQUEST64_CR 0xC2 | 1383 | #define CMD_GEN_REQUEST64_CR 0xC2 |
1383 | #define CMD_GEN_REQUEST64_CX 0xC3 | 1384 | #define CMD_GEN_REQUEST64_CX 0xC3 |
1384 | 1385 | ||
1386 | /* Unhandled SLI-3 Commands */ | ||
1387 | #define CMD_IOCB_XMIT_MSEQ64_CR 0xB0 | ||
1388 | #define CMD_IOCB_XMIT_MSEQ64_CX 0xB1 | ||
1389 | #define CMD_IOCB_RCV_SEQ_LIST64_CX 0xC1 | ||
1390 | #define CMD_IOCB_RCV_ELS_LIST64_CX 0xCD | ||
1391 | #define CMD_IOCB_CLOSE_EXTENDED_CN 0xB6 | ||
1392 | #define CMD_IOCB_ABORT_EXTENDED_CN 0xBA | ||
1393 | #define CMD_IOCB_RET_HBQE64_CN 0xCA | ||
1394 | #define CMD_IOCB_FCP_IBIDIR64_CR 0xAC | ||
1395 | #define CMD_IOCB_FCP_IBIDIR64_CX 0xAD | ||
1396 | #define CMD_IOCB_FCP_ITASKMGT64_CX 0xAF | ||
1397 | #define CMD_IOCB_LOGENTRY_CN 0x94 | ||
1398 | #define CMD_IOCB_LOGENTRY_ASYNC_CN 0x96 | ||
1399 | |||
1385 | #define CMD_MAX_IOCB_CMD 0xE6 | 1400 | #define CMD_MAX_IOCB_CMD 0xE6 |
1386 | #define CMD_IOCB_MASK 0xff | 1401 | #define CMD_IOCB_MASK 0xff |
1387 | 1402 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7a5ce3355808..22843751c2ca 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -2087,6 +2087,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2087 | 2087 | ||
2088 | memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size()); | 2088 | memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size()); |
2089 | 2089 | ||
2090 | INIT_LIST_HEAD(&phba->hbqbuf_in_list); | ||
2091 | |||
2090 | /* Initialize the SLI Layer to run with lpfc HBAs. */ | 2092 | /* Initialize the SLI Layer to run with lpfc HBAs. */ |
2091 | lpfc_sli_setup(phba); | 2093 | lpfc_sli_setup(phba); |
2092 | lpfc_sli_queue_setup(phba); | 2094 | lpfc_sli_queue_setup(phba); |
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 27448c98c07a..3c0cebc71800 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
@@ -264,18 +264,27 @@ void | |||
264 | lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) | 264 | lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) |
265 | { | 265 | { |
266 | struct hbq_dmabuf *hbq_entry; | 266 | struct hbq_dmabuf *hbq_entry; |
267 | unsigned long flags; | ||
267 | 268 | ||
268 | if (!mp) | 269 | if (!mp) |
269 | return; | 270 | return; |
270 | 271 | ||
271 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { | 272 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { |
273 | /* Check whether HBQ is still in use */ | ||
274 | spin_lock_irqsave(&phba->hbalock, flags); | ||
275 | if (!phba->hbq_in_use) { | ||
276 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
277 | return; | ||
278 | } | ||
272 | hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); | 279 | hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); |
280 | list_del(&hbq_entry->dbuf.list); | ||
273 | if (hbq_entry->tag == -1) { | 281 | if (hbq_entry->tag == -1) { |
274 | (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer) | 282 | (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer) |
275 | (phba, hbq_entry); | 283 | (phba, hbq_entry); |
276 | } else { | 284 | } else { |
277 | lpfc_sli_free_hbq(phba, hbq_entry); | 285 | lpfc_sli_free_hbq(phba, hbq_entry); |
278 | } | 286 | } |
287 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
279 | } else { | 288 | } else { |
280 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 289 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
281 | kfree(mp); | 290 | kfree(mp); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c8c5b48baa66..f53206411cd8 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -203,8 +203,25 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) | |||
203 | case CMD_IOCB_RCV_SEQ64_CX: | 203 | case CMD_IOCB_RCV_SEQ64_CX: |
204 | case CMD_IOCB_RCV_ELS64_CX: | 204 | case CMD_IOCB_RCV_ELS64_CX: |
205 | case CMD_IOCB_RCV_CONT64_CX: | 205 | case CMD_IOCB_RCV_CONT64_CX: |
206 | case CMD_IOCB_RET_XRI64_CX: | ||
206 | type = LPFC_UNSOL_IOCB; | 207 | type = LPFC_UNSOL_IOCB; |
207 | break; | 208 | break; |
209 | case CMD_IOCB_XMIT_MSEQ64_CR: | ||
210 | case CMD_IOCB_XMIT_MSEQ64_CX: | ||
211 | case CMD_IOCB_RCV_SEQ_LIST64_CX: | ||
212 | case CMD_IOCB_RCV_ELS_LIST64_CX: | ||
213 | case CMD_IOCB_CLOSE_EXTENDED_CN: | ||
214 | case CMD_IOCB_ABORT_EXTENDED_CN: | ||
215 | case CMD_IOCB_RET_HBQE64_CN: | ||
216 | case CMD_IOCB_FCP_IBIDIR64_CR: | ||
217 | case CMD_IOCB_FCP_IBIDIR64_CX: | ||
218 | case CMD_IOCB_FCP_ITASKMGT64_CX: | ||
219 | case CMD_IOCB_LOGENTRY_CN: | ||
220 | case CMD_IOCB_LOGENTRY_ASYNC_CN: | ||
221 | printk("%s - Unhandled SLI-3 Command x%x\n", | ||
222 | __FUNCTION__, iocb_cmnd); | ||
223 | type = LPFC_UNKNOWN_IOCB; | ||
224 | break; | ||
208 | default: | 225 | default: |
209 | type = LPFC_UNKNOWN_IOCB; | 226 | type = LPFC_UNKNOWN_IOCB; |
210 | break; | 227 | break; |
@@ -529,10 +546,13 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) | |||
529 | { | 546 | { |
530 | struct lpfc_dmabuf *dmabuf, *next_dmabuf; | 547 | struct lpfc_dmabuf *dmabuf, *next_dmabuf; |
531 | struct hbq_dmabuf *hbq_buf; | 548 | struct hbq_dmabuf *hbq_buf; |
549 | unsigned long flags; | ||
532 | int i, hbq_count; | 550 | int i, hbq_count; |
551 | uint32_t hbqno; | ||
533 | 552 | ||
534 | hbq_count = lpfc_sli_hbq_count(); | 553 | hbq_count = lpfc_sli_hbq_count(); |
535 | /* Return all memory used by all HBQs */ | 554 | /* Return all memory used by all HBQs */ |
555 | spin_lock_irqsave(&phba->hbalock, flags); | ||
536 | for (i = 0; i < hbq_count; ++i) { | 556 | for (i = 0; i < hbq_count; ++i) { |
537 | list_for_each_entry_safe(dmabuf, next_dmabuf, | 557 | list_for_each_entry_safe(dmabuf, next_dmabuf, |
538 | &phba->hbqs[i].hbq_buffer_list, list) { | 558 | &phba->hbqs[i].hbq_buffer_list, list) { |
@@ -542,6 +562,28 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) | |||
542 | } | 562 | } |
543 | phba->hbqs[i].buffer_count = 0; | 563 | phba->hbqs[i].buffer_count = 0; |
544 | } | 564 | } |
565 | /* Return all HBQ buffer that are in-fly */ | ||
566 | list_for_each_entry_safe(dmabuf, next_dmabuf, | ||
567 | &phba->hbqbuf_in_list, list) { | ||
568 | hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf); | ||
569 | list_del(&hbq_buf->dbuf.list); | ||
570 | if (hbq_buf->tag == -1) { | ||
571 | (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer) | ||
572 | (phba, hbq_buf); | ||
573 | } else { | ||
574 | hbqno = hbq_buf->tag >> 16; | ||
575 | if (hbqno >= LPFC_MAX_HBQS) | ||
576 | (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer) | ||
577 | (phba, hbq_buf); | ||
578 | else | ||
579 | (phba->hbqs[hbqno].hbq_free_buffer)(phba, | ||
580 | hbq_buf); | ||
581 | } | ||
582 | } | ||
583 | |||
584 | /* Mark the HBQs not in use */ | ||
585 | phba->hbq_in_use = 0; | ||
586 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
545 | } | 587 | } |
546 | 588 | ||
547 | static struct lpfc_hbq_entry * | 589 | static struct lpfc_hbq_entry * |
@@ -603,6 +645,7 @@ static int | |||
603 | lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) | 645 | lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) |
604 | { | 646 | { |
605 | uint32_t i, start, end; | 647 | uint32_t i, start, end; |
648 | unsigned long flags; | ||
606 | struct hbq_dmabuf *hbq_buffer; | 649 | struct hbq_dmabuf *hbq_buffer; |
607 | 650 | ||
608 | if (!phba->hbqs[hbqno].hbq_alloc_buffer) { | 651 | if (!phba->hbqs[hbqno].hbq_alloc_buffer) { |
@@ -615,6 +658,13 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) | |||
615 | end = lpfc_hbq_defs[hbqno]->entry_count; | 658 | end = lpfc_hbq_defs[hbqno]->entry_count; |
616 | } | 659 | } |
617 | 660 | ||
661 | /* Check whether HBQ is still in use */ | ||
662 | spin_lock_irqsave(&phba->hbalock, flags); | ||
663 | if (!phba->hbq_in_use) { | ||
664 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
665 | return 0; | ||
666 | } | ||
667 | |||
618 | /* Populate HBQ entries */ | 668 | /* Populate HBQ entries */ |
619 | for (i = start; i < end; i++) { | 669 | for (i = start; i < end; i++) { |
620 | hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba); | 670 | hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba); |
@@ -626,6 +676,8 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) | |||
626 | else | 676 | else |
627 | (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer); | 677 | (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer); |
628 | } | 678 | } |
679 | |||
680 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
629 | return 0; | 681 | return 0; |
630 | } | 682 | } |
631 | 683 | ||
@@ -910,16 +962,29 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) | |||
910 | uint32_t hbqno; | 962 | uint32_t hbqno; |
911 | void *virt; /* virtual address ptr */ | 963 | void *virt; /* virtual address ptr */ |
912 | dma_addr_t phys; /* mapped address */ | 964 | dma_addr_t phys; /* mapped address */ |
965 | unsigned long flags; | ||
966 | |||
967 | /* Check whether HBQ is still in use */ | ||
968 | spin_lock_irqsave(&phba->hbalock, flags); | ||
969 | if (!phba->hbq_in_use) { | ||
970 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
971 | return NULL; | ||
972 | } | ||
913 | 973 | ||
914 | hbq_entry = lpfc_sli_hbqbuf_find(phba, tag); | 974 | hbq_entry = lpfc_sli_hbqbuf_find(phba, tag); |
915 | if (hbq_entry == NULL) | 975 | if (hbq_entry == NULL) { |
976 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
916 | return NULL; | 977 | return NULL; |
978 | } | ||
917 | list_del(&hbq_entry->dbuf.list); | 979 | list_del(&hbq_entry->dbuf.list); |
918 | 980 | ||
919 | hbqno = tag >> 16; | 981 | hbqno = tag >> 16; |
920 | new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba); | 982 | new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba); |
921 | if (new_hbq_entry == NULL) | 983 | if (new_hbq_entry == NULL) { |
984 | list_add_tail(&hbq_entry->dbuf.list, &phba->hbqbuf_in_list); | ||
985 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
922 | return &hbq_entry->dbuf; | 986 | return &hbq_entry->dbuf; |
987 | } | ||
923 | new_hbq_entry->tag = -1; | 988 | new_hbq_entry->tag = -1; |
924 | phys = new_hbq_entry->dbuf.phys; | 989 | phys = new_hbq_entry->dbuf.phys; |
925 | virt = new_hbq_entry->dbuf.virt; | 990 | virt = new_hbq_entry->dbuf.virt; |
@@ -928,6 +993,9 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) | |||
928 | hbq_entry->dbuf.phys = phys; | 993 | hbq_entry->dbuf.phys = phys; |
929 | hbq_entry->dbuf.virt = virt; | 994 | hbq_entry->dbuf.virt = virt; |
930 | lpfc_sli_free_hbq(phba, hbq_entry); | 995 | lpfc_sli_free_hbq(phba, hbq_entry); |
996 | list_add_tail(&new_hbq_entry->dbuf.list, &phba->hbqbuf_in_list); | ||
997 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
998 | |||
931 | return &new_hbq_entry->dbuf; | 999 | return &new_hbq_entry->dbuf; |
932 | } | 1000 | } |
933 | 1001 | ||
@@ -951,6 +1019,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
951 | uint32_t Rctl, Type; | 1019 | uint32_t Rctl, Type; |
952 | uint32_t match, i; | 1020 | uint32_t match, i; |
953 | struct lpfc_iocbq *iocbq; | 1021 | struct lpfc_iocbq *iocbq; |
1022 | struct lpfc_dmabuf *dmzbuf; | ||
954 | 1023 | ||
955 | match = 0; | 1024 | match = 0; |
956 | irsp = &(saveq->iocb); | 1025 | irsp = &(saveq->iocb); |
@@ -972,6 +1041,29 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
972 | return 1; | 1041 | return 1; |
973 | } | 1042 | } |
974 | 1043 | ||
1044 | if ((irsp->ulpCommand == CMD_IOCB_RET_XRI64_CX) && | ||
1045 | (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) { | ||
1046 | if (irsp->ulpBdeCount > 0) { | ||
1047 | dmzbuf = lpfc_sli_get_buff(phba, pring, | ||
1048 | irsp->un.ulpWord[3]); | ||
1049 | lpfc_in_buf_free(phba, dmzbuf); | ||
1050 | } | ||
1051 | |||
1052 | if (irsp->ulpBdeCount > 1) { | ||
1053 | dmzbuf = lpfc_sli_get_buff(phba, pring, | ||
1054 | irsp->unsli3.sli3Words[3]); | ||
1055 | lpfc_in_buf_free(phba, dmzbuf); | ||
1056 | } | ||
1057 | |||
1058 | if (irsp->ulpBdeCount > 2) { | ||
1059 | dmzbuf = lpfc_sli_get_buff(phba, pring, | ||
1060 | irsp->unsli3.sli3Words[7]); | ||
1061 | lpfc_in_buf_free(phba, dmzbuf); | ||
1062 | } | ||
1063 | |||
1064 | return 1; | ||
1065 | } | ||
1066 | |||
975 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { | 1067 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { |
976 | if (irsp->ulpBdeCount != 0) { | 1068 | if (irsp->ulpBdeCount != 0) { |
977 | saveq->context2 = lpfc_sli_get_buff(phba, pring, | 1069 | saveq->context2 = lpfc_sli_get_buff(phba, pring, |
@@ -2293,6 +2385,7 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba) | |||
2293 | 2385 | ||
2294 | /* Initialize the struct lpfc_sli_hbq structure for each hbq */ | 2386 | /* Initialize the struct lpfc_sli_hbq structure for each hbq */ |
2295 | phba->link_state = LPFC_INIT_MBX_CMDS; | 2387 | phba->link_state = LPFC_INIT_MBX_CMDS; |
2388 | phba->hbq_in_use = 1; | ||
2296 | 2389 | ||
2297 | hbq_entry_index = 0; | 2390 | hbq_entry_index = 0; |
2298 | for (hbqno = 0; hbqno < hbq_count; ++hbqno) { | 2391 | for (hbqno = 0; hbqno < hbq_count; ++hbqno) { |