@@ -186,6 +186,9 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
186186 case MPI2_FUNCTION_NVME_ENCAPSULATED :
187187 desc = "nvme_encapsulated" ;
188188 break ;
189+ case MPI2_FUNCTION_MCTP_PASSTHROUGH :
190+ desc = "mctp_passthrough" ;
191+ break ;
189192 }
190193
191194 if (!desc )
@@ -652,6 +655,40 @@ _ctl_set_task_mid(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command *karg,
652655 return 0 ;
653656}
654657
658+ /**
659+ * _ctl_send_mctp_passthru_req - Send an MCTP passthru request
660+ * @ioc: per adapter object
661+ * @mctp_passthru_req: MPI mctp passhthru request from caller
662+ * @psge: pointer to the H2DSGL
663+ * @data_out_dma: DMA buffer for H2D SGL
664+ * @data_out_sz: H2D length
665+ * @data_in_dma: DMA buffer for D2H SGL
666+ * @data_in_sz: D2H length
667+ * @smid: SMID to submit the request
668+ *
669+ */
670+ static void
671+ _ctl_send_mctp_passthru_req (
672+ struct MPT3SAS_ADAPTER * ioc ,
673+ Mpi26MctpPassthroughRequest_t * mctp_passthru_req , void * psge ,
674+ dma_addr_t data_out_dma , int data_out_sz ,
675+ dma_addr_t data_in_dma , int data_in_sz ,
676+ u16 smid )
677+ {
678+ mctp_passthru_req -> H2DLength = data_out_sz ;
679+ mctp_passthru_req -> D2HLength = data_in_sz ;
680+
681+ /* Build the H2D SGL from the data out buffer */
682+ ioc -> build_sg (ioc , psge , data_out_dma , data_out_sz , 0 , 0 );
683+
684+ psge += ioc -> sge_size_ieee ;
685+
686+ /* Build the D2H SGL for the data in buffer */
687+ ioc -> build_sg (ioc , psge , 0 , 0 , data_in_dma , data_in_sz );
688+
689+ ioc -> put_smid_default (ioc , smid );
690+ }
691+
655692/**
656693 * _ctl_do_mpt_command - main handler for MPT3COMMAND opcode
657694 * @ioc: per adapter object
@@ -792,6 +829,23 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
792829
793830 init_completion (& ioc -> ctl_cmds .done );
794831 switch (mpi_request -> Function ) {
832+ case MPI2_FUNCTION_MCTP_PASSTHROUGH :
833+ {
834+ Mpi26MctpPassthroughRequest_t * mctp_passthru_req =
835+ (Mpi26MctpPassthroughRequest_t * )request ;
836+
837+ if (!(ioc -> facts .IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_MCTP_PASSTHRU )) {
838+ ioc_err (ioc , "%s: MCTP Passthrough request not supported\n" ,
839+ __func__ );
840+ mpt3sas_base_free_smid (ioc , smid );
841+ ret = - EINVAL ;
842+ goto out ;
843+ }
844+
845+ _ctl_send_mctp_passthru_req (ioc , mctp_passthru_req , psge , data_out_dma ,
846+ data_out_sz , data_in_dma , data_in_sz , smid );
847+ break ;
848+ }
795849 case MPI2_FUNCTION_NVME_ENCAPSULATED :
796850 {
797851 nvme_encap_request = (Mpi26NVMeEncapsulatedRequest_t * )request ;
@@ -2786,6 +2840,217 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
27862840 return ret ;
27872841}
27882842
2843+ /**
2844+ * _ctl_get_mpt_mctp_passthru_adapter - Traverse the IOC list and return the IOC at
2845+ * dev_index positionthat support MCTP passhtru
2846+ * @dev_index: position in the mpt3sas_ioc_list to search for
2847+ * Return pointer to the IOC on success
2848+ * NULL if device not found error
2849+ */
2850+ static struct MPT3SAS_ADAPTER *
2851+ _ctl_get_mpt_mctp_passthru_adapter (int dev_index )
2852+ {
2853+ struct MPT3SAS_ADAPTER * ioc = NULL ;
2854+ int count = 0 ;
2855+
2856+ spin_lock (& gioc_lock );
2857+ /* Traverse ioc list and return number of IOC that support MCTP passthru */
2858+ list_for_each_entry (ioc , & mpt3sas_ioc_list , list ) {
2859+ if (ioc -> facts .IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_MCTP_PASSTHRU ) {
2860+ if (count == dev_index ) {
2861+ spin_unlock (& gioc_lock );
2862+ return 0 ;
2863+ }
2864+ }
2865+ }
2866+ spin_unlock (& gioc_lock );
2867+
2868+ return NULL ;
2869+ }
2870+
2871+ /**
2872+ * mpt3sas_get_device_count - Retrieve the count of MCTP passthrough
2873+ * capable devices managed by the driver.
2874+ *
2875+ * Returns number of devices that support MCTP passthrough.
2876+ */
2877+ int
2878+ mpt3sas_get_device_count (void )
2879+ {
2880+ int count = 0 ;
2881+ struct MPT3SAS_ADAPTER * ioc = NULL ;
2882+
2883+ spin_lock (& gioc_lock );
2884+ /* Traverse ioc list and return number of IOC that support MCTP passthru */
2885+ list_for_each_entry (ioc , & mpt3sas_ioc_list , list )
2886+ if (ioc -> facts .IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_MCTP_PASSTHRU )
2887+ count ++ ;
2888+
2889+ spin_unlock (& gioc_lock );
2890+
2891+ return count ;
2892+ }
2893+ EXPORT_SYMBOL (mpt3sas_get_device_count );
2894+
2895+ /**
2896+ * mpt3sas_send_passthru_cmd - Send an MPI MCTP passthrough command to
2897+ * firmware
2898+ * @command: The MPI MCTP passthrough command to send to firmware
2899+ *
2900+ * Returns 0 on success, anything else is error.
2901+ */
2902+ int mpt3sas_send_mctp_passthru_req (struct mpt3_passthru_command * command )
2903+ {
2904+ struct MPT3SAS_ADAPTER * ioc ;
2905+ MPI2RequestHeader_t * mpi_request = NULL , * request ;
2906+ MPI2DefaultReply_t * mpi_reply ;
2907+ Mpi26MctpPassthroughRequest_t * mctp_passthru_req ;
2908+ u16 smid ;
2909+ unsigned long timeout ;
2910+ u8 issue_reset = 0 ;
2911+ u32 sz ;
2912+ void * psge ;
2913+ void * data_out = NULL ;
2914+ dma_addr_t data_out_dma = 0 ;
2915+ size_t data_out_sz = 0 ;
2916+ void * data_in = NULL ;
2917+ dma_addr_t data_in_dma = 0 ;
2918+ size_t data_in_sz = 0 ;
2919+ long ret ;
2920+
2921+ /* Retrieve ioc from dev_index */
2922+ ioc = _ctl_get_mpt_mctp_passthru_adapter (command -> dev_index );
2923+ if (!ioc )
2924+ return - ENODEV ;
2925+
2926+ mutex_lock (& ioc -> pci_access_mutex );
2927+ if (ioc -> shost_recovery ||
2928+ ioc -> pci_error_recovery || ioc -> is_driver_loading ||
2929+ ioc -> remove_host ) {
2930+ ret = - EAGAIN ;
2931+ goto unlock_pci_access ;
2932+ }
2933+
2934+ /* Lock the ctl_cmds mutex to ensure a single ctl cmd is pending */
2935+ if (mutex_lock_interruptible (& ioc -> ctl_cmds .mutex )) {
2936+ ret = - ERESTARTSYS ;
2937+ goto unlock_pci_access ;
2938+ }
2939+
2940+ if (ioc -> ctl_cmds .status != MPT3_CMD_NOT_USED ) {
2941+ ioc_err (ioc , "%s: ctl_cmd in use\n" , __func__ );
2942+ ret = - EAGAIN ;
2943+ goto unlock_ctl_cmds ;
2944+ }
2945+
2946+ ret = mpt3sas_wait_for_ioc (ioc , IOC_OPERATIONAL_WAIT_COUNT );
2947+ if (ret )
2948+ goto unlock_ctl_cmds ;
2949+
2950+ mpi_request = (MPI2RequestHeader_t * )command -> mpi_request ;
2951+ if (mpi_request -> Function != MPI2_FUNCTION_MCTP_PASSTHROUGH ) {
2952+ ioc_err (ioc , "%s: Invalid request receveid, Function 0x%x\n" ,
2953+ __func__ , mpi_request -> Function );
2954+ ret = - EINVAL ;
2955+ goto unlock_ctl_cmds ;
2956+ }
2957+
2958+ /* Use first reserved smid for passthrough commands */
2959+ smid = ioc -> scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT + 1 ;
2960+ ret = 0 ;
2961+ ioc -> ctl_cmds .status = MPT3_CMD_PENDING ;
2962+ memset (ioc -> ctl_cmds .reply , 0 , ioc -> reply_sz );
2963+ request = mpt3sas_base_get_msg_frame (ioc , smid );
2964+ memset (request , 0 , ioc -> request_sz );
2965+ memcpy (request , command -> mpi_request , sizeof (Mpi26MctpPassthroughRequest_t ));
2966+ ioc -> ctl_cmds .smid = smid ;
2967+ data_out_sz = command -> data_out_size ;
2968+ data_in_sz = command -> data_in_size ;
2969+
2970+ /* obtain dma-able memory for data transfer */
2971+ if (data_out_sz ) /* WRITE */ {
2972+ data_out = dma_alloc_coherent (& ioc -> pdev -> dev , data_out_sz ,
2973+ & data_out_dma , GFP_ATOMIC );
2974+ if (!data_out ) {
2975+ ret = - ENOMEM ;
2976+ mpt3sas_base_free_smid (ioc , smid );
2977+ goto out ;
2978+ }
2979+ memcpy (data_out , command -> data_out_buf_ptr , data_out_sz );
2980+
2981+ }
2982+
2983+ if (data_in_sz ) /* READ */ {
2984+ data_in = dma_alloc_coherent (& ioc -> pdev -> dev , data_in_sz ,
2985+ & data_in_dma , GFP_ATOMIC );
2986+ if (!data_in ) {
2987+ ret = - ENOMEM ;
2988+ mpt3sas_base_free_smid (ioc , smid );
2989+ goto out ;
2990+ }
2991+ }
2992+
2993+ psge = & ((Mpi26MctpPassthroughRequest_t * )request )-> H2DSGL ;
2994+
2995+ init_completion (& ioc -> ctl_cmds .done );
2996+
2997+ mctp_passthru_req = (Mpi26MctpPassthroughRequest_t * )request ;
2998+
2999+ _ctl_send_mctp_passthru_req (ioc , mctp_passthru_req , psge , data_out_dma ,
3000+ data_out_sz , data_in_dma , data_in_sz , smid );
3001+
3002+ timeout = command -> timeout ;
3003+ if (timeout < MPT3_IOCTL_DEFAULT_TIMEOUT )
3004+ timeout = MPT3_IOCTL_DEFAULT_TIMEOUT ;
3005+
3006+ wait_for_completion_timeout (& ioc -> ctl_cmds .done , timeout * HZ );
3007+ if (!(ioc -> ctl_cmds .status & MPT3_CMD_COMPLETE )) {
3008+ mpt3sas_check_cmd_timeout (ioc ,
3009+ ioc -> ctl_cmds .status , mpi_request ,
3010+ sizeof (Mpi26MctpPassthroughRequest_t ), issue_reset );
3011+ goto issue_host_reset ;
3012+ }
3013+
3014+ mpi_reply = ioc -> ctl_cmds .reply ;
3015+
3016+ /* copy out xdata to user */
3017+ if (data_in_sz )
3018+ memcpy (command -> data_in_buf_ptr , data_in , data_in_sz );
3019+
3020+ /* copy out reply message frame to user */
3021+ if (command -> max_reply_bytes ) {
3022+ sz = min_t (u32 , command -> max_reply_bytes , ioc -> reply_sz );
3023+ memcpy (command -> reply_frame_buf_ptr , ioc -> ctl_cmds .reply , sz );
3024+ }
3025+
3026+ issue_host_reset :
3027+ if (issue_reset ) {
3028+ ret = - ENODATA ;
3029+ mpt3sas_base_hard_reset_handler (ioc , FORCE_BIG_HAMMER );
3030+ }
3031+
3032+ out :
3033+ /* free memory associated with sg buffers */
3034+ if (data_in )
3035+ dma_free_coherent (& ioc -> pdev -> dev , data_in_sz , data_in ,
3036+ data_in_dma );
3037+
3038+ if (data_out )
3039+ dma_free_coherent (& ioc -> pdev -> dev , data_out_sz , data_out ,
3040+ data_out_dma );
3041+
3042+ ioc -> ctl_cmds .status = MPT3_CMD_NOT_USED ;
3043+
3044+ unlock_ctl_cmds :
3045+ mutex_unlock (& ioc -> ctl_cmds .mutex );
3046+
3047+ unlock_pci_access :
3048+ mutex_unlock (& ioc -> pci_access_mutex );
3049+ return ret ;
3050+
3051+ }
3052+ EXPORT_SYMBOL (mpt3sas_send_mctp_passthru_req );
3053+
27893054/**
27903055 * _ctl_ioctl - mpt3ctl main ioctl entry point (unlocked)
27913056 * @file: (struct file)
0 commit comments