Loading drivers/soc/qcom/msm_smem.c +97 −42 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -83,6 +83,7 @@ static int smem_module_inited; static RAW_NOTIFIER_HEAD(smem_module_init_notifier_list); static DEFINE_MUTEX(smem_module_init_notifier_lock); static bool probe_done; uint32_t smem_max_items; /* smem security feature components */ #define SMEM_TOC_IDENTIFIER 0x434f5424 /* "$TOC" */ Loading Loading @@ -138,6 +139,11 @@ struct smem_partition_info { }; static struct smem_partition_info partitions[NUM_SMEM_SUBSYSTEMS]; #define SMEM_COMM_PART_VERSION 0x000C #define SMEM_COMM_HOST 0xFFFE static bool use_comm_partition; static struct smem_partition_info comm_partition; /* end smem security feature components */ /* Identifier for the SMEM target info struct. */ Loading @@ -148,6 +154,7 @@ struct smem_targ_info_type { uint32_t identifier; uint32_t size; phys_addr_t phys_base_addr; uint32_t max_items; }; struct restart_notifier_block { Loading Loading @@ -311,7 +318,7 @@ static void *__smem_get_entry_nonsecure(unsigned int id, unsigned int *size, if (!skip_init_check && !smem_initialized_check()) return ret; if (id >= SMEM_NUM_ITEMS) if (id >= smem_max_items) return ret; if (use_spinlocks) { Loading Loading @@ -373,7 +380,7 @@ static void *__smem_get_entry_secure(unsigned int id, if (!skip_init_check && !smem_initialized_check()) return NULL; if (id >= SMEM_NUM_ITEMS) { if (id >= smem_max_items) { SMEM_INFO("%s: invalid id %d\n", __func__, id); return NULL; } Loading @@ -384,12 +391,18 @@ static void *__smem_get_entry_secure(unsigned int id, return NULL; } if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) return __smem_get_entry_nonsecure(id, size, skip_init_check, use_rspinlock); if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) { if (use_comm_partition) { partition_num = comm_partition.partition_num; hdr = smem_areas[0].virt_addr + comm_partition.offset; } else { return __smem_get_entry_nonsecure(id, size, skip_init_check, use_rspinlock); } } else { partition_num = partitions[to_proc].partition_num; hdr = smem_areas[0].virt_addr + partitions[to_proc].offset; } if (unlikely(!spinlocks_initialized)) { rc = init_smem_remote_spinlock(); if (unlikely(rc)) { Loading Loading @@ -614,8 +627,19 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in, uint32_t partition_num; void *ret = NULL; if (to_proc == SMEM_COMM_HOST) { hdr = smem_base + comm_partition.offset; partition_num = comm_partition.partition_num; size_cacheline = comm_partition.size_cacheline; } else if (to_proc < NUM_SMEM_SUBSYSTEMS) { hdr = smem_base + partitions[to_proc].offset; partition_num = partitions[to_proc].partition_num; size_cacheline = partitions[to_proc].size_cacheline; } else { SMEM_INFO("%s: invalid to_proc %u for id %u\n", __func__, to_proc, id); return NULL; } if (hdr->identifier != SMEM_PART_HDR_IDENTIFIER) { LOG_ERR( Loading @@ -627,7 +651,6 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in, BUG(); } size_cacheline = partitions[to_proc].size_cacheline; free_space = hdr->offset_free_cached - hdr->offset_free_uncached; Loading Loading @@ -719,7 +742,7 @@ void *smem_alloc(unsigned int id, unsigned int size_in, unsigned int to_proc, if (!smem_initialized_check()) return NULL; if (id >= SMEM_NUM_ITEMS) { if (id >= smem_max_items) { SMEM_INFO("%s: invalid id %u\n", __func__, id); return NULL; } Loading Loading @@ -761,11 +784,16 @@ void *smem_alloc(unsigned int id, unsigned int size_in, unsigned int to_proc, if (id > SMEM_FIXED_ITEM_LAST) { SMEM_INFO("%s: allocating %u size %u to_proc %u flags %u\n", __func__, id, size_in, to_proc, flags); if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) ret = alloc_item_nonsecure(id, a_size_in); if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) { if (use_comm_partition) ret = alloc_item_secure(id, size_in, SMEM_COMM_HOST, flags); else ret = alloc_item_nonsecure(id, a_size_in); } else { ret = alloc_item_secure(id, size_in, to_proc, flags); } } else { SMEM_INFO("%s: attempted to allocate non-dynamic item %u\n", __func__, id); Loading Loading @@ -892,14 +920,18 @@ EXPORT_SYMBOL(smem_get_free_space); unsigned int smem_get_version(unsigned int idx) { int *version_array; struct smem_shared *smem = smem_ram_base; if (idx > 32) { pr_err("%s: invalid idx:%d\n", __func__, idx); return 0; } version_array = __smem_find(SMEM_VERSION_INFO, SMEM_VERSION_INFO_SIZE, true); if (use_comm_partition) version_array = smem->version; else version_array = __smem_find(SMEM_VERSION_INFO, SMEM_VERSION_INFO_SIZE, true); if (version_array == NULL) return 0; Loading Loading @@ -947,6 +979,7 @@ bool smem_initialized_check(void) static int is_inited; unsigned long flags; struct smem_shared *smem; unsigned int ver; if (likely(checked)) { if (unlikely(!is_inited)) Loading Loading @@ -975,8 +1008,12 @@ bool smem_initialized_check(void) * structures. Without the extra configuration data, the SMEM driver * cannot be properly initialized. */ if (smem_get_version(MODEM_SBL_VERSION_INDEX) != SMEM_VERSION << 16) { pr_err("%s: SBL version not correct\n", __func__); ver = smem->version[MODEM_SBL_VERSION_INDEX]; if (ver == SMEM_COMM_PART_VERSION << 16) { use_comm_partition = true; } else if (ver != SMEM_VERSION << 16) { pr_err("%s: SBL version not correct 0x%x\n", __func__, smem->version[7]); goto failed; } Loading Loading @@ -1122,6 +1159,7 @@ static void smem_init_security_partition(struct smem_toc_entry *entry, { uint16_t remote_host; struct smem_partition_header *hdr; bool is_comm_partition = false; if (!entry->offset) { SMEM_INFO("Skipping smem partition %d - bad offset\n", num); Loading @@ -1136,30 +1174,37 @@ static void smem_init_security_partition(struct smem_toc_entry *entry, return; } if (entry->host0 == SMEM_COMM_HOST && entry->host1 == SMEM_COMM_HOST) is_comm_partition = true; if (!is_comm_partition) { if (entry->host0 == SMEM_APPS) remote_host = entry->host1; else remote_host = entry->host0; if (remote_host >= NUM_SMEM_SUBSYSTEMS) { SMEM_INFO("Skipping smem partition %d - bad remote:%d\n", num, remote_host); SMEM_INFO( "Skipping smem partition %d - bad remote:%d\n", num, remote_host); return; } if (partitions[remote_host].offset) { SMEM_INFO("Skipping smem partition %d - duplicate of %d\n", num, partitions[remote_host].partition_num); SMEM_INFO( "Skipping smem partition %d - duplicate of %d\n", num, partitions[remote_host].partition_num); return; } hdr = smem_areas[0].virt_addr + entry->offset; if (entry->host0 != SMEM_APPS && entry->host1 != SMEM_APPS) { SMEM_INFO( "Non-APSS Partition %d offset:%x host0:%d host1:%d\n", num, entry->offset, entry->host0, entry->host1); return; } } hdr = smem_areas[0].virt_addr + entry->offset; if (hdr->identifier != SMEM_PART_HDR_IDENTIFIER) { LOG_ERR("Smem partition %d hdr magic is bad\n", num); Loading @@ -1177,6 +1222,14 @@ static void smem_init_security_partition(struct smem_toc_entry *entry, LOG_ERR("Smem partition %d cached heap exceeds size\n", num); BUG(); } if (hdr->host0 == SMEM_COMM_HOST && hdr->host1 == SMEM_COMM_HOST) { comm_partition.partition_num = num; comm_partition.offset = entry->offset; comm_partition.size_cacheline = entry->size_cacheline; SMEM_INFO("Common Partition %d offset:%x\n", num, entry->offset); return; } if (hdr->host0 != SMEM_APPS && hdr->host1 != SMEM_APPS) { LOG_ERR("Smem partition %d hosts don't match TOC\n", num); BUG(); Loading Loading @@ -1254,6 +1307,8 @@ static int smem_init_target_info(phys_addr_t info_addr, resource_size_t size) } smem_ram_phys = smem_targ_info->phys_base_addr; smem_ram_size = smem_targ_info->size; if (smem_targ_info->max_items) smem_max_items = smem_targ_info->max_items; iounmap(smem_targ_info_addr); return 0; } Loading Loading @@ -1490,7 +1545,7 @@ int __init msm_smem_init(void) return 0; registered = true; smem_max_items = SMEM_NUM_ITEMS; smem_ipc_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smem", 0); if (!smem_ipc_log_ctx) { pr_err("%s: unable to create logging context\n", __func__); Loading drivers/soc/qcom/smem_debug.c +4 −5 Original line number Diff line number Diff line /* arch/arm/mach-msm/smem_debug.c * * Copyright (C) 2007 Google, Inc. * Copyright (c) 2009-2013,2016 The Linux Foundation. All rights reserved. * Copyright (c) 2009-2013,2016-2017 The Linux Foundation. All rights reserved. * Author: Brian Swetland <swetland@google.com> * * This software is licensed under the terms of the GNU General Public Loading Loading @@ -53,7 +53,7 @@ static void debug_read_mem(struct seq_file *s) heap_info->free_offset, heap_info->heap_remaining); for (n = 0; n < SMEM_NUM_ITEMS; n++) { for (n = 0; n < smem_max_items; n++) { if (toc[n].allocated == 0) continue; seq_printf(s, "%04d: offset %08x size %08x\n", Loading @@ -67,9 +67,8 @@ static void debug_read_smem_version(struct seq_file *s) for (n = 0; n < 32; n++) { version = smem_get_version(n); seq_printf(s, "entry %d: smem = %d proc_comm = %d\n", n, version >> 16, version & 0xffff); seq_printf(s, "entry %d:%x smem = %d proc_comm = %d\n", n, version, version >> 16, version & 0xffff); } } Loading drivers/soc/qcom/smem_private.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2013,2016 The Linux Foundation. All rights reserved. /* Copyright (c) 2013,2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -18,6 +18,7 @@ #define SMD_HEAP_SIZE 512 extern uint32_t smem_max_items; struct smem_heap_info { unsigned int initialized; Loading Loading
drivers/soc/qcom/msm_smem.c +97 −42 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -83,6 +83,7 @@ static int smem_module_inited; static RAW_NOTIFIER_HEAD(smem_module_init_notifier_list); static DEFINE_MUTEX(smem_module_init_notifier_lock); static bool probe_done; uint32_t smem_max_items; /* smem security feature components */ #define SMEM_TOC_IDENTIFIER 0x434f5424 /* "$TOC" */ Loading Loading @@ -138,6 +139,11 @@ struct smem_partition_info { }; static struct smem_partition_info partitions[NUM_SMEM_SUBSYSTEMS]; #define SMEM_COMM_PART_VERSION 0x000C #define SMEM_COMM_HOST 0xFFFE static bool use_comm_partition; static struct smem_partition_info comm_partition; /* end smem security feature components */ /* Identifier for the SMEM target info struct. */ Loading @@ -148,6 +154,7 @@ struct smem_targ_info_type { uint32_t identifier; uint32_t size; phys_addr_t phys_base_addr; uint32_t max_items; }; struct restart_notifier_block { Loading Loading @@ -311,7 +318,7 @@ static void *__smem_get_entry_nonsecure(unsigned int id, unsigned int *size, if (!skip_init_check && !smem_initialized_check()) return ret; if (id >= SMEM_NUM_ITEMS) if (id >= smem_max_items) return ret; if (use_spinlocks) { Loading Loading @@ -373,7 +380,7 @@ static void *__smem_get_entry_secure(unsigned int id, if (!skip_init_check && !smem_initialized_check()) return NULL; if (id >= SMEM_NUM_ITEMS) { if (id >= smem_max_items) { SMEM_INFO("%s: invalid id %d\n", __func__, id); return NULL; } Loading @@ -384,12 +391,18 @@ static void *__smem_get_entry_secure(unsigned int id, return NULL; } if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) return __smem_get_entry_nonsecure(id, size, skip_init_check, use_rspinlock); if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) { if (use_comm_partition) { partition_num = comm_partition.partition_num; hdr = smem_areas[0].virt_addr + comm_partition.offset; } else { return __smem_get_entry_nonsecure(id, size, skip_init_check, use_rspinlock); } } else { partition_num = partitions[to_proc].partition_num; hdr = smem_areas[0].virt_addr + partitions[to_proc].offset; } if (unlikely(!spinlocks_initialized)) { rc = init_smem_remote_spinlock(); if (unlikely(rc)) { Loading Loading @@ -614,8 +627,19 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in, uint32_t partition_num; void *ret = NULL; if (to_proc == SMEM_COMM_HOST) { hdr = smem_base + comm_partition.offset; partition_num = comm_partition.partition_num; size_cacheline = comm_partition.size_cacheline; } else if (to_proc < NUM_SMEM_SUBSYSTEMS) { hdr = smem_base + partitions[to_proc].offset; partition_num = partitions[to_proc].partition_num; size_cacheline = partitions[to_proc].size_cacheline; } else { SMEM_INFO("%s: invalid to_proc %u for id %u\n", __func__, to_proc, id); return NULL; } if (hdr->identifier != SMEM_PART_HDR_IDENTIFIER) { LOG_ERR( Loading @@ -627,7 +651,6 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in, BUG(); } size_cacheline = partitions[to_proc].size_cacheline; free_space = hdr->offset_free_cached - hdr->offset_free_uncached; Loading Loading @@ -719,7 +742,7 @@ void *smem_alloc(unsigned int id, unsigned int size_in, unsigned int to_proc, if (!smem_initialized_check()) return NULL; if (id >= SMEM_NUM_ITEMS) { if (id >= smem_max_items) { SMEM_INFO("%s: invalid id %u\n", __func__, id); return NULL; } Loading Loading @@ -761,11 +784,16 @@ void *smem_alloc(unsigned int id, unsigned int size_in, unsigned int to_proc, if (id > SMEM_FIXED_ITEM_LAST) { SMEM_INFO("%s: allocating %u size %u to_proc %u flags %u\n", __func__, id, size_in, to_proc, flags); if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) ret = alloc_item_nonsecure(id, a_size_in); if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) { if (use_comm_partition) ret = alloc_item_secure(id, size_in, SMEM_COMM_HOST, flags); else ret = alloc_item_nonsecure(id, a_size_in); } else { ret = alloc_item_secure(id, size_in, to_proc, flags); } } else { SMEM_INFO("%s: attempted to allocate non-dynamic item %u\n", __func__, id); Loading Loading @@ -892,14 +920,18 @@ EXPORT_SYMBOL(smem_get_free_space); unsigned int smem_get_version(unsigned int idx) { int *version_array; struct smem_shared *smem = smem_ram_base; if (idx > 32) { pr_err("%s: invalid idx:%d\n", __func__, idx); return 0; } version_array = __smem_find(SMEM_VERSION_INFO, SMEM_VERSION_INFO_SIZE, true); if (use_comm_partition) version_array = smem->version; else version_array = __smem_find(SMEM_VERSION_INFO, SMEM_VERSION_INFO_SIZE, true); if (version_array == NULL) return 0; Loading Loading @@ -947,6 +979,7 @@ bool smem_initialized_check(void) static int is_inited; unsigned long flags; struct smem_shared *smem; unsigned int ver; if (likely(checked)) { if (unlikely(!is_inited)) Loading Loading @@ -975,8 +1008,12 @@ bool smem_initialized_check(void) * structures. Without the extra configuration data, the SMEM driver * cannot be properly initialized. */ if (smem_get_version(MODEM_SBL_VERSION_INDEX) != SMEM_VERSION << 16) { pr_err("%s: SBL version not correct\n", __func__); ver = smem->version[MODEM_SBL_VERSION_INDEX]; if (ver == SMEM_COMM_PART_VERSION << 16) { use_comm_partition = true; } else if (ver != SMEM_VERSION << 16) { pr_err("%s: SBL version not correct 0x%x\n", __func__, smem->version[7]); goto failed; } Loading Loading @@ -1122,6 +1159,7 @@ static void smem_init_security_partition(struct smem_toc_entry *entry, { uint16_t remote_host; struct smem_partition_header *hdr; bool is_comm_partition = false; if (!entry->offset) { SMEM_INFO("Skipping smem partition %d - bad offset\n", num); Loading @@ -1136,30 +1174,37 @@ static void smem_init_security_partition(struct smem_toc_entry *entry, return; } if (entry->host0 == SMEM_COMM_HOST && entry->host1 == SMEM_COMM_HOST) is_comm_partition = true; if (!is_comm_partition) { if (entry->host0 == SMEM_APPS) remote_host = entry->host1; else remote_host = entry->host0; if (remote_host >= NUM_SMEM_SUBSYSTEMS) { SMEM_INFO("Skipping smem partition %d - bad remote:%d\n", num, remote_host); SMEM_INFO( "Skipping smem partition %d - bad remote:%d\n", num, remote_host); return; } if (partitions[remote_host].offset) { SMEM_INFO("Skipping smem partition %d - duplicate of %d\n", num, partitions[remote_host].partition_num); SMEM_INFO( "Skipping smem partition %d - duplicate of %d\n", num, partitions[remote_host].partition_num); return; } hdr = smem_areas[0].virt_addr + entry->offset; if (entry->host0 != SMEM_APPS && entry->host1 != SMEM_APPS) { SMEM_INFO( "Non-APSS Partition %d offset:%x host0:%d host1:%d\n", num, entry->offset, entry->host0, entry->host1); return; } } hdr = smem_areas[0].virt_addr + entry->offset; if (hdr->identifier != SMEM_PART_HDR_IDENTIFIER) { LOG_ERR("Smem partition %d hdr magic is bad\n", num); Loading @@ -1177,6 +1222,14 @@ static void smem_init_security_partition(struct smem_toc_entry *entry, LOG_ERR("Smem partition %d cached heap exceeds size\n", num); BUG(); } if (hdr->host0 == SMEM_COMM_HOST && hdr->host1 == SMEM_COMM_HOST) { comm_partition.partition_num = num; comm_partition.offset = entry->offset; comm_partition.size_cacheline = entry->size_cacheline; SMEM_INFO("Common Partition %d offset:%x\n", num, entry->offset); return; } if (hdr->host0 != SMEM_APPS && hdr->host1 != SMEM_APPS) { LOG_ERR("Smem partition %d hosts don't match TOC\n", num); BUG(); Loading Loading @@ -1254,6 +1307,8 @@ static int smem_init_target_info(phys_addr_t info_addr, resource_size_t size) } smem_ram_phys = smem_targ_info->phys_base_addr; smem_ram_size = smem_targ_info->size; if (smem_targ_info->max_items) smem_max_items = smem_targ_info->max_items; iounmap(smem_targ_info_addr); return 0; } Loading Loading @@ -1490,7 +1545,7 @@ int __init msm_smem_init(void) return 0; registered = true; smem_max_items = SMEM_NUM_ITEMS; smem_ipc_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smem", 0); if (!smem_ipc_log_ctx) { pr_err("%s: unable to create logging context\n", __func__); Loading
drivers/soc/qcom/smem_debug.c +4 −5 Original line number Diff line number Diff line /* arch/arm/mach-msm/smem_debug.c * * Copyright (C) 2007 Google, Inc. * Copyright (c) 2009-2013,2016 The Linux Foundation. All rights reserved. * Copyright (c) 2009-2013,2016-2017 The Linux Foundation. All rights reserved. * Author: Brian Swetland <swetland@google.com> * * This software is licensed under the terms of the GNU General Public Loading Loading @@ -53,7 +53,7 @@ static void debug_read_mem(struct seq_file *s) heap_info->free_offset, heap_info->heap_remaining); for (n = 0; n < SMEM_NUM_ITEMS; n++) { for (n = 0; n < smem_max_items; n++) { if (toc[n].allocated == 0) continue; seq_printf(s, "%04d: offset %08x size %08x\n", Loading @@ -67,9 +67,8 @@ static void debug_read_smem_version(struct seq_file *s) for (n = 0; n < 32; n++) { version = smem_get_version(n); seq_printf(s, "entry %d: smem = %d proc_comm = %d\n", n, version >> 16, version & 0xffff); seq_printf(s, "entry %d:%x smem = %d proc_comm = %d\n", n, version, version >> 16, version & 0xffff); } } Loading
drivers/soc/qcom/smem_private.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2013,2016 The Linux Foundation. All rights reserved. /* Copyright (c) 2013,2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -18,6 +18,7 @@ #define SMD_HEAP_SIZE 512 extern uint32_t smem_max_items; struct smem_heap_info { unsigned int initialized; Loading