| From e074877895e67fb8f49e762e7a3466f9ffb66d18 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 26 Sep 2018 16:50:17 -0500 |
| Subject: firmware: dell_rbu: Make payload memory uncachable |
| |
| From: Stuart Hayes <stuart.w.hayes@gmail.com> |
| |
| [ Upstream commit 6aecee6ad41cf97c0270f72da032c10eef025bf0 ] |
| |
| The dell_rbu driver takes firmware update payloads and puts them in memory so |
| the system BIOS can find them after a reboot. This sometimes fails (though |
| rarely), because the memory containing the payload is in the CPU cache but |
| never gets written back to main memory before the system is rebooted (CPU |
| cache contents are lost on reboot). |
| |
| With this patch, the payload memory will be changed to uncachable to ensure |
| that the payload is actually in main memory before the system is rebooted. |
| |
| Signed-off-by: Stuart Hayes <stuart.w.hayes@gmail.com> |
| Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/firmware/dell_rbu.c | 8 ++++++++ |
| 1 file changed, 8 insertions(+) |
| |
| diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c |
| index fb8af5cb7c9bf..ccefa84f73057 100644 |
| --- a/drivers/firmware/dell_rbu.c |
| +++ b/drivers/firmware/dell_rbu.c |
| @@ -45,6 +45,7 @@ |
| #include <linux/moduleparam.h> |
| #include <linux/firmware.h> |
| #include <linux/dma-mapping.h> |
| +#include <asm/set_memory.h> |
| |
| MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); |
| MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); |
| @@ -181,6 +182,11 @@ static int create_packet(void *data, size_t length) |
| packet_data_temp_buf = NULL; |
| } |
| } |
| + /* |
| + * set to uncachable or it may never get written back before reboot |
| + */ |
| + set_memory_uc((unsigned long)packet_data_temp_buf, 1 << ordernum); |
| + |
| spin_lock(&rbu_data.lock); |
| |
| newpacket->data = packet_data_temp_buf; |
| @@ -349,6 +355,8 @@ static void packet_empty_list(void) |
| * to make sure there are no stale RBU packets left in memory |
| */ |
| memset(newpacket->data, 0, rbu_data.packetsize); |
| + set_memory_wb((unsigned long)newpacket->data, |
| + 1 << newpacket->ordernum); |
| free_pages((unsigned long) newpacket->data, |
| newpacket->ordernum); |
| kfree(newpacket); |
| -- |
| 2.20.1 |
| |