@@ -81,6 +81,7 @@ enum { CTB_SEND = 0, CTB_RECV = 1 };
8181
8282enum { CTB_OWNER_HOST = 0 };
8383
84+ static void ct_receive_tasklet_func (struct tasklet_struct * t );
8485static void ct_incoming_request_worker_func (struct work_struct * w );
8586
8687/**
@@ -95,6 +96,7 @@ void intel_guc_ct_init_early(struct intel_guc_ct *ct)
9596 INIT_LIST_HEAD (& ct -> requests .pending );
9697 INIT_LIST_HEAD (& ct -> requests .incoming );
9798 INIT_WORK (& ct -> requests .worker , ct_incoming_request_worker_func );
99+ tasklet_setup (& ct -> receive_tasklet , ct_receive_tasklet_func );
98100}
99101
100102static inline const char * guc_ct_buffer_type_to_str (u32 type )
@@ -244,6 +246,7 @@ void intel_guc_ct_fini(struct intel_guc_ct *ct)
244246{
245247 GEM_BUG_ON (ct -> enabled );
246248
249+ tasklet_kill (& ct -> receive_tasklet );
247250 i915_vma_unpin_and_release (& ct -> vma , I915_VMA_RELEASE_MAP );
248251 memset (ct , 0 , sizeof (* ct ));
249252}
@@ -651,7 +654,7 @@ static int ct_read(struct intel_guc_ct *ct, u32 *data)
651654 CT_DEBUG (ct , "received %*ph\n" , 4 * len , data );
652655
653656 desc -> head = head * 4 ;
654- return 0 ;
657+ return available - len ;
655658
656659corrupted :
657660 CT_ERROR (ct , "Corrupted descriptor addr=%#x head=%u tail=%u size=%u\n" ,
@@ -687,10 +690,10 @@ static int ct_handle_response(struct intel_guc_ct *ct, const u32 *msg)
687690 u32 status ;
688691 u32 datalen ;
689692 struct ct_request * req ;
693+ unsigned long flags ;
690694 bool found = false;
691695
692696 GEM_BUG_ON (!ct_header_is_response (header ));
693- GEM_BUG_ON (!in_irq ());
694697
695698 /* Response payload shall at least include fence and status */
696699 if (unlikely (len < 2 )) {
@@ -710,7 +713,7 @@ static int ct_handle_response(struct intel_guc_ct *ct, const u32 *msg)
710713
711714 CT_DEBUG (ct , "response fence %u status %#x\n" , fence , status );
712715
713- spin_lock (& ct -> requests .lock );
716+ spin_lock_irqsave (& ct -> requests .lock , flags );
714717 list_for_each_entry (req , & ct -> requests .pending , link ) {
715718 if (unlikely (fence != req -> fence )) {
716719 CT_DEBUG (ct , "request %u awaits response\n" ,
@@ -729,7 +732,7 @@ static int ct_handle_response(struct intel_guc_ct *ct, const u32 *msg)
729732 found = true;
730733 break ;
731734 }
732- spin_unlock (& ct -> requests .lock );
735+ spin_unlock_irqrestore (& ct -> requests .lock , flags );
733736
734737 if (!found )
735738 CT_ERROR (ct , "Unsolicited response %*ph\n" , msgsize , msg );
@@ -843,31 +846,55 @@ static int ct_handle_request(struct intel_guc_ct *ct, const u32 *msg)
843846 return 0 ;
844847}
845848
849+ static int ct_receive (struct intel_guc_ct * ct )
850+ {
851+ u32 msg [GUC_CT_MSG_LEN_MASK + 1 ]; /* one extra dw for the header */
852+ unsigned long flags ;
853+ int ret ;
854+
855+ spin_lock_irqsave (& ct -> ctbs .recv .lock , flags );
856+ ret = ct_read (ct , msg );
857+ spin_unlock_irqrestore (& ct -> ctbs .recv .lock , flags );
858+ if (ret < 0 )
859+ return ret ;
860+
861+ if (ct_header_is_response (msg [0 ]))
862+ ct_handle_response (ct , msg );
863+ else
864+ ct_handle_request (ct , msg );
865+
866+ return ret ;
867+ }
868+
869+ static void ct_try_receive_message (struct intel_guc_ct * ct )
870+ {
871+ int ret ;
872+
873+ if (GEM_WARN_ON (!ct -> enabled ))
874+ return ;
875+
876+ ret = ct_receive (ct );
877+ if (ret > 0 )
878+ tasklet_hi_schedule (& ct -> receive_tasklet );
879+ }
880+
881+ static void ct_receive_tasklet_func (struct tasklet_struct * t )
882+ {
883+ struct intel_guc_ct * ct = from_tasklet (ct , t , receive_tasklet );
884+
885+ ct_try_receive_message (ct );
886+ }
887+
846888/*
847889 * When we're communicating with the GuC over CT, GuC uses events
848890 * to notify us about new messages being posted on the RECV buffer.
849891 */
850892void intel_guc_ct_event_handler (struct intel_guc_ct * ct )
851893{
852- u32 msg [GUC_CT_MSG_LEN_MASK + 1 ]; /* one extra dw for the header */
853- unsigned long flags ;
854- int err = 0 ;
855-
856894 if (unlikely (!ct -> enabled )) {
857895 WARN (1 , "Unexpected GuC event received while CT disabled!\n" );
858896 return ;
859897 }
860898
861- do {
862- spin_lock_irqsave (& ct -> ctbs .recv .lock , flags );
863- err = ct_read (ct , msg );
864- spin_unlock_irqrestore (& ct -> ctbs .recv .lock , flags );
865- if (err )
866- break ;
867-
868- if (ct_header_is_response (msg [0 ]))
869- err = ct_handle_response (ct , msg );
870- else
871- err = ct_handle_request (ct , msg );
872- } while (!err );
899+ ct_try_receive_message (ct );
873900}
0 commit comments