Lines Matching +full:rpm +full:- +full:msg +full:- +full:ram
1 // SPDX-License-Identifier: GPL-2.0+
4 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
21 * The Qualcomm shared memory system is an allocate-only heap structure that
45 * two regions are cached and non-cached memory respectively. Each region
49 * Items in the non-cached region are allocated from the start of the partition
51 * is hence the region between the cached and non-cached offsets. The header of
89 * struct smem_proc_comm - proc_comm communication struct (legacy)
101 * struct smem_global_entry - entry to reference smem items on the heap
117 * struct smem_header - header found in beginning of primary smem region
137 * struct smem_ptable_entry - one entry in the @smem_ptable list
157 * struct smem_ptable - partition table for the private partitions
175 * struct smem_partition_header - header of the partitions
199 * struct smem_private_entry - header of each item in the private partition
218 * struct smem_info - smem region info located after the table of contents
236 * struct smem_region - representation of a chunk of memory used for smem
248 * struct qcom_smem - device data for the smem device
277 return p + le32_to_cpu(phdr->offset_free_uncached); in phdr_to_last_uncached_entry()
285 return p + le32_to_cpu(phdr->size) - ALIGN(sizeof(*phdr), cacheline); in phdr_to_first_cached_entry()
292 return p + le32_to_cpu(phdr->offset_free_cached); in phdr_to_last_cached_entry()
308 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr) + in uncached_entry_next()
309 le32_to_cpu(e->size); in uncached_entry_next()
317 return p - le32_to_cpu(e->size) - ALIGN(sizeof(*e), cacheline); in cached_entry_next()
324 return p + sizeof(*e) + le16_to_cpu(e->padding_hdr); in uncached_entry_to_item()
331 return p - le32_to_cpu(e->size); in cached_entry_to_item()
351 if (hdr->canary != SMEM_PRIVATE_CANARY) { in qcom_smem_alloc_private()
352 dev_err(smem->dev, in qcom_smem_alloc_private()
354 phdr->host0, phdr->host1); in qcom_smem_alloc_private()
355 return -EINVAL; in qcom_smem_alloc_private()
358 if (le16_to_cpu(hdr->item) == item) in qcom_smem_alloc_private()
359 return -EEXIST; in qcom_smem_alloc_private()
367 dev_err(smem->dev, "Out of memory\n"); in qcom_smem_alloc_private()
368 return -ENOSPC; in qcom_smem_alloc_private()
371 hdr->canary = SMEM_PRIVATE_CANARY; in qcom_smem_alloc_private()
372 hdr->item = cpu_to_le16(item); in qcom_smem_alloc_private()
373 hdr->size = cpu_to_le32(ALIGN(size, 8)); in qcom_smem_alloc_private()
374 hdr->padding_data = cpu_to_le16(le32_to_cpu(hdr->size) - size); in qcom_smem_alloc_private()
375 hdr->padding_hdr = 0; in qcom_smem_alloc_private()
383 le32_add_cpu(&phdr->offset_free_uncached, alloc_size); in qcom_smem_alloc_private()
395 header = smem->regions[0].virt_base; in qcom_smem_alloc_global()
396 entry = &header->toc[item]; in qcom_smem_alloc_global()
397 if (entry->allocated) in qcom_smem_alloc_global()
398 return -EEXIST; in qcom_smem_alloc_global()
401 if (WARN_ON(size > le32_to_cpu(header->available))) in qcom_smem_alloc_global()
402 return -ENOMEM; in qcom_smem_alloc_global()
404 entry->offset = header->free_offset; in qcom_smem_alloc_global()
405 entry->size = cpu_to_le32(size); in qcom_smem_alloc_global()
413 entry->allocated = cpu_to_le32(1); in qcom_smem_alloc_global()
415 le32_add_cpu(&header->free_offset, size); in qcom_smem_alloc_global()
416 le32_add_cpu(&header->available, -size); in qcom_smem_alloc_global()
422 * qcom_smem_alloc() - allocate space for a smem item
423 * @host: remote processor id, or -1
436 return -EPROBE_DEFER; in qcom_smem_alloc()
439 dev_err(__smem->dev, in qcom_smem_alloc()
441 return -EINVAL; in qcom_smem_alloc()
444 if (WARN_ON(item >= __smem->item_count)) in qcom_smem_alloc()
445 return -EINVAL; in qcom_smem_alloc()
447 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) { in qcom_smem_alloc()
448 phdr = __smem->partitions[host]; in qcom_smem_alloc()
450 } else if (__smem->global_partition) { in qcom_smem_alloc()
451 phdr = __smem->global_partition; in qcom_smem_alloc()
470 header = smem->regions[0].virt_base; in qcom_smem_get_global()
471 entry = &header->toc[item]; in qcom_smem_get_global()
472 if (!entry->allocated) in qcom_smem_get_global()
473 return ERR_PTR(-ENXIO); in qcom_smem_get_global()
475 aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK; in qcom_smem_get_global()
477 for (i = 0; i < smem->num_regions; i++) { in qcom_smem_get_global()
478 area = &smem->regions[i]; in qcom_smem_get_global()
480 if (area->aux_base == aux_base || !aux_base) { in qcom_smem_get_global()
482 *size = le32_to_cpu(entry->size); in qcom_smem_get_global()
483 return area->virt_base + le32_to_cpu(entry->offset); in qcom_smem_get_global()
487 return ERR_PTR(-ENOENT); in qcom_smem_get_global()
502 if (e->canary != SMEM_PRIVATE_CANARY) in qcom_smem_get_private()
505 if (le16_to_cpu(e->item) == item) { in qcom_smem_get_private()
507 *size = le32_to_cpu(e->size) - in qcom_smem_get_private()
508 le16_to_cpu(e->padding_data); in qcom_smem_get_private()
522 if (e->canary != SMEM_PRIVATE_CANARY) in qcom_smem_get_private()
525 if (le16_to_cpu(e->item) == item) { in qcom_smem_get_private()
527 *size = le32_to_cpu(e->size) - in qcom_smem_get_private()
528 le16_to_cpu(e->padding_data); in qcom_smem_get_private()
536 return ERR_PTR(-ENOENT); in qcom_smem_get_private()
539 dev_err(smem->dev, "Found invalid canary in hosts %d:%d partition\n", in qcom_smem_get_private()
540 phdr->host0, phdr->host1); in qcom_smem_get_private()
542 return ERR_PTR(-EINVAL); in qcom_smem_get_private()
546 * qcom_smem_get() - resolve ptr of size of a smem item
547 * @host: the remote processor, or -1
558 void *ptr = ERR_PTR(-EPROBE_DEFER); in qcom_smem_get()
563 if (WARN_ON(item >= __smem->item_count)) in qcom_smem_get()
564 return ERR_PTR(-EINVAL); in qcom_smem_get()
566 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) { in qcom_smem_get()
567 phdr = __smem->partitions[host]; in qcom_smem_get()
568 cacheln = __smem->cacheline[host]; in qcom_smem_get()
570 } else if (__smem->global_partition) { in qcom_smem_get()
571 phdr = __smem->global_partition; in qcom_smem_get()
572 cacheln = __smem->global_cacheline; in qcom_smem_get()
583 * qcom_smem_get_free_space() - retrieve amount of free space in a partition
584 * @host: the remote processor identifying a partition, or -1
596 return -EPROBE_DEFER; in qcom_smem_get_free_space()
598 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) { in qcom_smem_get_free_space()
599 phdr = __smem->partitions[host]; in qcom_smem_get_free_space()
600 ret = le32_to_cpu(phdr->offset_free_cached) - in qcom_smem_get_free_space()
601 le32_to_cpu(phdr->offset_free_uncached); in qcom_smem_get_free_space()
602 } else if (__smem->global_partition) { in qcom_smem_get_free_space()
603 phdr = __smem->global_partition; in qcom_smem_get_free_space()
604 ret = le32_to_cpu(phdr->offset_free_cached) - in qcom_smem_get_free_space()
605 le32_to_cpu(phdr->offset_free_uncached); in qcom_smem_get_free_space()
607 header = __smem->regions[0].virt_base; in qcom_smem_get_free_space()
608 ret = le32_to_cpu(header->available); in qcom_smem_get_free_space()
619 header = smem->regions[0].virt_base; in qcom_smem_get_sbl_version()
620 versions = header->version; in qcom_smem_get_sbl_version()
630 ptable = smem->regions[0].virt_base + smem->regions[0].size - SZ_4K; in qcom_smem_get_ptable()
631 if (memcmp(ptable->magic, SMEM_PTABLE_MAGIC, sizeof(ptable->magic))) in qcom_smem_get_ptable()
632 return ERR_PTR(-ENOENT); in qcom_smem_get_ptable()
634 version = le32_to_cpu(ptable->version); in qcom_smem_get_ptable()
636 dev_err(smem->dev, in qcom_smem_get_ptable()
638 return ERR_PTR(-EINVAL); in qcom_smem_get_ptable()
652 info = (struct smem_info *)&ptable->entry[ptable->num_entries]; in qcom_smem_get_item_count()
653 if (memcmp(info->magic, SMEM_INFO_MAGIC, sizeof(info->magic))) in qcom_smem_get_item_count()
656 return le16_to_cpu(info->num_items); in qcom_smem_get_item_count()
671 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { in qcom_smem_set_global_partition()
672 entry = &ptable->entry[i]; in qcom_smem_set_global_partition()
673 host0 = le16_to_cpu(entry->host0); in qcom_smem_set_global_partition()
674 host1 = le16_to_cpu(entry->host1); in qcom_smem_set_global_partition()
681 dev_err(smem->dev, "Missing entry for global partition\n"); in qcom_smem_set_global_partition()
682 return -EINVAL; in qcom_smem_set_global_partition()
685 if (!le32_to_cpu(entry->offset) || !le32_to_cpu(entry->size)) { in qcom_smem_set_global_partition()
686 dev_err(smem->dev, "Invalid entry for global partition\n"); in qcom_smem_set_global_partition()
687 return -EINVAL; in qcom_smem_set_global_partition()
690 if (smem->global_partition) { in qcom_smem_set_global_partition()
691 dev_err(smem->dev, "Already found the global partition\n"); in qcom_smem_set_global_partition()
692 return -EINVAL; in qcom_smem_set_global_partition()
695 header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); in qcom_smem_set_global_partition()
696 host0 = le16_to_cpu(header->host0); in qcom_smem_set_global_partition()
697 host1 = le16_to_cpu(header->host1); in qcom_smem_set_global_partition()
699 if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { in qcom_smem_set_global_partition()
700 dev_err(smem->dev, "Global partition has invalid magic\n"); in qcom_smem_set_global_partition()
701 return -EINVAL; in qcom_smem_set_global_partition()
705 dev_err(smem->dev, "Global partition hosts are invalid\n"); in qcom_smem_set_global_partition()
706 return -EINVAL; in qcom_smem_set_global_partition()
709 if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) { in qcom_smem_set_global_partition()
710 dev_err(smem->dev, "Global partition has invalid size\n"); in qcom_smem_set_global_partition()
711 return -EINVAL; in qcom_smem_set_global_partition()
714 size = le32_to_cpu(header->offset_free_uncached); in qcom_smem_set_global_partition()
715 if (size > le32_to_cpu(header->size)) { in qcom_smem_set_global_partition()
716 dev_err(smem->dev, in qcom_smem_set_global_partition()
718 return -EINVAL; in qcom_smem_set_global_partition()
721 smem->global_partition = header; in qcom_smem_set_global_partition()
722 smem->global_cacheline = le32_to_cpu(entry->cacheline); in qcom_smem_set_global_partition()
741 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { in qcom_smem_enumerate_partitions()
742 entry = &ptable->entry[i]; in qcom_smem_enumerate_partitions()
743 host0 = le16_to_cpu(entry->host0); in qcom_smem_enumerate_partitions()
744 host1 = le16_to_cpu(entry->host1); in qcom_smem_enumerate_partitions()
749 if (!le32_to_cpu(entry->offset)) in qcom_smem_enumerate_partitions()
752 if (!le32_to_cpu(entry->size)) in qcom_smem_enumerate_partitions()
761 dev_err(smem->dev, in qcom_smem_enumerate_partitions()
764 return -EINVAL; in qcom_smem_enumerate_partitions()
767 if (smem->partitions[remote_host]) { in qcom_smem_enumerate_partitions()
768 dev_err(smem->dev, in qcom_smem_enumerate_partitions()
771 return -EINVAL; in qcom_smem_enumerate_partitions()
774 header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); in qcom_smem_enumerate_partitions()
775 host0 = le16_to_cpu(header->host0); in qcom_smem_enumerate_partitions()
776 host1 = le16_to_cpu(header->host1); in qcom_smem_enumerate_partitions()
778 if (memcmp(header->magic, SMEM_PART_MAGIC, in qcom_smem_enumerate_partitions()
779 sizeof(header->magic))) { in qcom_smem_enumerate_partitions()
780 dev_err(smem->dev, in qcom_smem_enumerate_partitions()
782 return -EINVAL; in qcom_smem_enumerate_partitions()
786 dev_err(smem->dev, in qcom_smem_enumerate_partitions()
788 return -EINVAL; in qcom_smem_enumerate_partitions()
792 dev_err(smem->dev, in qcom_smem_enumerate_partitions()
794 return -EINVAL; in qcom_smem_enumerate_partitions()
797 if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) { in qcom_smem_enumerate_partitions()
798 dev_err(smem->dev, in qcom_smem_enumerate_partitions()
800 return -EINVAL; in qcom_smem_enumerate_partitions()
803 if (le32_to_cpu(header->offset_free_uncached) > le32_to_cpu(header->size)) { in qcom_smem_enumerate_partitions()
804 dev_err(smem->dev, in qcom_smem_enumerate_partitions()
806 return -EINVAL; in qcom_smem_enumerate_partitions()
809 smem->partitions[remote_host] = header; in qcom_smem_enumerate_partitions()
810 smem->cacheline[remote_host] = le32_to_cpu(entry->cacheline); in qcom_smem_enumerate_partitions()
823 ret = fdtdec_lookup_phandle(gd->fdt_blob, node, name); in qcom_smem_map_memory()
826 return -EINVAL; in qcom_smem_map_memory()
829 ret = fdt_get_resource(gd->fdt_blob, ret, "reg", 0, &r); in qcom_smem_map_memory()
833 smem->regions[i].aux_base = (u32)r.start; in qcom_smem_map_memory()
834 smem->regions[i].size = fdt_resource_size(&r); in qcom_smem_map_memory()
835 smem->regions[i].virt_base = devm_ioremap(dev, r.start, fdt_resource_size(&r)); in qcom_smem_map_memory()
836 if (!smem->regions[i].virt_base) in qcom_smem_map_memory()
837 return -ENOMEM; in qcom_smem_map_memory()
853 if (fdtdec_lookup_phandle(gd->fdt_blob, node, "qcomrpm-msg-ram") >= 0) in qcom_smem_probe()
859 return -ENOMEM; in qcom_smem_probe()
861 smem->dev = dev; in qcom_smem_probe()
862 smem->num_regions = num_regions; in qcom_smem_probe()
864 ret = qcom_smem_map_memory(smem, dev, "memory-region", 0); in qcom_smem_probe()
870 "qcom,rpm-msg-ram", 1); in qcom_smem_probe()
875 header = smem->regions[0].virt_base; in qcom_smem_probe()
876 if (le32_to_cpu(header->initialized) != 1 || in qcom_smem_probe()
877 le32_to_cpu(header->reserved)) { in qcom_smem_probe()
878 dev_err(&pdev->dev, "SMEM is not initialized by SBL\n"); in qcom_smem_probe()
879 return -EINVAL; in qcom_smem_probe()
888 smem->item_count = qcom_smem_get_item_count(smem); in qcom_smem_probe()
891 smem->item_count = SMEM_ITEM_COUNT; in qcom_smem_probe()
895 return -EINVAL; in qcom_smem_probe()
899 if (ret < 0 && ret != -ENOENT) in qcom_smem_probe()