diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_bsg.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 332 |
1 files changed, 332 insertions, 0 deletions
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; |