3636 * The driver uses the Linux GPIO and interrupt framework to expose a virtual
3737 * GPIO for each outbound entry and a virtual interrupt controller for each
3838 * inbound entry.
39+ *
40+ * Driver supports two versions:
41+ * V1 - For processor that start after local host
42+ * V2 - For processor that start in early boot sequence
3943 */
4044
4145#define SMP2P_MAX_ENTRY 16
5054
5155#define ONE 1
5256#define TWO 2
57+ #define MAX_VERSION TWO
5358
5459/**
5560 * struct smp2p_smem_item - in memory communication structure
5661 * @magic: magic number
57- * @version: version - must be 1
62+ * @version: version
5863 * @features: features flag - currently unused
5964 * @local_pid: processor id of sending end
6065 * @remote_pid: processor id of receiving end
@@ -183,14 +188,23 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
183188static bool qcom_smp2p_check_ssr (struct qcom_smp2p * smp2p )
184189{
185190 struct smp2p_smem_item * in = smp2p -> in ;
191+ struct smp2p_entry * entry ;
186192 bool restart ;
187193
188194 if (!smp2p -> ssr_ack_enabled )
189195 return false;
190196
191197 restart = in -> flags & BIT (SMP2P_FLAGS_RESTART_DONE_BIT );
198+ restart = restart != smp2p -> ssr_ack ;
199+ if (restart && in -> version > ONE ) {
200+ list_for_each_entry (entry , & smp2p -> inbound , node ) {
201+ if (!entry -> value )
202+ continue ;
203+ entry -> last_value = 0 ;
204+ }
205+ }
192206
193- return restart != smp2p -> ssr_ack ;
207+ return restart ;
194208}
195209
196210static void qcom_smp2p_do_ssr_ack (struct qcom_smp2p * smp2p )
@@ -225,6 +239,20 @@ static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p)
225239 }
226240}
227241
242+ static int qcom_smp2p_in_version (struct qcom_smp2p * smp2p )
243+ {
244+ unsigned int smem_id = smp2p -> smem_items [SMP2P_INBOUND ];
245+ unsigned int pid = smp2p -> remote_pid ;
246+ struct smp2p_smem_item * in ;
247+ size_t size ;
248+
249+ in = qcom_smem_get (pid , smem_id , & size );
250+ if (IS_ERR (in ))
251+ return 0 ;
252+
253+ return in -> version ;
254+ }
255+
228256static void qcom_smp2p_start_in (struct qcom_smp2p * smp2p )
229257{
230258 unsigned int smem_id = smp2p -> smem_items [SMP2P_INBOUND ];
@@ -522,6 +550,7 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p)
522550 struct smp2p_smem_item * out ;
523551 unsigned smem_id = smp2p -> smem_items [SMP2P_OUTBOUND ];
524552 unsigned pid = smp2p -> remote_pid ;
553+ u8 in_version ;
525554 int ret ;
526555
527556 ret = qcom_smem_alloc (pid , smem_id , sizeof (* out ));
@@ -543,12 +572,18 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p)
543572 out -> valid_entries = 0 ;
544573 out -> features = SMP2P_ALL_FEATURES ;
545574
575+ in_version = qcom_smp2p_in_version (smp2p );
576+ if (in_version > MAX_VERSION ) {
577+ dev_err (smp2p -> dev , "Unsupported smp2p version\n" );
578+ return - EINVAL ;
579+ }
580+
546581 /*
547582 * Make sure the rest of the header is written before we validate the
548583 * item by writing a valid version number.
549584 */
550585 wmb ();
551- out -> version = 1 ;
586+ out -> version = ( in_version ) ? in_version : 1 ;
552587
553588 qcom_smp2p_kick (smp2p );
554589
0 commit comments