Loading drivers/soc/qcom/mem-offline.c +52 −3 Original line number Original line Diff line number Diff line Loading @@ -19,7 +19,9 @@ #include <linux/mailbox/qmp.h> #include <linux/mailbox/qmp.h> #include <asm/tlbflush.h> #include <asm/tlbflush.h> #include <asm/cacheflush.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_MASK 0xffffffff #define AOP_MSG_ADDR_HIGH_SHIFT 32 #define AOP_MSG_ADDR_HIGH_SHIFT 32 #define MAX_LEN 96 #define MAX_LEN 96 Loading @@ -28,6 +30,7 @@ static unsigned long start_section_nr, end_section_nr; static struct kobject *kobj; static struct kobject *kobj; static unsigned int sections_per_block; static unsigned int sections_per_block; static u32 offline_granule; static u32 offline_granule; static bool is_rpm_controller; #define MODULE_CLASS_NAME "mem-offline" #define MODULE_CLASS_NAME "mem-offline" struct section_stat { struct section_stat { Loading Loading @@ -55,6 +58,15 @@ static struct mem_offline_mailbox { struct mbox_chan *mbox; struct mbox_chan *mbox; } mailbox; } 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 struct section_stat *mem_info; static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end) static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end) Loading Loading @@ -151,6 +163,25 @@ static void record_stat(unsigned long sec, ktime_t delay, int mode) mem_info[blk_nr].resident_since = 0; mem_info[blk_nr].resident_since = 0; } } 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) static int aop_send_msg(unsigned long addr, bool online) { { struct qmp_pkt pkt; struct qmp_pkt pkt; Loading Loading @@ -195,9 +226,16 @@ static int send_msg(struct memory_notify *mn, bool online, int count) start = section_nr_to_pfn(base_sec_nr); start = section_nr_to_pfn(base_sec_nr); for (i = 0; i < count; ++i) { 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); ret = aop_send_msg(__pfn_to_phys(start), online); if (ret) { 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", online ? "online" : "offline", __pfn_to_phys(start)); __pfn_to_phys(start)); goto undo; goto undo; Loading @@ -212,7 +250,13 @@ static int send_msg(struct memory_notify *mn, bool online, int count) while (i-- > 0) { while (i-- > 0) { int ret; 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); ret = aop_send_msg(__pfn_to_phys(start), !online); if (ret) if (ret) panic("Failed to completely online/offline a hotpluggable segment. A quasi state of memblock can cause randomn system failures."); 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); start = __phys_to_pfn(__pfn_to_phys(start) + segment_size); Loading Loading @@ -671,6 +715,11 @@ static int mem_parse_dt(struct platform_device *pdev) return -EINVAL; return -EINVAL; } } if (!of_find_property(node, "mboxes", NULL)) { is_rpm_controller = true; return 0; } mailbox.cl.dev = &pdev->dev; mailbox.cl.dev = &pdev->dev; mailbox.cl.tx_block = true; mailbox.cl.tx_block = true; mailbox.cl.tx_tout = 1000; mailbox.cl.tx_tout = 1000; Loading Loading
drivers/soc/qcom/mem-offline.c +52 −3 Original line number Original line Diff line number Diff line Loading @@ -19,7 +19,9 @@ #include <linux/mailbox/qmp.h> #include <linux/mailbox/qmp.h> #include <asm/tlbflush.h> #include <asm/tlbflush.h> #include <asm/cacheflush.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_MASK 0xffffffff #define AOP_MSG_ADDR_HIGH_SHIFT 32 #define AOP_MSG_ADDR_HIGH_SHIFT 32 #define MAX_LEN 96 #define MAX_LEN 96 Loading @@ -28,6 +30,7 @@ static unsigned long start_section_nr, end_section_nr; static struct kobject *kobj; static struct kobject *kobj; static unsigned int sections_per_block; static unsigned int sections_per_block; static u32 offline_granule; static u32 offline_granule; static bool is_rpm_controller; #define MODULE_CLASS_NAME "mem-offline" #define MODULE_CLASS_NAME "mem-offline" struct section_stat { struct section_stat { Loading Loading @@ -55,6 +58,15 @@ static struct mem_offline_mailbox { struct mbox_chan *mbox; struct mbox_chan *mbox; } mailbox; } 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 struct section_stat *mem_info; static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end) static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end) Loading Loading @@ -151,6 +163,25 @@ static void record_stat(unsigned long sec, ktime_t delay, int mode) mem_info[blk_nr].resident_since = 0; mem_info[blk_nr].resident_since = 0; } } 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) static int aop_send_msg(unsigned long addr, bool online) { { struct qmp_pkt pkt; struct qmp_pkt pkt; Loading Loading @@ -195,9 +226,16 @@ static int send_msg(struct memory_notify *mn, bool online, int count) start = section_nr_to_pfn(base_sec_nr); start = section_nr_to_pfn(base_sec_nr); for (i = 0; i < count; ++i) { 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); ret = aop_send_msg(__pfn_to_phys(start), online); if (ret) { 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", online ? "online" : "offline", __pfn_to_phys(start)); __pfn_to_phys(start)); goto undo; goto undo; Loading @@ -212,7 +250,13 @@ static int send_msg(struct memory_notify *mn, bool online, int count) while (i-- > 0) { while (i-- > 0) { int ret; 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); ret = aop_send_msg(__pfn_to_phys(start), !online); if (ret) if (ret) panic("Failed to completely online/offline a hotpluggable segment. A quasi state of memblock can cause randomn system failures."); 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); start = __phys_to_pfn(__pfn_to_phys(start) + segment_size); Loading Loading @@ -671,6 +715,11 @@ static int mem_parse_dt(struct platform_device *pdev) return -EINVAL; return -EINVAL; } } if (!of_find_property(node, "mboxes", NULL)) { is_rpm_controller = true; return 0; } mailbox.cl.dev = &pdev->dev; mailbox.cl.dev = &pdev->dev; mailbox.cl.tx_block = true; mailbox.cl.tx_block = true; mailbox.cl.tx_tout = 1000; mailbox.cl.tx_tout = 1000; Loading