@@ -104,6 +104,7 @@ struct scmi_chan_info {
104
104
struct mbox_chan * chan ;
105
105
void __iomem * payload ;
106
106
struct device * dev ;
107
+ struct scmi_handle * handle ;
107
108
};
108
109
109
110
/**
@@ -115,7 +116,7 @@ struct scmi_chan_info {
115
116
* @version: SCMI revision information containing protocol version,
116
117
* implementation version and (sub-)vendor identification.
117
118
* @minfo: Message info
118
- * @tx_cinfo: Reference to SCMI channel information
119
+ * @tx_idr: IDR object to map protocol id to channel info pointer
119
120
* @protocols_imp: list of protocols implemented, currently maximum of
120
121
* MAX_PROTOCOLS_IMP elements allocated by the base protocol
121
122
* @node: list head
@@ -127,7 +128,7 @@ struct scmi_info {
127
128
struct scmi_revision_info version ;
128
129
struct scmi_handle handle ;
129
130
struct scmi_xfers_info minfo ;
130
- struct scmi_chan_info * tx_cinfo ;
131
+ struct idr tx_idr ;
131
132
u8 * protocols_imp ;
132
133
struct list_head node ;
133
134
int users ;
@@ -218,7 +219,7 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m)
218
219
struct scmi_xfer * xfer ;
219
220
struct scmi_chan_info * cinfo = client_to_scmi_chan_info (cl );
220
221
struct device * dev = cinfo -> dev ;
221
- struct scmi_info * info = dev_get_drvdata ( dev );
222
+ struct scmi_info * info = handle_to_scmi_info ( cinfo -> handle );
222
223
struct scmi_xfers_info * minfo = & info -> minfo ;
223
224
struct scmi_shared_mem __iomem * mem = cinfo -> payload ;
224
225
@@ -390,7 +391,11 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
390
391
int timeout ;
391
392
struct scmi_info * info = handle_to_scmi_info (handle );
392
393
struct device * dev = info -> dev ;
393
- struct scmi_chan_info * cinfo = info -> tx_cinfo ;
394
+ struct scmi_chan_info * cinfo ;
395
+
396
+ cinfo = idr_find (& info -> tx_idr , xfer -> hdr .protocol_id );
397
+ if (unlikely (!cinfo ))
398
+ return - EINVAL ;
394
399
395
400
ret = mbox_send_message (cinfo -> chan , xfer );
396
401
if (ret < 0 ) {
@@ -657,20 +662,26 @@ static int scmi_mailbox_check(struct device_node *np)
657
662
return of_parse_phandle_with_args (np , "mboxes" , "#mbox-cells" , 0 , & arg );
658
663
}
659
664
660
- static int scmi_mbox_free_channel (struct scmi_chan_info * cinfo )
665
+ static int scmi_mbox_free_channel (int id , void * p , void * data )
661
666
{
667
+ struct scmi_chan_info * cinfo = p ;
668
+ struct idr * idr = data ;
669
+
662
670
if (!IS_ERR_OR_NULL (cinfo -> chan )) {
663
671
mbox_free_channel (cinfo -> chan );
664
672
cinfo -> chan = NULL ;
665
673
}
666
674
675
+ idr_remove (idr , id );
676
+
667
677
return 0 ;
668
678
}
669
679
670
680
static int scmi_remove (struct platform_device * pdev )
671
681
{
672
682
int ret = 0 ;
673
683
struct scmi_info * info = platform_get_drvdata (pdev );
684
+ struct idr * idr = & info -> tx_idr ;
674
685
675
686
mutex_lock (& scmi_list_mutex );
676
687
if (info -> users )
@@ -679,28 +690,34 @@ static int scmi_remove(struct platform_device *pdev)
679
690
list_del (& info -> node );
680
691
mutex_unlock (& scmi_list_mutex );
681
692
682
- if (!ret )
693
+ if (!ret ) {
683
694
/* Safe to free channels since no more users */
684
- return scmi_mbox_free_channel (info -> tx_cinfo );
695
+ ret = idr_for_each (idr , scmi_mbox_free_channel , idr );
696
+ idr_destroy (& info -> tx_idr );
697
+ }
685
698
686
699
return ret ;
687
700
}
688
701
689
- static inline int scmi_mbox_chan_setup (struct scmi_info * info )
702
+ static inline int
703
+ scmi_mbox_chan_setup (struct scmi_info * info , struct device * dev , int prot_id )
690
704
{
691
705
int ret ;
692
706
struct resource res ;
693
707
resource_size_t size ;
694
- struct device * dev = info -> dev ;
695
708
struct device_node * shmem , * np = dev -> of_node ;
696
709
struct scmi_chan_info * cinfo ;
697
710
struct mbox_client * cl ;
698
711
712
+ if (scmi_mailbox_check (np )) {
713
+ cinfo = idr_find (& info -> tx_idr , SCMI_PROTOCOL_BASE );
714
+ goto idr_alloc ;
715
+ }
716
+
699
717
cinfo = devm_kzalloc (info -> dev , sizeof (* cinfo ), GFP_KERNEL );
700
718
if (!cinfo )
701
719
return - ENOMEM ;
702
720
703
- info -> tx_cinfo = cinfo ;
704
721
cinfo -> dev = dev ;
705
722
706
723
cl = & cinfo -> cl ;
@@ -734,6 +751,14 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info)
734
751
return ret ;
735
752
}
736
753
754
+ idr_alloc :
755
+ ret = idr_alloc (& info -> tx_idr , cinfo , prot_id , prot_id + 1 , GFP_KERNEL );
756
+ if (ret != prot_id ) {
757
+ dev_err (dev , "unable to allocate SCMI idr slot err %d\n" , ret );
758
+ return ret ;
759
+ }
760
+
761
+ cinfo -> handle = & info -> handle ;
737
762
return 0 ;
738
763
}
739
764
@@ -750,6 +775,11 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
750
775
return ;
751
776
}
752
777
778
+ if (scmi_mbox_chan_setup (info , & sdev -> dev , prot_id )) {
779
+ dev_err (& sdev -> dev , "failed to setup transport\n" );
780
+ scmi_device_destroy (sdev );
781
+ }
782
+
753
783
/* setup handle now as the transport is ready */
754
784
scmi_set_handle (sdev );
755
785
}
@@ -784,19 +814,19 @@ static int scmi_probe(struct platform_device *pdev)
784
814
return ret ;
785
815
786
816
platform_set_drvdata (pdev , info );
817
+ idr_init (& info -> tx_idr );
787
818
788
819
handle = & info -> handle ;
789
820
handle -> dev = info -> dev ;
790
821
handle -> version = & info -> version ;
791
822
792
- ret = scmi_mbox_chan_setup (info );
823
+ ret = scmi_mbox_chan_setup (info , dev , SCMI_PROTOCOL_BASE );
793
824
if (ret )
794
825
return ret ;
795
826
796
827
ret = scmi_base_protocol_init (handle );
797
828
if (ret ) {
798
829
dev_err (dev , "unable to communicate with SCMI(%d)\n" , ret );
799
- scmi_mbox_free_channel (info -> tx_cinfo );
800
830
return ret ;
801
831
}
802
832
0 commit comments