@@ -491,6 +491,73 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
491491 return 0 ;
492492}
493493
494+ void mhi_deinit_chan_ctxt (struct mhi_controller * mhi_cntrl ,
495+ struct mhi_chan * mhi_chan )
496+ {
497+ struct mhi_ring * buf_ring ;
498+ struct mhi_ring * tre_ring ;
499+ struct mhi_chan_ctxt * chan_ctxt ;
500+
501+ buf_ring = & mhi_chan -> buf_ring ;
502+ tre_ring = & mhi_chan -> tre_ring ;
503+ chan_ctxt = & mhi_cntrl -> mhi_ctxt -> chan_ctxt [mhi_chan -> chan ];
504+
505+ mhi_free_coherent (mhi_cntrl , tre_ring -> alloc_size ,
506+ tre_ring -> pre_aligned , tre_ring -> dma_handle );
507+ vfree (buf_ring -> base );
508+
509+ buf_ring -> base = tre_ring -> base = NULL ;
510+ chan_ctxt -> rbase = 0 ;
511+ }
512+
513+ int mhi_init_chan_ctxt (struct mhi_controller * mhi_cntrl ,
514+ struct mhi_chan * mhi_chan )
515+ {
516+ struct mhi_ring * buf_ring ;
517+ struct mhi_ring * tre_ring ;
518+ struct mhi_chan_ctxt * chan_ctxt ;
519+ u32 tmp ;
520+ int ret ;
521+
522+ buf_ring = & mhi_chan -> buf_ring ;
523+ tre_ring = & mhi_chan -> tre_ring ;
524+ tre_ring -> el_size = sizeof (struct mhi_tre );
525+ tre_ring -> len = tre_ring -> el_size * tre_ring -> elements ;
526+ chan_ctxt = & mhi_cntrl -> mhi_ctxt -> chan_ctxt [mhi_chan -> chan ];
527+ ret = mhi_alloc_aligned_ring (mhi_cntrl , tre_ring , tre_ring -> len );
528+ if (ret )
529+ return - ENOMEM ;
530+
531+ buf_ring -> el_size = sizeof (struct mhi_buf_info );
532+ buf_ring -> len = buf_ring -> el_size * buf_ring -> elements ;
533+ buf_ring -> base = vzalloc (buf_ring -> len );
534+
535+ if (!buf_ring -> base ) {
536+ mhi_free_coherent (mhi_cntrl , tre_ring -> alloc_size ,
537+ tre_ring -> pre_aligned , tre_ring -> dma_handle );
538+ return - ENOMEM ;
539+ }
540+
541+ tmp = chan_ctxt -> chcfg ;
542+ tmp &= ~CHAN_CTX_CHSTATE_MASK ;
543+ tmp |= (MHI_CH_STATE_ENABLED << CHAN_CTX_CHSTATE_SHIFT );
544+ chan_ctxt -> chcfg = tmp ;
545+
546+ chan_ctxt -> rbase = tre_ring -> iommu_base ;
547+ chan_ctxt -> rp = chan_ctxt -> wp = chan_ctxt -> rbase ;
548+ chan_ctxt -> rlen = tre_ring -> len ;
549+ tre_ring -> ctxt_wp = & chan_ctxt -> wp ;
550+
551+ tre_ring -> rp = tre_ring -> wp = tre_ring -> base ;
552+ buf_ring -> rp = buf_ring -> wp = buf_ring -> base ;
553+ mhi_chan -> db_cfg .db_mode = 1 ;
554+
555+ /* Update to all cores */
556+ smp_wmb ();
557+
558+ return 0 ;
559+ }
560+
494561static int parse_ev_cfg (struct mhi_controller * mhi_cntrl ,
495562 struct mhi_controller_config * config )
496563{
@@ -799,6 +866,14 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
799866 rwlock_init (& mhi_chan -> lock );
800867 }
801868
869+ if (mhi_cntrl -> bounce_buf ) {
870+ mhi_cntrl -> map_single = mhi_map_single_use_bb ;
871+ mhi_cntrl -> unmap_single = mhi_unmap_single_use_bb ;
872+ } else {
873+ mhi_cntrl -> map_single = mhi_map_single_no_bb ;
874+ mhi_cntrl -> unmap_single = mhi_unmap_single_no_bb ;
875+ }
876+
802877 /* Register controller with MHI bus */
803878 mhi_dev = mhi_alloc_device (mhi_cntrl );
804879 if (IS_ERR (mhi_dev )) {
@@ -969,20 +1044,33 @@ static int mhi_driver_probe(struct device *dev)
9691044 struct mhi_event * mhi_event ;
9701045 struct mhi_chan * ul_chan = mhi_dev -> ul_chan ;
9711046 struct mhi_chan * dl_chan = mhi_dev -> dl_chan ;
1047+ int ret ;
1048+
1049+ /* Bring device out of LPM */
1050+ ret = mhi_device_get_sync (mhi_dev );
1051+ if (ret )
1052+ return ret ;
1053+
1054+ ret = - EINVAL ;
9721055
9731056 if (ul_chan ) {
9741057 /*
9751058 * If channel supports LPM notifications then status_cb should
9761059 * be provided
9771060 */
9781061 if (ul_chan -> lpm_notify && !mhi_drv -> status_cb )
979- return - EINVAL ;
1062+ goto exit_probe ;
9801063
9811064 /* For non-offload channels then xfer_cb should be provided */
9821065 if (!ul_chan -> offload_ch && !mhi_drv -> ul_xfer_cb )
983- return - EINVAL ;
1066+ goto exit_probe ;
9841067
9851068 ul_chan -> xfer_cb = mhi_drv -> ul_xfer_cb ;
1069+ if (ul_chan -> auto_start ) {
1070+ ret = mhi_prepare_channel (mhi_cntrl , ul_chan );
1071+ if (ret )
1072+ goto exit_probe ;
1073+ }
9861074 }
9871075
9881076 if (dl_chan ) {
@@ -991,11 +1079,11 @@ static int mhi_driver_probe(struct device *dev)
9911079 * be provided
9921080 */
9931081 if (dl_chan -> lpm_notify && !mhi_drv -> status_cb )
994- return - EINVAL ;
1082+ goto exit_probe ;
9951083
9961084 /* For non-offload channels then xfer_cb should be provided */
9971085 if (!dl_chan -> offload_ch && !mhi_drv -> dl_xfer_cb )
998- return - EINVAL ;
1086+ goto exit_probe ;
9991087
10001088 mhi_event = & mhi_cntrl -> mhi_event [dl_chan -> er_index ];
10011089
@@ -1005,19 +1093,36 @@ static int mhi_driver_probe(struct device *dev)
10051093 * notify pending data
10061094 */
10071095 if (mhi_event -> cl_manage && !mhi_drv -> status_cb )
1008- return - EINVAL ;
1096+ goto exit_probe ;
10091097
10101098 dl_chan -> xfer_cb = mhi_drv -> dl_xfer_cb ;
10111099 }
10121100
10131101 /* Call the user provided probe function */
1014- return mhi_drv -> probe (mhi_dev , mhi_dev -> id );
1102+ ret = mhi_drv -> probe (mhi_dev , mhi_dev -> id );
1103+ if (ret )
1104+ goto exit_probe ;
1105+
1106+ if (dl_chan && dl_chan -> auto_start )
1107+ mhi_prepare_channel (mhi_cntrl , dl_chan );
1108+
1109+ mhi_device_put (mhi_dev );
1110+
1111+ return ret ;
1112+
1113+ exit_probe :
1114+ mhi_unprepare_from_transfer (mhi_dev );
1115+
1116+ mhi_device_put (mhi_dev );
1117+
1118+ return ret ;
10151119}
10161120
10171121static int mhi_driver_remove (struct device * dev )
10181122{
10191123 struct mhi_device * mhi_dev = to_mhi_device (dev );
10201124 struct mhi_driver * mhi_drv = to_mhi_driver (dev -> driver );
1125+ struct mhi_controller * mhi_cntrl = mhi_dev -> mhi_cntrl ;
10211126 struct mhi_chan * mhi_chan ;
10221127 enum mhi_ch_state ch_state [] = {
10231128 MHI_CH_STATE_DISABLED ,
@@ -1049,6 +1154,10 @@ static int mhi_driver_remove(struct device *dev)
10491154 mhi_chan -> ch_state = MHI_CH_STATE_SUSPENDED ;
10501155 write_unlock_irq (& mhi_chan -> lock );
10511156
1157+ /* Reset the non-offload channel */
1158+ if (!mhi_chan -> offload_ch )
1159+ mhi_reset_chan (mhi_cntrl , mhi_chan );
1160+
10521161 mutex_unlock (& mhi_chan -> mutex );
10531162 }
10541163
@@ -1063,11 +1172,20 @@ static int mhi_driver_remove(struct device *dev)
10631172
10641173 mutex_lock (& mhi_chan -> mutex );
10651174
1175+ if (ch_state [dir ] == MHI_CH_STATE_ENABLED &&
1176+ !mhi_chan -> offload_ch )
1177+ mhi_deinit_chan_ctxt (mhi_cntrl , mhi_chan );
1178+
10661179 mhi_chan -> ch_state = MHI_CH_STATE_DISABLED ;
10671180
10681181 mutex_unlock (& mhi_chan -> mutex );
10691182 }
10701183
1184+ read_lock_bh (& mhi_cntrl -> pm_lock );
1185+ while (mhi_dev -> dev_wake )
1186+ mhi_device_put (mhi_dev );
1187+ read_unlock_bh (& mhi_cntrl -> pm_lock );
1188+
10711189 return 0 ;
10721190}
10731191
0 commit comments