Loading drivers/soc/qcom/mem-offline.c +52 −3 Original line number Diff line number Diff line Loading @@ -19,7 +19,9 @@ #include <linux/mailbox/qmp.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> #include <soc/qcom/rpm-smd.h> #define RPM_DDR_REQ 0x726464 #define AOP_MSG_ADDR_MASK 0xffffffff #define AOP_MSG_ADDR_HIGH_SHIFT 32 #define MAX_LEN 96 Loading @@ -27,6 +29,7 @@ static unsigned long start_section_nr, end_section_nr; static struct kobject *kobj; static unsigned int offline_granule, sections_per_block; static bool is_rpm_controller; #define MODULE_CLASS_NAME "mem-offline" #define BUF_LEN 100 Loading @@ -53,6 +56,15 @@ static struct mem_offline_mailbox { struct mbox_chan *mbox; } mailbox; struct memory_refresh_request { u64 start; /* Lower bit signifies action * 0 - disable self-refresh * 1 - enable self-refresh * upper bits are for base address */ u32 size; /* size of memory region */ }; static struct section_stat *mem_info; static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end) Loading Loading @@ -119,6 +131,25 @@ void record_stat(unsigned long sec, ktime_t delay, int mode) mem_info[blk_nr].last_recorded_time = delay; } static int mem_region_refresh_control(unsigned long pfn, unsigned long nr_pages, bool enable) { struct memory_refresh_request mem_req; struct msm_rpm_kvp rpm_kvp; mem_req.start = enable; mem_req.start |= pfn << PAGE_SHIFT; mem_req.size = nr_pages * PAGE_SIZE; rpm_kvp.key = RPM_DDR_REQ; rpm_kvp.data = (void *)&mem_req; rpm_kvp.length = sizeof(mem_req); return msm_rpm_send_message(MSM_RPM_CTX_ACTIVE_SET, RPM_DDR_REQ, 0, &rpm_kvp, 1); } static int aop_send_msg(unsigned long addr, bool online) { struct qmp_pkt pkt; Loading Loading @@ -163,9 +194,16 @@ static int send_msg(struct memory_notify *mn, bool online, int count) start = section_nr_to_pfn(base_sec_nr); for (i = 0; i < count; ++i) { if (is_rpm_controller) ret = mem_region_refresh_control(start, segment_size >> PAGE_SHIFT, online); else ret = aop_send_msg(__pfn_to_phys(start), online); if (ret) { pr_err("PASR: AOP %s request addr:0x%llx failed\n", pr_err("PASR: %s %s request addr:0x%llx failed\n", is_rpm_controller ? "RPM" : "AOP", online ? "online" : "offline", __pfn_to_phys(start)); goto undo; Loading @@ -180,7 +218,13 @@ static int send_msg(struct memory_notify *mn, bool online, int count) while (i-- > 0) { int ret; if (is_rpm_controller) ret = mem_region_refresh_control(start, segment_size >> PAGE_SHIFT, !online); else ret = aop_send_msg(__pfn_to_phys(start), !online); if (ret) panic("Failed to completely online/offline a hotpluggable segment. A quasi state of memblock can cause randomn system failures."); start = __phys_to_pfn(__pfn_to_phys(start) + segment_size); Loading Loading @@ -530,6 +574,11 @@ static int mem_parse_dt(struct platform_device *pdev) return -EINVAL; } if (!of_find_property(node, "mboxes", NULL)) { is_rpm_controller = true; return 0; } mailbox.cl.dev = &pdev->dev; mailbox.cl.tx_block = true; mailbox.cl.tx_tout = 1000; Loading Loading
drivers/soc/qcom/mem-offline.c +52 −3 Original line number Diff line number Diff line Loading @@ -19,7 +19,9 @@ #include <linux/mailbox/qmp.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> #include <soc/qcom/rpm-smd.h> #define RPM_DDR_REQ 0x726464 #define AOP_MSG_ADDR_MASK 0xffffffff #define AOP_MSG_ADDR_HIGH_SHIFT 32 #define MAX_LEN 96 Loading @@ -27,6 +29,7 @@ static unsigned long start_section_nr, end_section_nr; static struct kobject *kobj; static unsigned int offline_granule, sections_per_block; static bool is_rpm_controller; #define MODULE_CLASS_NAME "mem-offline" #define BUF_LEN 100 Loading @@ -53,6 +56,15 @@ static struct mem_offline_mailbox { struct mbox_chan *mbox; } mailbox; struct memory_refresh_request { u64 start; /* Lower bit signifies action * 0 - disable self-refresh * 1 - enable self-refresh * upper bits are for base address */ u32 size; /* size of memory region */ }; static struct section_stat *mem_info; static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end) Loading Loading @@ -119,6 +131,25 @@ void record_stat(unsigned long sec, ktime_t delay, int mode) mem_info[blk_nr].last_recorded_time = delay; } static int mem_region_refresh_control(unsigned long pfn, unsigned long nr_pages, bool enable) { struct memory_refresh_request mem_req; struct msm_rpm_kvp rpm_kvp; mem_req.start = enable; mem_req.start |= pfn << PAGE_SHIFT; mem_req.size = nr_pages * PAGE_SIZE; rpm_kvp.key = RPM_DDR_REQ; rpm_kvp.data = (void *)&mem_req; rpm_kvp.length = sizeof(mem_req); return msm_rpm_send_message(MSM_RPM_CTX_ACTIVE_SET, RPM_DDR_REQ, 0, &rpm_kvp, 1); } static int aop_send_msg(unsigned long addr, bool online) { struct qmp_pkt pkt; Loading Loading @@ -163,9 +194,16 @@ static int send_msg(struct memory_notify *mn, bool online, int count) start = section_nr_to_pfn(base_sec_nr); for (i = 0; i < count; ++i) { if (is_rpm_controller) ret = mem_region_refresh_control(start, segment_size >> PAGE_SHIFT, online); else ret = aop_send_msg(__pfn_to_phys(start), online); if (ret) { pr_err("PASR: AOP %s request addr:0x%llx failed\n", pr_err("PASR: %s %s request addr:0x%llx failed\n", is_rpm_controller ? "RPM" : "AOP", online ? "online" : "offline", __pfn_to_phys(start)); goto undo; Loading @@ -180,7 +218,13 @@ static int send_msg(struct memory_notify *mn, bool online, int count) while (i-- > 0) { int ret; if (is_rpm_controller) ret = mem_region_refresh_control(start, segment_size >> PAGE_SHIFT, !online); else ret = aop_send_msg(__pfn_to_phys(start), !online); if (ret) panic("Failed to completely online/offline a hotpluggable segment. A quasi state of memblock can cause randomn system failures."); start = __phys_to_pfn(__pfn_to_phys(start) + segment_size); Loading Loading @@ -530,6 +574,11 @@ static int mem_parse_dt(struct platform_device *pdev) return -EINVAL; } if (!of_find_property(node, "mboxes", NULL)) { is_rpm_controller = true; return 0; } mailbox.cl.dev = &pdev->dev; mailbox.cl.tx_block = true; mailbox.cl.tx_tout = 1000; Loading