@@ -140,8 +140,9 @@ enum {
140140 * @name: unique channel name/identifier
141141 * @lcid: channel id, in local space
142142 * @rcid: channel id, in remote space
143- * @intent_lock: lock for protection of @liids
143+ * @intent_lock: lock for protection of @liids, @riids
144144 * @liids: idr of all local intents
145+ * @riids: idr of all remote intents
145146 * @intent_work: worker responsible for transmitting rx_done packets
146147 * @done_intents: list of intents that needs to be announced rx_done
147148 * @buf: receive buffer, for gathering fragments
@@ -166,6 +167,7 @@ struct glink_channel {
166167
167168 spinlock_t intent_lock ;
168169 struct idr liids ;
170+ struct idr riids ;
169171 struct work_struct intent_work ;
170172 struct list_head done_intents ;
171173
@@ -223,6 +225,7 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
223225 INIT_WORK (& channel -> intent_work , qcom_glink_rx_done_work );
224226
225227 idr_init (& channel -> liids );
228+ idr_init (& channel -> riids );
226229 kref_init (& channel -> refcount );
227230
228231 return channel ;
@@ -236,6 +239,7 @@ static void qcom_glink_channel_release(struct kref *ref)
236239
237240 spin_lock_irqsave (& channel -> intent_lock , flags );
238241 idr_destroy (& channel -> liids );
242+ idr_destroy (& channel -> riids );
239243 spin_unlock_irqrestore (& channel -> intent_lock , flags );
240244
241245 kfree (channel -> name );
@@ -807,6 +811,68 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
807811 return ret ;
808812}
809813
814+ static void qcom_glink_handle_intent (struct qcom_glink * glink ,
815+ unsigned int cid ,
816+ unsigned int count ,
817+ size_t avail )
818+ {
819+ struct glink_core_rx_intent * intent ;
820+ struct glink_channel * channel ;
821+ struct intent_pair {
822+ __le32 size ;
823+ __le32 iid ;
824+ };
825+
826+ struct {
827+ struct glink_msg msg ;
828+ struct intent_pair intents [];
829+ } __packed * msg ;
830+
831+ const size_t msglen = sizeof (* msg ) + sizeof (struct intent_pair ) * count ;
832+ int ret ;
833+ int i ;
834+ unsigned long flags ;
835+
836+ if (avail < msglen ) {
837+ dev_dbg (glink -> dev , "Not enough data in fifo\n" );
838+ return ;
839+ }
840+
841+ spin_lock_irqsave (& glink -> idr_lock , flags );
842+ channel = idr_find (& glink -> rcids , cid );
843+ spin_unlock_irqrestore (& glink -> idr_lock , flags );
844+ if (!channel ) {
845+ dev_err (glink -> dev , "intents for non-existing channel\n" );
846+ return ;
847+ }
848+
849+ msg = kmalloc (msglen , GFP_ATOMIC );
850+ if (!msg )
851+ return ;
852+
853+ qcom_glink_rx_peak (glink , msg , 0 , msglen );
854+
855+ for (i = 0 ; i < count ; ++ i ) {
856+ intent = kzalloc (sizeof (* intent ), GFP_ATOMIC );
857+ if (!intent )
858+ break ;
859+
860+ intent -> id = le32_to_cpu (msg -> intents [i ].iid );
861+ intent -> size = le32_to_cpu (msg -> intents [i ].size );
862+
863+ spin_lock_irqsave (& channel -> intent_lock , flags );
864+ ret = idr_alloc (& channel -> riids , intent ,
865+ intent -> id , intent -> id + 1 , GFP_ATOMIC );
866+ spin_unlock_irqrestore (& channel -> intent_lock , flags );
867+
868+ if (ret < 0 )
869+ dev_err (glink -> dev , "failed to store remote intent\n" );
870+ }
871+
872+ kfree (msg );
873+ qcom_glink_rx_advance (glink , ALIGN (msglen , 8 ));
874+ }
875+
810876static int qcom_glink_rx_open_ack (struct qcom_glink * glink , unsigned int lcid )
811877{
812878 struct glink_channel * channel ;
@@ -872,6 +938,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data)
872938
873939 ret = 0 ;
874940 break ;
941+ case RPM_CMD_INTENT :
942+ qcom_glink_handle_intent (glink , param1 , param2 , avail );
943+ break ;
875944 default :
876945 dev_err (glink -> dev , "unhandled rx cmd: %d\n" , cmd );
877946 ret = - EINVAL ;
0 commit comments