diff options
author | James Smart <james.smart@emulex.com> | 2010-04-06 15:05:28 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-04-11 14:45:38 -0400 |
commit | c74959370369cd870560777b7db7ec940565bb85 (patch) | |
tree | febf7febd3fce3ba160a405f91bc1c42858c8ee8 /drivers/scsi/lpfc/lpfc_bsg.c | |
parent | 49198b371e2da20548d1408a7d3a8dea2f91263c (diff) |
[SCSI] lpfc 8.3.12: BSG Fixes and enhancements
- Add memcpy to mailbox completion to transfer reply correctly.
- Add support for BSG mailbox commands (dump, update_cfg, and
event_log_status).
- Add warning message and refuse mailbox command while mgmt is blocked.
- Add checks for memory allocation failure.
- Add check for sli4 dump zero BDE size.
- Only copy data if mailbox commands succeed.
- Add support for Read Event Log mailbox command.
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_bsg.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 274 |
1 files changed, 236 insertions, 38 deletions
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 141a1ce9b742..dcf088262b20 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -84,7 +84,7 @@ struct lpfc_bsg_mbox { | |||
84 | uint8_t *ext; /* extended mailbox data */ | 84 | uint8_t *ext; /* extended mailbox data */ |
85 | uint32_t mbOffset; /* from app */ | 85 | uint32_t mbOffset; /* from app */ |
86 | uint32_t inExtWLen; /* from app */ | 86 | uint32_t inExtWLen; /* from app */ |
87 | uint32_t outWxtWLen; /* from app */ | 87 | uint32_t outExtWLen; /* from app */ |
88 | 88 | ||
89 | /* job waiting for this mbox command to finish */ | 89 | /* job waiting for this mbox command to finish */ |
90 | struct fc_bsg_job *set_job; | 90 | struct fc_bsg_job *set_job; |
@@ -1714,21 +1714,26 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi, | |||
1714 | dmabuf = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 1714 | dmabuf = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
1715 | if (dmabuf) { | 1715 | if (dmabuf) { |
1716 | dmabuf->virt = lpfc_mbuf_alloc(phba, 0, &dmabuf->phys); | 1716 | dmabuf->virt = lpfc_mbuf_alloc(phba, 0, &dmabuf->phys); |
1717 | INIT_LIST_HEAD(&dmabuf->list); | 1717 | if (dmabuf->virt) { |
1718 | bpl = (struct ulp_bde64 *) dmabuf->virt; | 1718 | INIT_LIST_HEAD(&dmabuf->list); |
1719 | memset(bpl, 0, sizeof(*bpl)); | 1719 | bpl = (struct ulp_bde64 *) dmabuf->virt; |
1720 | ctreq = (struct lpfc_sli_ct_request *)(bpl + 1); | 1720 | memset(bpl, 0, sizeof(*bpl)); |
1721 | bpl->addrHigh = | 1721 | ctreq = (struct lpfc_sli_ct_request *)(bpl + 1); |
1722 | le32_to_cpu(putPaddrHigh(dmabuf->phys + sizeof(*bpl))); | 1722 | bpl->addrHigh = |
1723 | bpl->addrLow = | 1723 | le32_to_cpu(putPaddrHigh(dmabuf->phys + |
1724 | le32_to_cpu(putPaddrLow(dmabuf->phys + sizeof(*bpl))); | 1724 | sizeof(*bpl))); |
1725 | bpl->tus.f.bdeFlags = 0; | 1725 | bpl->addrLow = |
1726 | bpl->tus.f.bdeSize = ELX_LOOPBACK_HEADER_SZ; | 1726 | le32_to_cpu(putPaddrLow(dmabuf->phys + |
1727 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 1727 | sizeof(*bpl))); |
1728 | bpl->tus.f.bdeFlags = 0; | ||
1729 | bpl->tus.f.bdeSize = ELX_LOOPBACK_HEADER_SZ; | ||
1730 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | ||
1731 | } | ||
1728 | } | 1732 | } |
1729 | 1733 | ||
1730 | if (cmdiocbq == NULL || rspiocbq == NULL || | 1734 | if (cmdiocbq == NULL || rspiocbq == NULL || |
1731 | dmabuf == NULL || bpl == NULL || ctreq == NULL) { | 1735 | dmabuf == NULL || bpl == NULL || ctreq == NULL || |
1736 | dmabuf->virt == NULL) { | ||
1732 | ret_val = ENOMEM; | 1737 | ret_val = ENOMEM; |
1733 | goto err_get_xri_exit; | 1738 | goto err_get_xri_exit; |
1734 | } | 1739 | } |
@@ -1924,9 +1929,11 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri, | |||
1924 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 1929 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
1925 | if (rxbmp != NULL) { | 1930 | if (rxbmp != NULL) { |
1926 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | 1931 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); |
1927 | INIT_LIST_HEAD(&rxbmp->list); | 1932 | if (rxbmp->virt) { |
1928 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | 1933 | INIT_LIST_HEAD(&rxbmp->list); |
1929 | rxbuffer = diag_cmd_data_alloc(phba, rxbpl, len, 0); | 1934 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; |
1935 | rxbuffer = diag_cmd_data_alloc(phba, rxbpl, len, 0); | ||
1936 | } | ||
1930 | } | 1937 | } |
1931 | 1938 | ||
1932 | if (!cmdiocbq || !rxbmp || !rxbpl || !rxbuffer) { | 1939 | if (!cmdiocbq || !rxbmp || !rxbpl || !rxbuffer) { |
@@ -2180,14 +2187,16 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job) | |||
2180 | 2187 | ||
2181 | if (txbmp) { | 2188 | if (txbmp) { |
2182 | txbmp->virt = lpfc_mbuf_alloc(phba, 0, &txbmp->phys); | 2189 | txbmp->virt = lpfc_mbuf_alloc(phba, 0, &txbmp->phys); |
2183 | INIT_LIST_HEAD(&txbmp->list); | 2190 | if (txbmp->virt) { |
2184 | txbpl = (struct ulp_bde64 *) txbmp->virt; | 2191 | INIT_LIST_HEAD(&txbmp->list); |
2185 | if (txbpl) | 2192 | txbpl = (struct ulp_bde64 *) txbmp->virt; |
2186 | txbuffer = diag_cmd_data_alloc(phba, | 2193 | txbuffer = diag_cmd_data_alloc(phba, |
2187 | txbpl, full_size, 0); | 2194 | txbpl, full_size, 0); |
2195 | } | ||
2188 | } | 2196 | } |
2189 | 2197 | ||
2190 | if (!cmdiocbq || !rspiocbq || !txbmp || !txbpl || !txbuffer) { | 2198 | if (!cmdiocbq || !rspiocbq || !txbmp || !txbpl || !txbuffer || |
2199 | !txbmp->virt) { | ||
2191 | rc = -ENOMEM; | 2200 | rc = -ENOMEM; |
2192 | goto err_loopback_test_exit; | 2201 | goto err_loopback_test_exit; |
2193 | } | 2202 | } |
@@ -2404,12 +2413,34 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
2404 | from = (uint8_t *)&pmboxq->u.mb; | 2413 | from = (uint8_t *)&pmboxq->u.mb; |
2405 | to = (uint8_t *)dd_data->context_un.mbox.mb; | 2414 | to = (uint8_t *)dd_data->context_un.mbox.mb; |
2406 | memcpy(to, from, sizeof(MAILBOX_t)); | 2415 | memcpy(to, from, sizeof(MAILBOX_t)); |
2407 | /* copy the extended data if any, count is in words */ | 2416 | if (pmboxq->u.mb.mbxStatus == MBX_SUCCESS) { |
2408 | if (dd_data->context_un.mbox.outWxtWLen) { | 2417 | /* copy the extended data if any, count is in words */ |
2409 | from = (uint8_t *)dd_data->context_un.mbox.ext; | 2418 | if (dd_data->context_un.mbox.outExtWLen) { |
2410 | to += sizeof(MAILBOX_t); | 2419 | from = (uint8_t *)dd_data->context_un.mbox.ext; |
2411 | memcpy(to, from, | 2420 | to += sizeof(MAILBOX_t); |
2412 | dd_data->context_un.mbox.outWxtWLen * sizeof(uint32_t)); | 2421 | size = dd_data->context_un.mbox.outExtWLen * |
2422 | sizeof(uint32_t); | ||
2423 | memcpy(to, from, size); | ||
2424 | } else if (pmboxq->u.mb.mbxCommand == MBX_RUN_BIU_DIAG64) { | ||
2425 | from = (uint8_t *)dd_data->context_un.mbox. | ||
2426 | dmp->dma.virt; | ||
2427 | to += sizeof(MAILBOX_t); | ||
2428 | size = dd_data->context_un.mbox.dmp->size; | ||
2429 | memcpy(to, from, size); | ||
2430 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
2431 | (pmboxq->u.mb.mbxCommand == MBX_DUMP_MEMORY)) { | ||
2432 | from = (uint8_t *)dd_data->context_un.mbox.dmp->dma. | ||
2433 | virt; | ||
2434 | to += sizeof(MAILBOX_t); | ||
2435 | size = pmboxq->u.mb.un.varWords[5]; | ||
2436 | memcpy(to, from, size); | ||
2437 | } else if (pmboxq->u.mb.mbxCommand == MBX_READ_EVENT_LOG) { | ||
2438 | from = (uint8_t *)dd_data->context_un. | ||
2439 | mbox.dmp->dma.virt; | ||
2440 | to += sizeof(MAILBOX_t); | ||
2441 | size = dd_data->context_un.mbox.dmp->size; | ||
2442 | memcpy(to, from, size); | ||
2443 | } | ||
2413 | } | 2444 | } |
2414 | 2445 | ||
2415 | from = (uint8_t *)dd_data->context_un.mbox.mb; | 2446 | from = (uint8_t *)dd_data->context_un.mbox.mb; |
@@ -2503,6 +2534,7 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba, | |||
2503 | case MBX_SET_DEBUG: | 2534 | case MBX_SET_DEBUG: |
2504 | case MBX_WRITE_WWN: | 2535 | case MBX_WRITE_WWN: |
2505 | case MBX_SLI4_CONFIG: | 2536 | case MBX_SLI4_CONFIG: |
2537 | case MBX_READ_EVENT_LOG: | ||
2506 | case MBX_READ_EVENT_LOG_STATUS: | 2538 | case MBX_READ_EVENT_LOG_STATUS: |
2507 | case MBX_WRITE_EVENT_LOG: | 2539 | case MBX_WRITE_EVENT_LOG: |
2508 | case MBX_PORT_CAPABILITIES: | 2540 | case MBX_PORT_CAPABILITIES: |
@@ -2522,7 +2554,6 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba, | |||
2522 | phba->fc_topology = TOPOLOGY_PT_PT; | 2554 | phba->fc_topology = TOPOLOGY_PT_PT; |
2523 | } | 2555 | } |
2524 | break; | 2556 | break; |
2525 | case MBX_READ_EVENT_LOG: | ||
2526 | case MBX_READ_SPARM64: | 2557 | case MBX_READ_SPARM64: |
2527 | case MBX_READ_LA: | 2558 | case MBX_READ_LA: |
2528 | case MBX_READ_LA64: | 2559 | case MBX_READ_LA64: |
@@ -2577,7 +2608,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2577 | 2608 | ||
2578 | /* check if requested extended data lengths are valid */ | 2609 | /* check if requested extended data lengths are valid */ |
2579 | if ((mbox_req->inExtWLen > MAILBOX_EXT_SIZE) || | 2610 | if ((mbox_req->inExtWLen > MAILBOX_EXT_SIZE) || |
2580 | (mbox_req->outWxtWLen > MAILBOX_EXT_SIZE)) { | 2611 | (mbox_req->outExtWLen > MAILBOX_EXT_SIZE)) { |
2581 | rc = -ERANGE; | 2612 | rc = -ERANGE; |
2582 | goto job_done; | 2613 | goto job_done; |
2583 | } | 2614 | } |
@@ -2618,8 +2649,29 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2618 | pmb->mbxOwner = OWN_HOST; | 2649 | pmb->mbxOwner = OWN_HOST; |
2619 | pmboxq->vport = vport; | 2650 | pmboxq->vport = vport; |
2620 | 2651 | ||
2652 | /* If HBA encountered an error attention, allow only DUMP | ||
2653 | * or RESTART mailbox commands until the HBA is restarted. | ||
2654 | */ | ||
2655 | if (phba->pport->stopped && | ||
2656 | pmb->mbxCommand != MBX_DUMP_MEMORY && | ||
2657 | pmb->mbxCommand != MBX_RESTART && | ||
2658 | pmb->mbxCommand != MBX_WRITE_VPARMS && | ||
2659 | pmb->mbxCommand != MBX_WRITE_WWN) | ||
2660 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, | ||
2661 | "2797 mbox: Issued mailbox cmd " | ||
2662 | "0x%x while in stopped state.\n", | ||
2663 | pmb->mbxCommand); | ||
2664 | |||
2665 | /* Don't allow mailbox commands to be sent when blocked | ||
2666 | * or when in the middle of discovery | ||
2667 | */ | ||
2668 | if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { | ||
2669 | rc = -EAGAIN; | ||
2670 | goto job_done; | ||
2671 | } | ||
2672 | |||
2621 | /* extended mailbox commands will need an extended buffer */ | 2673 | /* extended mailbox commands will need an extended buffer */ |
2622 | if (mbox_req->inExtWLen || mbox_req->outWxtWLen) { | 2674 | if (mbox_req->inExtWLen || mbox_req->outExtWLen) { |
2623 | ext = kzalloc(MAILBOX_EXT_SIZE, GFP_KERNEL); | 2675 | ext = kzalloc(MAILBOX_EXT_SIZE, GFP_KERNEL); |
2624 | if (!ext) { | 2676 | if (!ext) { |
2625 | rc = -ENOMEM; | 2677 | rc = -ENOMEM; |
@@ -2639,7 +2691,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2639 | mbox_req->inExtWLen * | 2691 | mbox_req->inExtWLen * |
2640 | sizeof(uint32_t); | 2692 | sizeof(uint32_t); |
2641 | pmboxq->out_ext_byte_len = | 2693 | pmboxq->out_ext_byte_len = |
2642 | mbox_req->outWxtWLen * | 2694 | mbox_req->outExtWLen * |
2643 | sizeof(uint32_t); | 2695 | sizeof(uint32_t); |
2644 | pmboxq->mbox_offset_word = | 2696 | pmboxq->mbox_offset_word = |
2645 | mbox_req->mbOffset; | 2697 | mbox_req->mbOffset; |
@@ -2647,7 +2699,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2647 | pmboxq->in_ext_byte_len = | 2699 | pmboxq->in_ext_byte_len = |
2648 | mbox_req->inExtWLen * sizeof(uint32_t); | 2700 | mbox_req->inExtWLen * sizeof(uint32_t); |
2649 | pmboxq->out_ext_byte_len = | 2701 | pmboxq->out_ext_byte_len = |
2650 | mbox_req->outWxtWLen * sizeof(uint32_t); | 2702 | mbox_req->outExtWLen * sizeof(uint32_t); |
2651 | pmboxq->mbox_offset_word = mbox_req->mbOffset; | 2703 | pmboxq->mbox_offset_word = mbox_req->mbOffset; |
2652 | } | 2704 | } |
2653 | 2705 | ||
@@ -2656,6 +2708,17 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2656 | * use ours | 2708 | * use ours |
2657 | */ | 2709 | */ |
2658 | if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) { | 2710 | if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) { |
2711 | uint32_t transmit_length = pmb->un.varWords[1]; | ||
2712 | uint32_t receive_length = pmb->un.varWords[4]; | ||
2713 | /* transmit length cannot be greater than receive length or | ||
2714 | * mailbox extension size | ||
2715 | */ | ||
2716 | if ((transmit_length > receive_length) || | ||
2717 | (transmit_length > MAILBOX_EXT_SIZE)) { | ||
2718 | rc = -ERANGE; | ||
2719 | goto job_done; | ||
2720 | } | ||
2721 | |||
2659 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 2722 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
2660 | if (!rxbmp) { | 2723 | if (!rxbmp) { |
2661 | rc = -ENOMEM; | 2724 | rc = -ENOMEM; |
@@ -2663,9 +2726,14 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2663 | } | 2726 | } |
2664 | 2727 | ||
2665 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | 2728 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); |
2729 | if (!rxbmp->virt) { | ||
2730 | rc = -ENOMEM; | ||
2731 | goto job_done; | ||
2732 | } | ||
2733 | |||
2666 | INIT_LIST_HEAD(&rxbmp->list); | 2734 | INIT_LIST_HEAD(&rxbmp->list); |
2667 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | 2735 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; |
2668 | dmp = diag_cmd_data_alloc(phba, rxbpl, BSG_MBOX_SIZE, 0); | 2736 | dmp = diag_cmd_data_alloc(phba, rxbpl, transmit_length, 0); |
2669 | if (!dmp) { | 2737 | if (!dmp) { |
2670 | rc = -ENOMEM; | 2738 | rc = -ENOMEM; |
2671 | goto job_done; | 2739 | goto job_done; |
@@ -2685,13 +2753,143 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2685 | putPaddrLow(dmp->dma.phys + | 2753 | putPaddrLow(dmp->dma.phys + |
2686 | pmb->un.varBIUdiag.un.s2. | 2754 | pmb->un.varBIUdiag.un.s2. |
2687 | xmit_bde64.tus.f.bdeSize); | 2755 | xmit_bde64.tus.f.bdeSize); |
2688 | dd_data->context_un.mbox.rxbmp = rxbmp; | 2756 | |
2689 | dd_data->context_un.mbox.dmp = dmp; | 2757 | /* copy the transmit data found in the mailbox extension area */ |
2690 | } else { | 2758 | from = (uint8_t *)mb; |
2691 | dd_data->context_un.mbox.rxbmp = NULL; | 2759 | from += sizeof(MAILBOX_t); |
2692 | dd_data->context_un.mbox.dmp = NULL; | 2760 | memcpy((uint8_t *)dmp->dma.virt, from, transmit_length); |
2761 | } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) { | ||
2762 | struct READ_EVENT_LOG_VAR *rdEventLog = | ||
2763 | &pmb->un.varRdEventLog ; | ||
2764 | uint32_t receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize; | ||
2765 | uint32_t mode = bf_get(lpfc_event_log, rdEventLog); | ||
2766 | |||
2767 | /* receive length cannot be greater than mailbox | ||
2768 | * extension size | ||
2769 | */ | ||
2770 | if (receive_length > MAILBOX_EXT_SIZE) { | ||
2771 | rc = -ERANGE; | ||
2772 | goto job_done; | ||
2773 | } | ||
2774 | |||
2775 | /* mode zero uses a bde like biu diags command */ | ||
2776 | if (mode == 0) { | ||
2777 | |||
2778 | /* rebuild the command for sli4 using our own buffers | ||
2779 | * like we do for biu diags | ||
2780 | */ | ||
2781 | |||
2782 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
2783 | if (!rxbmp) { | ||
2784 | rc = -ENOMEM; | ||
2785 | goto job_done; | ||
2786 | } | ||
2787 | |||
2788 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
2789 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
2790 | if (rxbpl) { | ||
2791 | INIT_LIST_HEAD(&rxbmp->list); | ||
2792 | dmp = diag_cmd_data_alloc(phba, rxbpl, | ||
2793 | receive_length, 0); | ||
2794 | } | ||
2795 | |||
2796 | if (!dmp) { | ||
2797 | rc = -ENOMEM; | ||
2798 | goto job_done; | ||
2799 | } | ||
2800 | |||
2801 | INIT_LIST_HEAD(&dmp->dma.list); | ||
2802 | pmb->un.varWords[3] = putPaddrLow(dmp->dma.phys); | ||
2803 | pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys); | ||
2804 | } | ||
2805 | } else if (phba->sli_rev == LPFC_SLI_REV4) { | ||
2806 | if (pmb->mbxCommand == MBX_DUMP_MEMORY) { | ||
2807 | /* rebuild the command for sli4 using our own buffers | ||
2808 | * like we do for biu diags | ||
2809 | */ | ||
2810 | uint32_t receive_length = pmb->un.varWords[2]; | ||
2811 | /* receive length cannot be greater than mailbox | ||
2812 | * extension size | ||
2813 | */ | ||
2814 | if ((receive_length == 0) || | ||
2815 | (receive_length > MAILBOX_EXT_SIZE)) { | ||
2816 | rc = -ERANGE; | ||
2817 | goto job_done; | ||
2818 | } | ||
2819 | |||
2820 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
2821 | if (!rxbmp) { | ||
2822 | rc = -ENOMEM; | ||
2823 | goto job_done; | ||
2824 | } | ||
2825 | |||
2826 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
2827 | if (!rxbmp->virt) { | ||
2828 | rc = -ENOMEM; | ||
2829 | goto job_done; | ||
2830 | } | ||
2831 | |||
2832 | INIT_LIST_HEAD(&rxbmp->list); | ||
2833 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
2834 | dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length, | ||
2835 | 0); | ||
2836 | if (!dmp) { | ||
2837 | rc = -ENOMEM; | ||
2838 | goto job_done; | ||
2839 | } | ||
2840 | |||
2841 | INIT_LIST_HEAD(&dmp->dma.list); | ||
2842 | pmb->un.varWords[3] = putPaddrLow(dmp->dma.phys); | ||
2843 | pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys); | ||
2844 | } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) && | ||
2845 | pmb->un.varUpdateCfg.co) { | ||
2846 | struct ulp_bde64 *bde = | ||
2847 | (struct ulp_bde64 *)&pmb->un.varWords[4]; | ||
2848 | |||
2849 | /* bde size cannot be greater than mailbox ext size */ | ||
2850 | if (bde->tus.f.bdeSize > MAILBOX_EXT_SIZE) { | ||
2851 | rc = -ERANGE; | ||
2852 | goto job_done; | ||
2853 | } | ||
2854 | |||
2855 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
2856 | if (!rxbmp) { | ||
2857 | rc = -ENOMEM; | ||
2858 | goto job_done; | ||
2859 | } | ||
2860 | |||
2861 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
2862 | if (!rxbmp->virt) { | ||
2863 | rc = -ENOMEM; | ||
2864 | goto job_done; | ||
2865 | } | ||
2866 | |||
2867 | INIT_LIST_HEAD(&rxbmp->list); | ||
2868 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
2869 | dmp = diag_cmd_data_alloc(phba, rxbpl, | ||
2870 | bde->tus.f.bdeSize, 0); | ||
2871 | if (!dmp) { | ||
2872 | rc = -ENOMEM; | ||
2873 | goto job_done; | ||
2874 | } | ||
2875 | |||
2876 | INIT_LIST_HEAD(&dmp->dma.list); | ||
2877 | bde->addrHigh = putPaddrHigh(dmp->dma.phys); | ||
2878 | bde->addrLow = putPaddrLow(dmp->dma.phys); | ||
2879 | |||
2880 | /* copy the transmit data found in the mailbox | ||
2881 | * extension area | ||
2882 | */ | ||
2883 | from = (uint8_t *)mb; | ||
2884 | from += sizeof(MAILBOX_t); | ||
2885 | memcpy((uint8_t *)dmp->dma.virt, from, | ||
2886 | bde->tus.f.bdeSize); | ||
2887 | } | ||
2693 | } | 2888 | } |
2694 | 2889 | ||
2890 | dd_data->context_un.mbox.rxbmp = rxbmp; | ||
2891 | dd_data->context_un.mbox.dmp = dmp; | ||
2892 | |||
2695 | /* setup wake call as IOCB callback */ | 2893 | /* setup wake call as IOCB callback */ |
2696 | pmboxq->mbox_cmpl = lpfc_bsg_wake_mbox_wait; | 2894 | pmboxq->mbox_cmpl = lpfc_bsg_wake_mbox_wait; |
2697 | 2895 | ||
@@ -2704,7 +2902,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2704 | dd_data->context_un.mbox.ext = ext; | 2902 | dd_data->context_un.mbox.ext = ext; |
2705 | dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset; | 2903 | dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset; |
2706 | dd_data->context_un.mbox.inExtWLen = mbox_req->inExtWLen; | 2904 | dd_data->context_un.mbox.inExtWLen = mbox_req->inExtWLen; |
2707 | dd_data->context_un.mbox.outWxtWLen = mbox_req->outWxtWLen; | 2905 | dd_data->context_un.mbox.outExtWLen = mbox_req->outExtWLen; |
2708 | job->dd_data = dd_data; | 2906 | job->dd_data = dd_data; |
2709 | 2907 | ||
2710 | if ((vport->fc_flag & FC_OFFLINE_MODE) || | 2908 | if ((vport->fc_flag & FC_OFFLINE_MODE) || |