diff options
| author | James Smart <james.smart@emulex.com> | 2010-02-26 14:15:00 -0500 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@suse.de> | 2010-03-03 08:39:36 -0500 |
| commit | e2aed29f29d0d289df3b0b627b122832d4dc80fe (patch) | |
| tree | 665b0aff11cfa908d7bc46b80e6c6717f94b665e /drivers/scsi | |
| parent | 0f65ff680f90281d49ee864965f06774eba9657d (diff) | |
[SCSI] lpfc 8.3.10: Added management for LP21000 through BSG.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
| -rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 6 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 332 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.h | 12 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 8 |
4 files changed, 358 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 4d45e6939783..565e16dd74fc 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
| @@ -37,6 +37,9 @@ struct lpfc_sli2_slim; | |||
| 37 | the NameServer before giving up. */ | 37 | the NameServer before giving up. */ |
| 38 | #define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */ | 38 | #define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */ |
| 39 | #define LPFC_DEFAULT_SG_SEG_CNT 64 /* sg element count per scsi cmnd */ | 39 | #define LPFC_DEFAULT_SG_SEG_CNT 64 /* sg element count per scsi cmnd */ |
| 40 | #define LPFC_DEFAULT_MENLO_SG_SEG_CNT 128 /* sg element count per scsi | ||
| 41 | cmnd for menlo needs nearly twice as for firmware | ||
| 42 | downloads using bsg */ | ||
| 40 | #define LPFC_DEFAULT_PROT_SG_SEG_CNT 4096 /* sg protection elements count */ | 43 | #define LPFC_DEFAULT_PROT_SG_SEG_CNT 4096 /* sg protection elements count */ |
| 41 | #define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */ | 44 | #define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */ |
| 42 | #define LPFC_MAX_PROT_SG_SEG_CNT 4096 /* prot sg element count per scsi cmd*/ | 45 | #define LPFC_MAX_PROT_SG_SEG_CNT 4096 /* prot sg element count per scsi cmd*/ |
| @@ -806,6 +809,9 @@ struct lpfc_hba { | |||
| 806 | struct list_head ct_ev_waiters; | 809 | struct list_head ct_ev_waiters; |
| 807 | struct unsol_rcv_ct_ctx ct_ctx[64]; | 810 | struct unsol_rcv_ct_ctx ct_ctx[64]; |
| 808 | uint32_t ctx_idx; | 811 | uint32_t ctx_idx; |
| 812 | |||
| 813 | uint8_t menlo_flag; /* menlo generic flags */ | ||
| 814 | #define HBA_MENLO_SUPPORT 0x1 /* HBA supports menlo commands */ | ||
| 809 | }; | 815 | }; |
| 810 | 816 | ||
| 811 | static inline struct Scsi_Host * | 817 | static inline struct Scsi_Host * |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index f3f1bf1a0a71..692c29f6048e 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
| @@ -83,15 +83,28 @@ struct lpfc_bsg_mbox { | |||
| 83 | struct fc_bsg_job *set_job; | 83 | struct fc_bsg_job *set_job; |
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | #define MENLO_DID 0x0000FC0E | ||
| 87 | |||
| 88 | struct lpfc_bsg_menlo { | ||
| 89 | struct lpfc_iocbq *cmdiocbq; | ||
| 90 | struct lpfc_iocbq *rspiocbq; | ||
| 91 | struct lpfc_dmabuf *bmp; | ||
| 92 | |||
| 93 | /* job waiting for this iocb to finish */ | ||
| 94 | struct fc_bsg_job *set_job; | ||
| 95 | }; | ||
| 96 | |||
| 86 | #define TYPE_EVT 1 | 97 | #define TYPE_EVT 1 |
| 87 | #define TYPE_IOCB 2 | 98 | #define TYPE_IOCB 2 |
| 88 | #define TYPE_MBOX 3 | 99 | #define TYPE_MBOX 3 |
| 100 | #define TYPE_MENLO 4 | ||
| 89 | struct bsg_job_data { | 101 | struct bsg_job_data { |
| 90 | uint32_t type; | 102 | uint32_t type; |
| 91 | union { | 103 | union { |
| 92 | struct lpfc_bsg_event *evt; | 104 | struct lpfc_bsg_event *evt; |
| 93 | struct lpfc_bsg_iocb iocb; | 105 | struct lpfc_bsg_iocb iocb; |
| 94 | struct lpfc_bsg_mbox mbox; | 106 | struct lpfc_bsg_mbox mbox; |
| 107 | struct lpfc_bsg_menlo menlo; | ||
| 95 | } context_un; | 108 | } context_un; |
| 96 | }; | 109 | }; |
| 97 | 110 | ||
| @@ -2456,6 +2469,18 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba, | |||
| 2456 | case MBX_PORT_IOV_CONTROL: | 2469 | case MBX_PORT_IOV_CONTROL: |
| 2457 | break; | 2470 | break; |
| 2458 | case MBX_SET_VARIABLE: | 2471 | case MBX_SET_VARIABLE: |
| 2472 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 2473 | "1226 mbox: set_variable 0x%x, 0x%x\n", | ||
| 2474 | mb->un.varWords[0], | ||
| 2475 | mb->un.varWords[1]); | ||
| 2476 | if ((mb->un.varWords[0] == SETVAR_MLOMNT) | ||
| 2477 | && (mb->un.varWords[1] == 1)) { | ||
| 2478 | phba->wait_4_mlo_maint_flg = 1; | ||
| 2479 | } else if (mb->un.varWords[0] == SETVAR_MLORST) { | ||
| 2480 | phba->link_flag &= ~LS_LOOPBACK_MODE; | ||
| 2481 | phba->fc_topology = TOPOLOGY_PT_PT; | ||
| 2482 | } | ||
| 2483 | break; | ||
| 2459 | case MBX_RUN_BIU_DIAG64: | 2484 | case MBX_RUN_BIU_DIAG64: |
| 2460 | case MBX_READ_EVENT_LOG: | 2485 | case MBX_READ_EVENT_LOG: |
| 2461 | case MBX_READ_SPARM64: | 2486 | case MBX_READ_SPARM64: |
| @@ -2638,6 +2663,297 @@ job_error: | |||
| 2638 | } | 2663 | } |
| 2639 | 2664 | ||
| 2640 | /** | 2665 | /** |
| 2666 | * lpfc_bsg_menlo_cmd_cmp - lpfc_menlo_cmd completion handler | ||
| 2667 | * @phba: Pointer to HBA context object. | ||
| 2668 | * @cmdiocbq: Pointer to command iocb. | ||
| 2669 | * @rspiocbq: Pointer to response iocb. | ||
| 2670 | * | ||
| 2671 | * This function is the completion handler for iocbs issued using | ||
| 2672 | * lpfc_menlo_cmd function. This function is called by the | ||
| 2673 | * ring event handler function without any lock held. This function | ||
| 2674 | * can be called from both worker thread context and interrupt | ||
| 2675 | * context. This function also can be called from another thread which | ||
| 2676 | * cleans up the SLI layer objects. | ||
| 2677 | * This function copies the contents of the response iocb to the | ||
| 2678 | * response iocb memory object provided by the caller of | ||
| 2679 | * lpfc_sli_issue_iocb_wait and then wakes up the thread which | ||
| 2680 | * sleeps for the iocb completion. | ||
| 2681 | **/ | ||
| 2682 | static void | ||
| 2683 | lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba, | ||
| 2684 | struct lpfc_iocbq *cmdiocbq, | ||
| 2685 | struct lpfc_iocbq *rspiocbq) | ||
| 2686 | { | ||
| 2687 | struct bsg_job_data *dd_data; | ||
| 2688 | struct fc_bsg_job *job; | ||
| 2689 | IOCB_t *rsp; | ||
| 2690 | struct lpfc_dmabuf *bmp; | ||
| 2691 | struct lpfc_bsg_menlo *menlo; | ||
| 2692 | unsigned long flags; | ||
| 2693 | struct menlo_response *menlo_resp; | ||
| 2694 | int rc = 0; | ||
| 2695 | |||
| 2696 | spin_lock_irqsave(&phba->ct_ev_lock, flags); | ||
| 2697 | dd_data = cmdiocbq->context1; | ||
| 2698 | if (!dd_data) { | ||
| 2699 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
| 2700 | return; | ||
| 2701 | } | ||
| 2702 | |||
| 2703 | menlo = &dd_data->context_un.menlo; | ||
| 2704 | job = menlo->set_job; | ||
| 2705 | job->dd_data = NULL; /* so timeout handler does not reply */ | ||
| 2706 | |||
| 2707 | spin_lock_irqsave(&phba->hbalock, flags); | ||
| 2708 | cmdiocbq->iocb_flag |= LPFC_IO_WAKE; | ||
| 2709 | if (cmdiocbq->context2 && rspiocbq) | ||
| 2710 | memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb, | ||
| 2711 | &rspiocbq->iocb, sizeof(IOCB_t)); | ||
| 2712 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
| 2713 | |||
| 2714 | bmp = menlo->bmp; | ||
| 2715 | rspiocbq = menlo->rspiocbq; | ||
| 2716 | rsp = &rspiocbq->iocb; | ||
| 2717 | |||
| 2718 | pci_unmap_sg(phba->pcidev, job->request_payload.sg_list, | ||
| 2719 | job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
| 2720 | pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list, | ||
| 2721 | job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
| 2722 | |||
| 2723 | /* always return the xri, this would be used in the case | ||
| 2724 | * of a menlo download to allow the data to be sent as a continuation | ||
| 2725 | * of the exchange. | ||
| 2726 | */ | ||
| 2727 | menlo_resp = (struct menlo_response *) | ||
| 2728 | job->reply->reply_data.vendor_reply.vendor_rsp; | ||
| 2729 | menlo_resp->xri = rsp->ulpContext; | ||
| 2730 | if (rsp->ulpStatus) { | ||
| 2731 | if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) { | ||
| 2732 | switch (rsp->un.ulpWord[4] & 0xff) { | ||
| 2733 | case IOERR_SEQUENCE_TIMEOUT: | ||
| 2734 | rc = -ETIMEDOUT; | ||
| 2735 | break; | ||
| 2736 | case IOERR_INVALID_RPI: | ||
| 2737 | rc = -EFAULT; | ||
| 2738 | break; | ||
| 2739 | default: | ||
| 2740 | rc = -EACCES; | ||
| 2741 | break; | ||
| 2742 | } | ||
| 2743 | } else | ||
| 2744 | rc = -EACCES; | ||
| 2745 | } else | ||
| 2746 | job->reply->reply_payload_rcv_len = | ||
| 2747 | rsp->un.genreq64.bdl.bdeSize; | ||
| 2748 | |||
| 2749 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | ||
| 2750 | lpfc_sli_release_iocbq(phba, rspiocbq); | ||
| 2751 | lpfc_sli_release_iocbq(phba, cmdiocbq); | ||
| 2752 | kfree(bmp); | ||
| 2753 | kfree(dd_data); | ||
| 2754 | /* make error code available to userspace */ | ||
| 2755 | job->reply->result = rc; | ||
| 2756 | /* complete the job back to userspace */ | ||
| 2757 | job->job_done(job); | ||
| 2758 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
| 2759 | return; | ||
| 2760 | } | ||
| 2761 | |||
| 2762 | /** | ||
| 2763 | * lpfc_menlo_cmd - send an ioctl for menlo hardware | ||
| 2764 | * @job: fc_bsg_job to handle | ||
| 2765 | * | ||
| 2766 | * This function issues a gen request 64 CR ioctl for all menlo cmd requests, | ||
| 2767 | * all the command completions will return the xri for the command. | ||
| 2768 | * For menlo data requests a gen request 64 CX is used to continue the exchange | ||
| 2769 | * supplied in the menlo request header xri field. | ||
| 2770 | **/ | ||
| 2771 | static int | ||
| 2772 | lpfc_menlo_cmd(struct fc_bsg_job *job) | ||
| 2773 | { | ||
| 2774 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; | ||
| 2775 | struct lpfc_hba *phba = vport->phba; | ||
| 2776 | struct lpfc_iocbq *cmdiocbq, *rspiocbq; | ||
| 2777 | IOCB_t *cmd, *rsp; | ||
| 2778 | int rc = 0; | ||
| 2779 | struct menlo_command *menlo_cmd; | ||
| 2780 | struct menlo_response *menlo_resp; | ||
| 2781 | struct lpfc_dmabuf *bmp = NULL; | ||
| 2782 | int request_nseg; | ||
| 2783 | int reply_nseg; | ||
| 2784 | struct scatterlist *sgel = NULL; | ||
| 2785 | int numbde; | ||
| 2786 | dma_addr_t busaddr; | ||
| 2787 | struct bsg_job_data *dd_data; | ||
| 2788 | struct ulp_bde64 *bpl = NULL; | ||
| 2789 | |||
| 2790 | /* in case no data is returned return just the return code */ | ||
| 2791 | job->reply->reply_payload_rcv_len = 0; | ||
| 2792 | |||
| 2793 | if (job->request_len < | ||
| 2794 | sizeof(struct fc_bsg_request) + | ||
| 2795 | sizeof(struct menlo_command)) { | ||
| 2796 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
| 2797 | "2784 Received MENLO_CMD request below " | ||
| 2798 | "minimum size\n"); | ||
| 2799 | rc = -ERANGE; | ||
| 2800 | goto no_dd_data; | ||
| 2801 | } | ||
| 2802 | |||
| 2803 | if (job->reply_len < | ||
| 2804 | sizeof(struct fc_bsg_request) + sizeof(struct menlo_response)) { | ||
| 2805 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
| 2806 | "2785 Received MENLO_CMD reply below " | ||
| 2807 | "minimum size\n"); | ||
| 2808 | rc = -ERANGE; | ||
| 2809 | goto no_dd_data; | ||
| 2810 | } | ||
| 2811 | |||
| 2812 | if (!(phba->menlo_flag & HBA_MENLO_SUPPORT)) { | ||
| 2813 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
| 2814 | "2786 Adapter does not support menlo " | ||
| 2815 | "commands\n"); | ||
| 2816 | rc = -EPERM; | ||
| 2817 | goto no_dd_data; | ||
| 2818 | } | ||
| 2819 | |||
| 2820 | menlo_cmd = (struct menlo_command *) | ||
| 2821 | job->request->rqst_data.h_vendor.vendor_cmd; | ||
| 2822 | |||
| 2823 | menlo_resp = (struct menlo_response *) | ||
| 2824 | job->reply->reply_data.vendor_reply.vendor_rsp; | ||
| 2825 | |||
| 2826 | /* allocate our bsg tracking structure */ | ||
| 2827 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); | ||
| 2828 | if (!dd_data) { | ||
| 2829 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
| 2830 | "2787 Failed allocation of dd_data\n"); | ||
| 2831 | rc = -ENOMEM; | ||
| 2832 | goto no_dd_data; | ||
| 2833 | } | ||
| 2834 | |||
| 2835 | bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
| 2836 | if (!bmp) { | ||
| 2837 | rc = -ENOMEM; | ||
| 2838 | goto free_dd; | ||
| 2839 | } | ||
| 2840 | |||
| 2841 | cmdiocbq = lpfc_sli_get_iocbq(phba); | ||
| 2842 | if (!cmdiocbq) { | ||
| 2843 | rc = -ENOMEM; | ||
| 2844 | goto free_bmp; | ||
| 2845 | } | ||
| 2846 | |||
| 2847 | rspiocbq = lpfc_sli_get_iocbq(phba); | ||
| 2848 | if (!rspiocbq) { | ||
| 2849 | rc = -ENOMEM; | ||
| 2850 | goto free_cmdiocbq; | ||
| 2851 | } | ||
| 2852 | |||
| 2853 | rsp = &rspiocbq->iocb; | ||
| 2854 | |||
| 2855 | bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys); | ||
| 2856 | if (!bmp->virt) { | ||
| 2857 | rc = -ENOMEM; | ||
| 2858 | goto free_rspiocbq; | ||
| 2859 | } | ||
| 2860 | |||
| 2861 | INIT_LIST_HEAD(&bmp->list); | ||
| 2862 | bpl = (struct ulp_bde64 *) bmp->virt; | ||
| 2863 | request_nseg = pci_map_sg(phba->pcidev, job->request_payload.sg_list, | ||
| 2864 | job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
| 2865 | for_each_sg(job->request_payload.sg_list, sgel, request_nseg, numbde) { | ||
| 2866 | busaddr = sg_dma_address(sgel); | ||
| 2867 | bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64; | ||
| 2868 | bpl->tus.f.bdeSize = sg_dma_len(sgel); | ||
| 2869 | bpl->tus.w = cpu_to_le32(bpl->tus.w); | ||
| 2870 | bpl->addrLow = cpu_to_le32(putPaddrLow(busaddr)); | ||
| 2871 | bpl->addrHigh = cpu_to_le32(putPaddrHigh(busaddr)); | ||
| 2872 | bpl++; | ||
| 2873 | } | ||
| 2874 | |||
| 2875 | reply_nseg = pci_map_sg(phba->pcidev, job->reply_payload.sg_list, | ||
| 2876 | job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
| 2877 | for_each_sg(job->reply_payload.sg_list, sgel, reply_nseg, numbde) { | ||
| 2878 | busaddr = sg_dma_address(sgel); | ||
| 2879 | bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I; | ||
| 2880 | bpl->tus.f.bdeSize = sg_dma_len(sgel); | ||
| 2881 | bpl->tus.w = cpu_to_le32(bpl->tus.w); | ||
| 2882 | bpl->addrLow = cpu_to_le32(putPaddrLow(busaddr)); | ||
| 2883 | bpl->addrHigh = cpu_to_le32(putPaddrHigh(busaddr)); | ||
| 2884 | bpl++; | ||
| 2885 | } | ||
| 2886 | |||
| 2887 | cmd = &cmdiocbq->iocb; | ||
| 2888 | cmd->un.genreq64.bdl.ulpIoTag32 = 0; | ||
| 2889 | cmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys); | ||
| 2890 | cmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys); | ||
| 2891 | cmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; | ||
| 2892 | cmd->un.genreq64.bdl.bdeSize = | ||
| 2893 | (request_nseg + reply_nseg) * sizeof(struct ulp_bde64); | ||
| 2894 | cmd->un.genreq64.w5.hcsw.Fctl = (SI | LA); | ||
| 2895 | cmd->un.genreq64.w5.hcsw.Dfctl = 0; | ||
| 2896 | cmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CMD; | ||
| 2897 | cmd->un.genreq64.w5.hcsw.Type = MENLO_TRANSPORT_TYPE; /* 0xfe */ | ||
| 2898 | cmd->ulpBdeCount = 1; | ||
| 2899 | cmd->ulpClass = CLASS3; | ||
| 2900 | cmd->ulpOwner = OWN_CHIP; | ||
| 2901 | cmd->ulpLe = 1; /* Limited Edition */ | ||
| 2902 | cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; | ||
| 2903 | cmdiocbq->vport = phba->pport; | ||
| 2904 | /* We want the firmware to timeout before we do */ | ||
| 2905 | cmd->ulpTimeout = MENLO_TIMEOUT - 5; | ||
| 2906 | cmdiocbq->context3 = bmp; | ||
| 2907 | cmdiocbq->context2 = rspiocbq; | ||
| 2908 | cmdiocbq->iocb_cmpl = lpfc_bsg_menlo_cmd_cmp; | ||
| 2909 | cmdiocbq->context1 = dd_data; | ||
| 2910 | cmdiocbq->context2 = rspiocbq; | ||
| 2911 | if (menlo_cmd->cmd == LPFC_BSG_VENDOR_MENLO_CMD) { | ||
| 2912 | cmd->ulpCommand = CMD_GEN_REQUEST64_CR; | ||
| 2913 | cmd->ulpPU = MENLO_PU; /* 3 */ | ||
| 2914 | cmd->un.ulpWord[4] = MENLO_DID; /* 0x0000FC0E */ | ||
| 2915 | cmd->ulpContext = MENLO_CONTEXT; /* 0 */ | ||
| 2916 | } else { | ||
| 2917 | cmd->ulpCommand = CMD_GEN_REQUEST64_CX; | ||
| 2918 | cmd->ulpPU = 1; | ||
| 2919 | cmd->un.ulpWord[4] = 0; | ||
| 2920 | cmd->ulpContext = menlo_cmd->xri; | ||
| 2921 | } | ||
| 2922 | |||
| 2923 | dd_data->type = TYPE_MENLO; | ||
| 2924 | dd_data->context_un.menlo.cmdiocbq = cmdiocbq; | ||
| 2925 | dd_data->context_un.menlo.rspiocbq = rspiocbq; | ||
| 2926 | dd_data->context_un.menlo.set_job = job; | ||
| 2927 | dd_data->context_un.menlo.bmp = bmp; | ||
| 2928 | |||
| 2929 | rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, | ||
| 2930 | MENLO_TIMEOUT - 5); | ||
| 2931 | if (rc == IOCB_SUCCESS) | ||
| 2932 | return 0; /* done for now */ | ||
| 2933 | |||
| 2934 | /* iocb failed so cleanup */ | ||
| 2935 | pci_unmap_sg(phba->pcidev, job->request_payload.sg_list, | ||
| 2936 | job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
| 2937 | pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list, | ||
| 2938 | job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
| 2939 | |||
| 2940 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | ||
| 2941 | |||
| 2942 | free_rspiocbq: | ||
| 2943 | lpfc_sli_release_iocbq(phba, rspiocbq); | ||
| 2944 | free_cmdiocbq: | ||
| 2945 | lpfc_sli_release_iocbq(phba, cmdiocbq); | ||
| 2946 | free_bmp: | ||
| 2947 | kfree(bmp); | ||
| 2948 | free_dd: | ||
| 2949 | kfree(dd_data); | ||
| 2950 | no_dd_data: | ||
| 2951 | /* make error code available to userspace */ | ||
| 2952 | job->reply->result = rc; | ||
| 2953 | job->dd_data = NULL; | ||
| 2954 | return rc; | ||
| 2955 | } | ||
| 2956 | /** | ||
| 2641 | * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job | 2957 | * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job |
| 2642 | * @job: fc_bsg_job to handle | 2958 | * @job: fc_bsg_job to handle |
| 2643 | **/ | 2959 | **/ |
| @@ -2669,6 +2985,10 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job) | |||
| 2669 | case LPFC_BSG_VENDOR_MBOX: | 2985 | case LPFC_BSG_VENDOR_MBOX: |
| 2670 | rc = lpfc_bsg_mbox_cmd(job); | 2986 | rc = lpfc_bsg_mbox_cmd(job); |
| 2671 | break; | 2987 | break; |
| 2988 | case LPFC_BSG_VENDOR_MENLO_CMD: | ||
| 2989 | case LPFC_BSG_VENDOR_MENLO_DATA: | ||
| 2990 | rc = lpfc_menlo_cmd(job); | ||
| 2991 | break; | ||
| 2672 | default: | 2992 | default: |
| 2673 | rc = -EINVAL; | 2993 | rc = -EINVAL; |
| 2674 | job->reply->reply_payload_rcv_len = 0; | 2994 | job->reply->reply_payload_rcv_len = 0; |
| @@ -2728,6 +3048,7 @@ lpfc_bsg_timeout(struct fc_bsg_job *job) | |||
| 2728 | struct lpfc_bsg_event *evt; | 3048 | struct lpfc_bsg_event *evt; |
| 2729 | struct lpfc_bsg_iocb *iocb; | 3049 | struct lpfc_bsg_iocb *iocb; |
| 2730 | struct lpfc_bsg_mbox *mbox; | 3050 | struct lpfc_bsg_mbox *mbox; |
| 3051 | struct lpfc_bsg_menlo *menlo; | ||
| 2731 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | 3052 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; |
| 2732 | struct bsg_job_data *dd_data; | 3053 | struct bsg_job_data *dd_data; |
| 2733 | unsigned long flags; | 3054 | unsigned long flags; |
| @@ -2775,6 +3096,17 @@ lpfc_bsg_timeout(struct fc_bsg_job *job) | |||
| 2775 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 3096 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
| 2776 | job->job_done(job); | 3097 | job->job_done(job); |
| 2777 | break; | 3098 | break; |
| 3099 | case TYPE_MENLO: | ||
| 3100 | menlo = &dd_data->context_un.menlo; | ||
| 3101 | cmdiocb = menlo->cmdiocbq; | ||
| 3102 | /* hint to completion handler that the job timed out */ | ||
| 3103 | job->reply->result = -EAGAIN; | ||
| 3104 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
| 3105 | /* this will call our completion handler */ | ||
| 3106 | spin_lock_irq(&phba->hbalock); | ||
| 3107 | lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb); | ||
| 3108 | spin_unlock_irq(&phba->hbalock); | ||
| 3109 | break; | ||
| 2778 | default: | 3110 | default: |
| 2779 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 3111 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
| 2780 | break; | 3112 | break; |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h index 6c8f87e39b98..5bc630819b9e 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.h +++ b/drivers/scsi/lpfc/lpfc_bsg.h | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | #define LPFC_BSG_VENDOR_DIAG_TEST 5 | 31 | #define LPFC_BSG_VENDOR_DIAG_TEST 5 |
| 32 | #define LPFC_BSG_VENDOR_GET_MGMT_REV 6 | 32 | #define LPFC_BSG_VENDOR_GET_MGMT_REV 6 |
| 33 | #define LPFC_BSG_VENDOR_MBOX 7 | 33 | #define LPFC_BSG_VENDOR_MBOX 7 |
| 34 | #define LPFC_BSG_VENDOR_MENLO_CMD 8 | ||
| 35 | #define LPFC_BSG_VENDOR_MENLO_DATA 9 | ||
| 34 | 36 | ||
| 35 | struct set_ct_event { | 37 | struct set_ct_event { |
| 36 | uint32_t command; | 38 | uint32_t command; |
| @@ -96,3 +98,13 @@ struct dfc_mbox_req { | |||
| 96 | uint8_t mbOffset; | 98 | uint8_t mbOffset; |
| 97 | }; | 99 | }; |
| 98 | 100 | ||
| 101 | /* Used for menlo command or menlo data. The xri is only used for menlo data */ | ||
| 102 | struct menlo_command { | ||
| 103 | uint32_t cmd; | ||
| 104 | uint32_t xri; | ||
| 105 | }; | ||
| 106 | |||
| 107 | struct menlo_response { | ||
| 108 | uint32_t xri; /* return the xri of the iocb exchange */ | ||
| 109 | }; | ||
| 110 | |||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b7889c53fe23..88e02a453e0e 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
| @@ -2597,6 +2597,14 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) | |||
| 2597 | init_timer(&vport->els_tmofunc); | 2597 | init_timer(&vport->els_tmofunc); |
| 2598 | vport->els_tmofunc.function = lpfc_els_timeout; | 2598 | vport->els_tmofunc.function = lpfc_els_timeout; |
| 2599 | vport->els_tmofunc.data = (unsigned long)vport; | 2599 | vport->els_tmofunc.data = (unsigned long)vport; |
| 2600 | if (phba->pcidev->device == PCI_DEVICE_ID_HORNET) { | ||
| 2601 | phba->menlo_flag |= HBA_MENLO_SUPPORT; | ||
| 2602 | /* check for menlo minimum sg count */ | ||
| 2603 | if (phba->cfg_sg_seg_cnt < LPFC_DEFAULT_MENLO_SG_SEG_CNT) { | ||
| 2604 | phba->cfg_sg_seg_cnt = LPFC_DEFAULT_MENLO_SG_SEG_CNT; | ||
| 2605 | shost->sg_tablesize = phba->cfg_sg_seg_cnt; | ||
| 2606 | } | ||
| 2607 | } | ||
| 2600 | 2608 | ||
| 2601 | error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev); | 2609 | error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev); |
| 2602 | if (error) | 2610 | if (error) |
