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 | |
| 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>
| -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) { |
