@@ -222,6 +222,24 @@ struct smem_private_entry {
222222};
223223#define SMEM_PRIVATE_CANARY 0xa5a5
224224
225+ /**
226+ * struct smem_info - smem region info located after the table of contents
227+ * @magic: magic number, must be SMEM_INFO_MAGIC
228+ * @size: size of the smem region
229+ * @base_addr: base address of the smem region
230+ * @reserved: for now reserved entry
231+ * @num_items: highest accepted item number
232+ */
233+ struct smem_info {
234+ u8 magic [4 ];
235+ __le32 size ;
236+ __le32 base_addr ;
237+ __le32 reserved ;
238+ __le16 num_items ;
239+ };
240+
241+ static const u8 SMEM_INFO_MAGIC [] = { 0x53 , 0x49 , 0x49 , 0x49 }; /* SIII */
242+
225243/**
226244 * struct smem_region - representation of a chunk of memory used for smem
227245 * @aux_base: identifier of aux_mem base
@@ -243,6 +261,7 @@ struct smem_region {
243261 * @partitions: list of pointers to partitions affecting the current
244262 * processor/host
245263 * @cacheline: list of cacheline sizes for each host
264+ * @item_count: max accepted item number
246265 * @num_regions: number of @regions
247266 * @regions: list of the memory regions defining the shared memory
248267 */
@@ -255,6 +274,7 @@ struct qcom_smem {
255274 size_t global_cacheline ;
256275 struct smem_partition_header * partitions [SMEM_HOST_COUNT ];
257276 size_t cacheline [SMEM_HOST_COUNT ];
277+ u32 item_count ;
258278
259279 unsigned num_regions ;
260280 struct smem_region regions [0 ];
@@ -386,9 +406,6 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
386406 struct smem_global_entry * entry ;
387407 struct smem_header * header ;
388408
389- if (WARN_ON (item >= SMEM_ITEM_COUNT ))
390- return - EINVAL ;
391-
392409 header = smem -> regions [0 ].virt_base ;
393410 entry = & header -> toc [item ];
394411 if (entry -> allocated )
@@ -439,6 +456,9 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
439456 return - EINVAL ;
440457 }
441458
459+ if (WARN_ON (item >= __smem -> item_count ))
460+ return - EINVAL ;
461+
442462 ret = hwspin_lock_timeout_irqsave (__smem -> hwlock ,
443463 HWSPINLOCK_TIMEOUT ,
444464 & flags );
@@ -471,9 +491,6 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
471491 u32 aux_base ;
472492 unsigned i ;
473493
474- if (WARN_ON (item >= SMEM_ITEM_COUNT ))
475- return ERR_PTR (- EINVAL );
476-
477494 header = smem -> regions [0 ].virt_base ;
478495 entry = & header -> toc [item ];
479496 if (!entry -> allocated )
@@ -569,6 +586,9 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
569586 if (!__smem )
570587 return ptr ;
571588
589+ if (WARN_ON (item >= __smem -> item_count ))
590+ return ERR_PTR (- EINVAL );
591+
572592 ret = hwspin_lock_timeout_irqsave (__smem -> hwlock ,
573593 HWSPINLOCK_TIMEOUT ,
574594 & flags );
@@ -656,6 +676,22 @@ static struct smem_ptable *qcom_smem_get_ptable(struct qcom_smem *smem)
656676 return ptable ;
657677}
658678
679+ static u32 qcom_smem_get_item_count (struct qcom_smem * smem )
680+ {
681+ struct smem_ptable * ptable ;
682+ struct smem_info * info ;
683+
684+ ptable = qcom_smem_get_ptable (smem );
685+ if (IS_ERR_OR_NULL (ptable ))
686+ return SMEM_ITEM_COUNT ;
687+
688+ info = (struct smem_info * )& ptable -> entry [ptable -> num_entries ];
689+ if (memcmp (info -> magic , SMEM_INFO_MAGIC , sizeof (info -> magic )))
690+ return SMEM_ITEM_COUNT ;
691+
692+ return le16_to_cpu (info -> num_items );
693+ }
694+
659695static int qcom_smem_set_global_partition (struct qcom_smem * smem )
660696{
661697 struct smem_partition_header * header ;
@@ -883,7 +919,10 @@ static int qcom_smem_probe(struct platform_device *pdev)
883919 ret = qcom_smem_set_global_partition (smem );
884920 if (ret < 0 )
885921 return ret ;
922+ smem -> item_count = qcom_smem_get_item_count (smem );
923+ break ;
886924 case SMEM_GLOBAL_HEAP_VERSION :
925+ smem -> item_count = SMEM_ITEM_COUNT ;
887926 break ;
888927 default :
889928 dev_err (& pdev -> dev , "Unsupported SMEM version 0x%x\n" , version );
0 commit comments