@@ -162,7 +162,7 @@ struct glink_channel {
162162 spinlock_t intent_lock ;
163163 struct idr liids ;
164164
165- void * buf ;
165+ struct glink_core_rx_intent * buf ;
166166 int buf_offset ;
167167 int buf_size ;
168168
@@ -614,6 +614,7 @@ static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra)
614614
615615static int qcom_glink_rx_data (struct qcom_glink * glink , size_t avail )
616616{
617+ struct glink_core_rx_intent * intent ;
617618 struct glink_channel * channel ;
618619 struct {
619620 struct glink_msg msg ;
@@ -623,6 +624,8 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
623624 unsigned int chunk_size ;
624625 unsigned int left_size ;
625626 unsigned int rcid ;
627+ unsigned int liid ;
628+ int ret = 0 ;
626629 unsigned long flags ;
627630
628631 if (avail < sizeof (hdr )) {
@@ -650,56 +653,78 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
650653 dev_dbg (glink -> dev , "Data on non-existing channel\n" );
651654
652655 /* Drop the message */
653- qcom_glink_rx_advance (glink ,
654- ALIGN (sizeof (hdr ) + chunk_size , 8 ));
655- return 0 ;
656+ goto advance_rx ;
656657 }
657658
658- /* Might have an ongoing, fragmented, message to append */
659- if (!channel -> buf ) {
660- channel -> buf = kmalloc (chunk_size + left_size , GFP_ATOMIC );
661- if (!channel -> buf )
662- return - ENOMEM ;
659+ if (glink -> intentless ) {
660+ /* Might have an ongoing, fragmented, message to append */
661+ if (!channel -> buf ) {
662+ intent = kzalloc (sizeof (* intent ), GFP_ATOMIC );
663+ if (!intent )
664+ return - ENOMEM ;
665+
666+ intent -> data = kmalloc (chunk_size + left_size ,
667+ GFP_ATOMIC );
668+ if (!intent -> data ) {
669+ kfree (intent );
670+ return - ENOMEM ;
671+ }
672+
673+ intent -> id = 0xbabababa ;
674+ intent -> size = chunk_size + left_size ;
675+ intent -> offset = 0 ;
676+
677+ channel -> buf = intent ;
678+ } else {
679+ intent = channel -> buf ;
680+ }
681+ } else {
682+ liid = le32_to_cpu (hdr .msg .param2 );
663683
664- channel -> buf_size = chunk_size + left_size ;
665- channel -> buf_offset = 0 ;
666- }
684+ spin_lock_irqsave ( & channel -> intent_lock , flags ) ;
685+ intent = idr_find ( & channel -> liids , liid ) ;
686+ spin_unlock_irqrestore ( & channel -> intent_lock , flags );
667687
668- qcom_glink_rx_advance (glink , sizeof (hdr ));
688+ if (!intent ) {
689+ dev_err (glink -> dev ,
690+ "no intent found for channel %s intent %d" ,
691+ channel -> name , liid );
692+ goto advance_rx ;
693+ }
694+ }
669695
670- if (channel -> buf_size - channel -> buf_offset < chunk_size ) {
671- dev_err (glink -> dev , "Insufficient space in input buffer \n" );
696+ if (intent -> size - intent -> offset < chunk_size ) {
697+ dev_err (glink -> dev , "Insufficient space in intent \n" );
672698
673699 /* The packet header lied, drop payload */
674- qcom_glink_rx_advance (glink , chunk_size );
675- return - ENOMEM ;
700+ goto advance_rx ;
676701 }
677702
678- qcom_glink_rx_peak (glink , channel -> buf + channel -> buf_offset ,
703+ qcom_glink_rx_advance (glink , ALIGN (sizeof (hdr ), 8 ));
704+ qcom_glink_rx_peak (glink , intent -> data + intent -> offset ,
679705 chunk_size );
680- channel -> buf_offset += chunk_size ;
706+ intent -> offset += chunk_size ;
681707
682708 /* Handle message when no fragments remain to be received */
683709 if (!left_size ) {
684710 spin_lock (& channel -> recv_lock );
685711 if (channel -> ept .cb ) {
686712 channel -> ept .cb (channel -> ept .rpdev ,
687- channel -> buf ,
688- channel -> buf_offset ,
713+ intent -> data ,
714+ intent -> offset ,
689715 channel -> ept .priv ,
690716 RPMSG_ADDR_ANY );
691717 }
692718 spin_unlock (& channel -> recv_lock );
693719
694- kfree ( channel -> buf ) ;
720+ intent -> offset = 0 ;
695721 channel -> buf = NULL ;
696- channel -> buf_size = 0 ;
697722 }
698723
699- /* Each message starts at 8 byte aligned address */
724+ advance_rx :
700725 qcom_glink_rx_advance (glink , ALIGN (chunk_size , 8 ));
701726
702- return 0 ;
727+ return ret ;
703728}
704729
705730static int qcom_glink_rx_open_ack (struct qcom_glink * glink , unsigned int lcid )
0 commit comments