Loading drivers/soc/qcom/mem-offline.c +54 −5 Original line number Diff line number Diff line /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019, 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 @@ -24,7 +24,9 @@ #include <linux/of.h> #include <linux/mailbox_client.h> #include <linux/mailbox/qmp.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 @@ -32,6 +34,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 @@ -56,6 +59,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; void record_stat(unsigned long sec, ktime_t delay, int mode) Loading Loading @@ -85,6 +97,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 @@ -103,6 +134,17 @@ static int aop_send_msg(unsigned long addr, bool online) return mbox_send_message(mailbox.mbox, &pkt); } static int send_msg(struct memory_notify *mn, bool online) { int start = SECTION_ALIGN_DOWN(mn->start_pfn); if (is_rpm_controller) return mem_region_refresh_control(start, mn->nr_pages, online); else return aop_send_msg(__pfn_to_phys(start), online); } static int mem_event_callback(struct notifier_block *self, unsigned long action, void *arg) { Loading Loading @@ -142,8 +184,9 @@ static int mem_event_callback(struct notifier_block *self, idx) / sections_per_block].fail_count; cur = ktime_get(); if (aop_send_msg(__pfn_to_phys(start), true)) pr_err("PASR: AOP online request addr:0x%llx failed\n", if (send_msg(mn, true)) pr_err("PASR: %s online request addr:0x%llx failed\n", is_rpm_controller ? "RPM" : "AOP", __pfn_to_phys(start)); break; Loading @@ -163,8 +206,9 @@ static int mem_event_callback(struct notifier_block *self, case MEM_OFFLINE: pr_info("mem-offline: Offlined memory block mem%lu\n", sec_nr); if (aop_send_msg(__pfn_to_phys(start), false)) pr_err("PASR: AOP offline request addr:0x%llx failed\n", if (send_msg(mn, false)) pr_err("PASR: %s offline request addr:0x%llx failed\n", is_rpm_controller ? "RPM" : "AOP", __pfn_to_phys(start)); delay = ktime_ms_delta(ktime_get(), cur); Loading Loading @@ -347,6 +391,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 +54 −5 Original line number Diff line number Diff line /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019, 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 @@ -24,7 +24,9 @@ #include <linux/of.h> #include <linux/mailbox_client.h> #include <linux/mailbox/qmp.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 @@ -32,6 +34,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 @@ -56,6 +59,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; void record_stat(unsigned long sec, ktime_t delay, int mode) Loading Loading @@ -85,6 +97,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 @@ -103,6 +134,17 @@ static int aop_send_msg(unsigned long addr, bool online) return mbox_send_message(mailbox.mbox, &pkt); } static int send_msg(struct memory_notify *mn, bool online) { int start = SECTION_ALIGN_DOWN(mn->start_pfn); if (is_rpm_controller) return mem_region_refresh_control(start, mn->nr_pages, online); else return aop_send_msg(__pfn_to_phys(start), online); } static int mem_event_callback(struct notifier_block *self, unsigned long action, void *arg) { Loading Loading @@ -142,8 +184,9 @@ static int mem_event_callback(struct notifier_block *self, idx) / sections_per_block].fail_count; cur = ktime_get(); if (aop_send_msg(__pfn_to_phys(start), true)) pr_err("PASR: AOP online request addr:0x%llx failed\n", if (send_msg(mn, true)) pr_err("PASR: %s online request addr:0x%llx failed\n", is_rpm_controller ? "RPM" : "AOP", __pfn_to_phys(start)); break; Loading @@ -163,8 +206,9 @@ static int mem_event_callback(struct notifier_block *self, case MEM_OFFLINE: pr_info("mem-offline: Offlined memory block mem%lu\n", sec_nr); if (aop_send_msg(__pfn_to_phys(start), false)) pr_err("PASR: AOP offline request addr:0x%llx failed\n", if (send_msg(mn, false)) pr_err("PASR: %s offline request addr:0x%llx failed\n", is_rpm_controller ? "RPM" : "AOP", __pfn_to_phys(start)); delay = ktime_ms_delta(ktime_get(), cur); Loading Loading @@ -347,6 +391,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