linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] dell_rbu: make firmware payload memory uncachable
@ 2018-03-22  1:05 Stuart Hayes
  2018-03-23  2:51 ` kbuild test robot
  2018-03-23  2:58 ` kbuild test robot
  0 siblings, 2 replies; 4+ messages in thread
From: Stuart Hayes @ 2018-03-22  1:05 UTC (permalink / raw)
  To: linux-kernel

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>
---
Note that there is no maintainer for this driver, so I'd be grateful if
someone could apply this... thank you!

diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index 2f452f1..6b84814 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -180,6 +180,11 @@ static int create_packet(void *data, size_t length)
 			invalid_addr_packet_array[idx++] = packet_data_temp_buf;
 			packet_data_temp_buf = NULL;
 		}
+		/*
+		 * set to uncachable or it may never get written back before
+		 * reboot
+		 */
+		set_memory_uc(packet_data_temp_buf, 1 << (ordernum));
 	}
 	spin_lock(&rbu_data.lock);
 
@@ -349,6 +354,7 @@ 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(newpacket->data, (1 << newpacket->ordernum));
 		free_pages((unsigned long) newpacket->data,
 			newpacket->ordernum);
 		kfree(newpacket);

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] dell_rbu: make firmware payload memory uncachable
  2018-03-22  1:05 [PATCH] dell_rbu: make firmware payload memory uncachable Stuart Hayes
@ 2018-03-23  2:51 ` kbuild test robot
  2018-03-23  2:58 ` kbuild test robot
  1 sibling, 0 replies; 4+ messages in thread
From: kbuild test robot @ 2018-03-23  2:51 UTC (permalink / raw)
  To: Stuart Hayes; +Cc: kbuild-all, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 10005 bytes --]

Hi Stuart,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.16-rc6 next-20180322]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Stuart-Hayes/dell_rbu-make-firmware-payload-memory-uncachable/20180323-094405
config: i386-randconfig-a0-201811 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/firmware/dell_rbu.c: In function 'create_packet':
>> drivers/firmware/dell_rbu.c:187:3: error: implicit declaration of function 'set_memory_uc' [-Werror=implicit-function-declaration]
      set_memory_uc(packet_data_temp_buf, 1 << (ordernum));
      ^
   drivers/firmware/dell_rbu.c: In function 'packet_empty_list':
>> drivers/firmware/dell_rbu.c:357:3: error: implicit declaration of function 'set_memory_wb' [-Werror=implicit-function-declaration]
      set_memory_wb(newpacket->data, (1 << newpacket->ordernum));
      ^
   cc1: some warnings being treated as errors

vim +/set_memory_uc +187 drivers/firmware/dell_rbu.c

   101	
   102	static int create_packet(void *data, size_t length)
   103	{
   104		struct packet_data *newpacket;
   105		int ordernum = 0;
   106		int retval = 0;
   107		unsigned int packet_array_size = 0;
   108		void **invalid_addr_packet_array = NULL;
   109		void *packet_data_temp_buf = NULL;
   110		unsigned int idx = 0;
   111	
   112		pr_debug("create_packet: entry \n");
   113	
   114		if (!rbu_data.packetsize) {
   115			pr_debug("create_packet: packetsize not specified\n");
   116			retval = -EINVAL;
   117			goto out_noalloc;
   118		}
   119	
   120		spin_unlock(&rbu_data.lock);
   121	
   122		newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);
   123	
   124		if (!newpacket) {
   125			printk(KERN_WARNING
   126				"dell_rbu:%s: failed to allocate new "
   127				"packet\n", __func__);
   128			retval = -ENOMEM;
   129			spin_lock(&rbu_data.lock);
   130			goto out_noalloc;
   131		}
   132	
   133		ordernum = get_order(length);
   134	
   135		/*
   136		 * BIOS errata mean we cannot allocate packets below 1MB or they will
   137		 * be overwritten by BIOS.
   138		 *
   139		 * array to temporarily hold packets
   140		 * that are below the allocation floor
   141		 *
   142		 * NOTE: very simplistic because we only need the floor to be at 1MB
   143		 *       due to BIOS errata. This shouldn't be used for higher floors
   144		 *       or you will run out of mem trying to allocate the array.
   145		 */
   146		packet_array_size = max(
   147		       		(unsigned int)(allocation_floor / rbu_data.packetsize),
   148				(unsigned int)1);
   149		invalid_addr_packet_array = kzalloc(packet_array_size * sizeof(void*),
   150							GFP_KERNEL);
   151	
   152		if (!invalid_addr_packet_array) {
   153			printk(KERN_WARNING
   154				"dell_rbu:%s: failed to allocate "
   155				"invalid_addr_packet_array \n",
   156				__func__);
   157			retval = -ENOMEM;
   158			spin_lock(&rbu_data.lock);
   159			goto out_alloc_packet;
   160		}
   161	
   162		while (!packet_data_temp_buf) {
   163			packet_data_temp_buf = (unsigned char *)
   164				__get_free_pages(GFP_KERNEL, ordernum);
   165			if (!packet_data_temp_buf) {
   166				printk(KERN_WARNING
   167					"dell_rbu:%s: failed to allocate new "
   168					"packet\n", __func__);
   169				retval = -ENOMEM;
   170				spin_lock(&rbu_data.lock);
   171				goto out_alloc_packet_array;
   172			}
   173	
   174			if ((unsigned long)virt_to_phys(packet_data_temp_buf)
   175					< allocation_floor) {
   176				pr_debug("packet 0x%lx below floor at 0x%lx.\n",
   177						(unsigned long)virt_to_phys(
   178							packet_data_temp_buf),
   179						allocation_floor);
   180				invalid_addr_packet_array[idx++] = packet_data_temp_buf;
   181				packet_data_temp_buf = NULL;
   182			}
   183			/*
   184			 * set to uncachable or it may never get written back before
   185			 * reboot
   186			 */
 > 187			set_memory_uc(packet_data_temp_buf, 1 << (ordernum));
   188		}
   189		spin_lock(&rbu_data.lock);
   190	
   191		newpacket->data = packet_data_temp_buf;
   192	
   193		pr_debug("create_packet: newpacket at physical addr %lx\n",
   194			(unsigned long)virt_to_phys(newpacket->data));
   195	
   196		/* packets may not have fixed size */
   197		newpacket->length = length;
   198		newpacket->ordernum = ordernum;
   199		++rbu_data.num_packets;
   200	
   201		/* initialize the newly created packet headers */
   202		INIT_LIST_HEAD(&newpacket->list);
   203		list_add_tail(&newpacket->list, &packet_data_head.list);
   204	
   205		memcpy(newpacket->data, data, length);
   206	
   207		pr_debug("create_packet: exit \n");
   208	
   209	out_alloc_packet_array:
   210		/* always free packet array */
   211		for (;idx>0;idx--) {
   212			pr_debug("freeing unused packet below floor 0x%lx.\n",
   213				(unsigned long)virt_to_phys(
   214					invalid_addr_packet_array[idx-1]));
   215			free_pages((unsigned long)invalid_addr_packet_array[idx-1],
   216				ordernum);
   217		}
   218		kfree(invalid_addr_packet_array);
   219	
   220	out_alloc_packet:
   221		/* if error, free data */
   222		if (retval)
   223			kfree(newpacket);
   224	
   225	out_noalloc:
   226		return retval;
   227	}
   228	
   229	static int packetize_data(const u8 *data, size_t length)
   230	{
   231		int rc = 0;
   232		int done = 0;
   233		int packet_length;
   234		u8 *temp;
   235		u8 *end = (u8 *) data + length;
   236		pr_debug("packetize_data: data length %zd\n", length);
   237		if (!rbu_data.packetsize) {
   238			printk(KERN_WARNING
   239				"dell_rbu: packetsize not specified\n");
   240			return -EIO;
   241		}
   242	
   243		temp = (u8 *) data;
   244	
   245		/* packetize the hunk */
   246		while (!done) {
   247			if ((temp + rbu_data.packetsize) < end)
   248				packet_length = rbu_data.packetsize;
   249			else {
   250				/* this is the last packet */
   251				packet_length = end - temp;
   252				done = 1;
   253			}
   254	
   255			if ((rc = create_packet(temp, packet_length)))
   256				return rc;
   257	
   258			pr_debug("%p:%td\n", temp, (end - temp));
   259			temp += packet_length;
   260		}
   261	
   262		rbu_data.imagesize = length;
   263	
   264		return rc;
   265	}
   266	
   267	static int do_packet_read(char *data, struct list_head *ptemp_list,
   268		int length, int bytes_read, int *list_read_count)
   269	{
   270		void *ptemp_buf;
   271		struct packet_data *newpacket = NULL;
   272		int bytes_copied = 0;
   273		int j = 0;
   274	
   275		newpacket = list_entry(ptemp_list, struct packet_data, list);
   276		*list_read_count += newpacket->length;
   277	
   278		if (*list_read_count > bytes_read) {
   279			/* point to the start of unread data */
   280			j = newpacket->length - (*list_read_count - bytes_read);
   281			/* point to the offset in the packet buffer */
   282			ptemp_buf = (u8 *) newpacket->data + j;
   283			/*
   284			 * check if there is enough room in
   285			 * * the incoming buffer
   286			 */
   287			if (length > (*list_read_count - bytes_read))
   288				/*
   289				 * copy what ever is there in this
   290				 * packet and move on
   291				 */
   292				bytes_copied = (*list_read_count - bytes_read);
   293			else
   294				/* copy the remaining */
   295				bytes_copied = length;
   296			memcpy(data, ptemp_buf, bytes_copied);
   297		}
   298		return bytes_copied;
   299	}
   300	
   301	static int packet_read_list(char *data, size_t * pread_length)
   302	{
   303		struct list_head *ptemp_list;
   304		int temp_count = 0;
   305		int bytes_copied = 0;
   306		int bytes_read = 0;
   307		int remaining_bytes = 0;
   308		char *pdest = data;
   309	
   310		/* check if we have any packets */
   311		if (0 == rbu_data.num_packets)
   312			return -ENOMEM;
   313	
   314		remaining_bytes = *pread_length;
   315		bytes_read = rbu_data.packet_read_count;
   316	
   317		ptemp_list = (&packet_data_head.list)->next;
   318		while (!list_empty(ptemp_list)) {
   319			bytes_copied = do_packet_read(pdest, ptemp_list,
   320				remaining_bytes, bytes_read, &temp_count);
   321			remaining_bytes -= bytes_copied;
   322			bytes_read += bytes_copied;
   323			pdest += bytes_copied;
   324			/*
   325			 * check if we reached end of buffer before reaching the
   326			 * last packet
   327			 */
   328			if (remaining_bytes == 0)
   329				break;
   330	
   331			ptemp_list = ptemp_list->next;
   332		}
   333		/*finally set the bytes read */
   334		*pread_length = bytes_read - rbu_data.packet_read_count;
   335		rbu_data.packet_read_count = bytes_read;
   336		return 0;
   337	}
   338	
   339	static void packet_empty_list(void)
   340	{
   341		struct list_head *ptemp_list;
   342		struct list_head *pnext_list;
   343		struct packet_data *newpacket;
   344	
   345		ptemp_list = (&packet_data_head.list)->next;
   346		while (!list_empty(ptemp_list)) {
   347			newpacket =
   348				list_entry(ptemp_list, struct packet_data, list);
   349			pnext_list = ptemp_list->next;
   350			list_del(ptemp_list);
   351			ptemp_list = pnext_list;
   352			/*
   353			 * zero out the RBU packet memory before freeing
   354			 * to make sure there are no stale RBU packets left in memory
   355			 */
   356			memset(newpacket->data, 0, rbu_data.packetsize);
 > 357			set_memory_wb(newpacket->data, (1 << newpacket->ordernum));
   358			free_pages((unsigned long) newpacket->data,
   359				newpacket->ordernum);
   360			kfree(newpacket);
   361		}
   362		rbu_data.packet_read_count = 0;
   363		rbu_data.num_packets = 0;
   364		rbu_data.imagesize = 0;
   365	}
   366	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 31690 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] dell_rbu: make firmware payload memory uncachable
  2018-03-22  1:05 [PATCH] dell_rbu: make firmware payload memory uncachable Stuart Hayes
  2018-03-23  2:51 ` kbuild test robot
@ 2018-03-23  2:58 ` kbuild test robot
  2018-03-23 22:19   ` Stuart Hayes
  1 sibling, 1 reply; 4+ messages in thread
From: kbuild test robot @ 2018-03-23  2:58 UTC (permalink / raw)
  To: Stuart Hayes; +Cc: kbuild-all, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 13653 bytes --]

Hi Stuart,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.16-rc6 next-20180322]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Stuart-Hayes/dell_rbu-make-firmware-payload-memory-uncachable/20180323-094405
config: i386-randconfig-x014-201811 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/firmware/dell_rbu.c: In function 'create_packet':
>> drivers/firmware/dell_rbu.c:187:3: error: implicit declaration of function 'set_memory_uc'; did you mean 'add_memory'? [-Werror=implicit-function-declaration]
      set_memory_uc(packet_data_temp_buf, 1 << (ordernum));
      ^~~~~~~~~~~~~
      add_memory
   drivers/firmware/dell_rbu.c: In function 'packet_empty_list':
>> drivers/firmware/dell_rbu.c:357:3: error: implicit declaration of function 'set_memory_wb'; did you mean 'add_memory'? [-Werror=implicit-function-declaration]
      set_memory_wb(newpacket->data, (1 << newpacket->ordernum));
      ^~~~~~~~~~~~~
      add_memory
   Cyclomatic Complexity 5 include/linux/compiler.h:__read_once_size
   Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
   Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls
   Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u32
   Cyclomatic Complexity 1 include/linux/list.h:INIT_LIST_HEAD
   Cyclomatic Complexity 2 include/linux/list.h:__list_add
   Cyclomatic Complexity 1 include/linux/list.h:list_add_tail
   Cyclomatic Complexity 1 include/linux/list.h:__list_del
   Cyclomatic Complexity 2 include/linux/list.h:__list_del_entry
   Cyclomatic Complexity 1 include/linux/list.h:list_del
   Cyclomatic Complexity 1 include/linux/list.h:list_empty
   Cyclomatic Complexity 1 include/asm-generic/getorder.h:__get_order
   Cyclomatic Complexity 1 arch/x86/include/asm/paravirt.h:arch_local_save_flags
   Cyclomatic Complexity 1 include/linux/err.h:PTR_ERR
   Cyclomatic Complexity 1 include/linux/err.h:IS_ERR
   Cyclomatic Complexity 1 arch/x86/include/asm/irqflags.h:arch_irqs_disabled_flags
   Cyclomatic Complexity 1 include/linux/spinlock.h:spinlock_check
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_lock
   Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock
   Cyclomatic Complexity 1 arch/x86/include/asm/io.h:virt_to_phys
   Cyclomatic Complexity 28 include/linux/slab.h:kmalloc_index
   Cyclomatic Complexity 67 include/linux/slab.h:kmalloc_large
   Cyclomatic Complexity 5 include/linux/slab.h:kmalloc
   Cyclomatic Complexity 1 include/linux/slab.h:kzalloc
   Cyclomatic Complexity 1 include/linux/platform_device.h:platform_device_register_resndata
   Cyclomatic Complexity 1 include/linux/platform_device.h:platform_device_register_simple
   Cyclomatic Complexity 1 include/linux/dma-debug.h:debug_dma_free_coherent
   Cyclomatic Complexity 1 arch/x86/include/asm/dma-mapping.h:get_arch_dma_ops
   Cyclomatic Complexity 4 include/linux/dma-mapping.h:get_dma_ops
   Cyclomatic Complexity 71 include/linux/dma-mapping.h:dma_free_attrs
   Cyclomatic Complexity 1 include/linux/dma-mapping.h:dma_free_coherent
   Cyclomatic Complexity 1 drivers/firmware/dell_rbu.c:init_packet_head
   Cyclomatic Complexity 3 drivers/firmware/dell_rbu.c:img_update_free
   Cyclomatic Complexity 3 drivers/firmware/dell_rbu.c:packet_empty_list
   Cyclomatic Complexity 1 drivers/firmware/dell_rbu.c:dcdrbu_exit
   Cyclomatic Complexity 5 drivers/firmware/dell_rbu.c:dcdrbu_init
   Cyclomatic Complexity 2 drivers/firmware/dell_rbu.c:write_rbu_packet_size
   Cyclomatic Complexity 2 drivers/firmware/dell_rbu.c:read_rbu_packet_size
   Cyclomatic Complexity 2 drivers/firmware/dell_rbu.c:read_rbu_image_type
   Cyclomatic Complexity 9 drivers/firmware/dell_rbu.c:write_rbu_image_type
   Cyclomatic Complexity 71 drivers/firmware/dell_rbu.c:img_update_realloc
   Cyclomatic Complexity 75 drivers/firmware/dell_rbu.c:create_packet
   Cyclomatic Complexity 5 drivers/firmware/dell_rbu.c:packetize_data
   Cyclomatic Complexity 7 drivers/firmware/dell_rbu.c:callbackfn_rbu
   Cyclomatic Complexity 3 drivers/firmware/dell_rbu.c:read_rbu_mono_data
   Cyclomatic Complexity 4 drivers/firmware/dell_rbu.c:do_packet_read
   Cyclomatic Complexity 4 drivers/firmware/dell_rbu.c:packet_read_list
   Cyclomatic Complexity 5 drivers/firmware/dell_rbu.c:read_packet_data
   Cyclomatic Complexity 3 drivers/firmware/dell_rbu.c:read_rbu_data
   Cyclomatic Complexity 1 drivers/firmware/dell_rbu.c:_GLOBAL__sub_I_00100_0_dell_rbu.c
   Cyclomatic Complexity 1 drivers/firmware/dell_rbu.c:_GLOBAL__sub_D_00100_1_dell_rbu.c
   cc1: some warnings being treated as errors

vim +187 drivers/firmware/dell_rbu.c

   101	
   102	static int create_packet(void *data, size_t length)
   103	{
   104		struct packet_data *newpacket;
   105		int ordernum = 0;
   106		int retval = 0;
   107		unsigned int packet_array_size = 0;
   108		void **invalid_addr_packet_array = NULL;
   109		void *packet_data_temp_buf = NULL;
   110		unsigned int idx = 0;
   111	
   112		pr_debug("create_packet: entry \n");
   113	
   114		if (!rbu_data.packetsize) {
   115			pr_debug("create_packet: packetsize not specified\n");
   116			retval = -EINVAL;
   117			goto out_noalloc;
   118		}
   119	
   120		spin_unlock(&rbu_data.lock);
   121	
   122		newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);
   123	
   124		if (!newpacket) {
   125			printk(KERN_WARNING
   126				"dell_rbu:%s: failed to allocate new "
   127				"packet\n", __func__);
   128			retval = -ENOMEM;
   129			spin_lock(&rbu_data.lock);
   130			goto out_noalloc;
   131		}
   132	
   133		ordernum = get_order(length);
   134	
   135		/*
   136		 * BIOS errata mean we cannot allocate packets below 1MB or they will
   137		 * be overwritten by BIOS.
   138		 *
   139		 * array to temporarily hold packets
   140		 * that are below the allocation floor
   141		 *
   142		 * NOTE: very simplistic because we only need the floor to be at 1MB
   143		 *       due to BIOS errata. This shouldn't be used for higher floors
   144		 *       or you will run out of mem trying to allocate the array.
   145		 */
   146		packet_array_size = max(
   147		       		(unsigned int)(allocation_floor / rbu_data.packetsize),
   148				(unsigned int)1);
   149		invalid_addr_packet_array = kzalloc(packet_array_size * sizeof(void*),
   150							GFP_KERNEL);
   151	
   152		if (!invalid_addr_packet_array) {
   153			printk(KERN_WARNING
   154				"dell_rbu:%s: failed to allocate "
   155				"invalid_addr_packet_array \n",
   156				__func__);
   157			retval = -ENOMEM;
   158			spin_lock(&rbu_data.lock);
   159			goto out_alloc_packet;
   160		}
   161	
   162		while (!packet_data_temp_buf) {
   163			packet_data_temp_buf = (unsigned char *)
   164				__get_free_pages(GFP_KERNEL, ordernum);
   165			if (!packet_data_temp_buf) {
   166				printk(KERN_WARNING
   167					"dell_rbu:%s: failed to allocate new "
   168					"packet\n", __func__);
   169				retval = -ENOMEM;
   170				spin_lock(&rbu_data.lock);
   171				goto out_alloc_packet_array;
   172			}
   173	
   174			if ((unsigned long)virt_to_phys(packet_data_temp_buf)
   175					< allocation_floor) {
   176				pr_debug("packet 0x%lx below floor at 0x%lx.\n",
   177						(unsigned long)virt_to_phys(
   178							packet_data_temp_buf),
   179						allocation_floor);
   180				invalid_addr_packet_array[idx++] = packet_data_temp_buf;
   181				packet_data_temp_buf = NULL;
   182			}
   183			/*
   184			 * set to uncachable or it may never get written back before
   185			 * reboot
   186			 */
 > 187			set_memory_uc(packet_data_temp_buf, 1 << (ordernum));
   188		}
   189		spin_lock(&rbu_data.lock);
   190	
   191		newpacket->data = packet_data_temp_buf;
   192	
   193		pr_debug("create_packet: newpacket at physical addr %lx\n",
   194			(unsigned long)virt_to_phys(newpacket->data));
   195	
   196		/* packets may not have fixed size */
   197		newpacket->length = length;
   198		newpacket->ordernum = ordernum;
   199		++rbu_data.num_packets;
   200	
   201		/* initialize the newly created packet headers */
   202		INIT_LIST_HEAD(&newpacket->list);
   203		list_add_tail(&newpacket->list, &packet_data_head.list);
   204	
   205		memcpy(newpacket->data, data, length);
   206	
   207		pr_debug("create_packet: exit \n");
   208	
   209	out_alloc_packet_array:
   210		/* always free packet array */
   211		for (;idx>0;idx--) {
   212			pr_debug("freeing unused packet below floor 0x%lx.\n",
   213				(unsigned long)virt_to_phys(
   214					invalid_addr_packet_array[idx-1]));
   215			free_pages((unsigned long)invalid_addr_packet_array[idx-1],
   216				ordernum);
   217		}
   218		kfree(invalid_addr_packet_array);
   219	
   220	out_alloc_packet:
   221		/* if error, free data */
   222		if (retval)
   223			kfree(newpacket);
   224	
   225	out_noalloc:
   226		return retval;
   227	}
   228	
   229	static int packetize_data(const u8 *data, size_t length)
   230	{
   231		int rc = 0;
   232		int done = 0;
   233		int packet_length;
   234		u8 *temp;
   235		u8 *end = (u8 *) data + length;
   236		pr_debug("packetize_data: data length %zd\n", length);
   237		if (!rbu_data.packetsize) {
   238			printk(KERN_WARNING
   239				"dell_rbu: packetsize not specified\n");
   240			return -EIO;
   241		}
   242	
   243		temp = (u8 *) data;
   244	
   245		/* packetize the hunk */
   246		while (!done) {
   247			if ((temp + rbu_data.packetsize) < end)
   248				packet_length = rbu_data.packetsize;
   249			else {
   250				/* this is the last packet */
   251				packet_length = end - temp;
   252				done = 1;
   253			}
   254	
   255			if ((rc = create_packet(temp, packet_length)))
   256				return rc;
   257	
   258			pr_debug("%p:%td\n", temp, (end - temp));
   259			temp += packet_length;
   260		}
   261	
   262		rbu_data.imagesize = length;
   263	
   264		return rc;
   265	}
   266	
   267	static int do_packet_read(char *data, struct list_head *ptemp_list,
   268		int length, int bytes_read, int *list_read_count)
   269	{
   270		void *ptemp_buf;
   271		struct packet_data *newpacket = NULL;
   272		int bytes_copied = 0;
   273		int j = 0;
   274	
   275		newpacket = list_entry(ptemp_list, struct packet_data, list);
   276		*list_read_count += newpacket->length;
   277	
   278		if (*list_read_count > bytes_read) {
   279			/* point to the start of unread data */
   280			j = newpacket->length - (*list_read_count - bytes_read);
   281			/* point to the offset in the packet buffer */
   282			ptemp_buf = (u8 *) newpacket->data + j;
   283			/*
   284			 * check if there is enough room in
   285			 * * the incoming buffer
   286			 */
   287			if (length > (*list_read_count - bytes_read))
   288				/*
   289				 * copy what ever is there in this
   290				 * packet and move on
   291				 */
   292				bytes_copied = (*list_read_count - bytes_read);
   293			else
   294				/* copy the remaining */
   295				bytes_copied = length;
   296			memcpy(data, ptemp_buf, bytes_copied);
   297		}
   298		return bytes_copied;
   299	}
   300	
   301	static int packet_read_list(char *data, size_t * pread_length)
   302	{
   303		struct list_head *ptemp_list;
   304		int temp_count = 0;
   305		int bytes_copied = 0;
   306		int bytes_read = 0;
   307		int remaining_bytes = 0;
   308		char *pdest = data;
   309	
   310		/* check if we have any packets */
   311		if (0 == rbu_data.num_packets)
   312			return -ENOMEM;
   313	
   314		remaining_bytes = *pread_length;
   315		bytes_read = rbu_data.packet_read_count;
   316	
   317		ptemp_list = (&packet_data_head.list)->next;
   318		while (!list_empty(ptemp_list)) {
   319			bytes_copied = do_packet_read(pdest, ptemp_list,
   320				remaining_bytes, bytes_read, &temp_count);
   321			remaining_bytes -= bytes_copied;
   322			bytes_read += bytes_copied;
   323			pdest += bytes_copied;
   324			/*
   325			 * check if we reached end of buffer before reaching the
   326			 * last packet
   327			 */
   328			if (remaining_bytes == 0)
   329				break;
   330	
   331			ptemp_list = ptemp_list->next;
   332		}
   333		/*finally set the bytes read */
   334		*pread_length = bytes_read - rbu_data.packet_read_count;
   335		rbu_data.packet_read_count = bytes_read;
   336		return 0;
   337	}
   338	
   339	static void packet_empty_list(void)
   340	{
   341		struct list_head *ptemp_list;
   342		struct list_head *pnext_list;
   343		struct packet_data *newpacket;
   344	
   345		ptemp_list = (&packet_data_head.list)->next;
   346		while (!list_empty(ptemp_list)) {
   347			newpacket =
   348				list_entry(ptemp_list, struct packet_data, list);
   349			pnext_list = ptemp_list->next;
   350			list_del(ptemp_list);
   351			ptemp_list = pnext_list;
   352			/*
   353			 * zero out the RBU packet memory before freeing
   354			 * to make sure there are no stale RBU packets left in memory
   355			 */
   356			memset(newpacket->data, 0, rbu_data.packetsize);
 > 357			set_memory_wb(newpacket->data, (1 << newpacket->ordernum));
   358			free_pages((unsigned long) newpacket->data,
   359				newpacket->ordernum);
   360			kfree(newpacket);
   361		}
   362		rbu_data.packet_read_count = 0;
   363		rbu_data.num_packets = 0;
   364		rbu_data.imagesize = 0;
   365	}
   366	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 31679 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] dell_rbu: make firmware payload memory uncachable
  2018-03-23  2:58 ` kbuild test robot
@ 2018-03-23 22:19   ` Stuart Hayes
  0 siblings, 0 replies; 4+ messages in thread
From: Stuart Hayes @ 2018-03-23 22:19 UTC (permalink / raw)
  To: kbuild test robot; +Cc: kbuild-all, linux-kernel



On 3/22/2018 9:58 PM, kbuild test robot wrote:
> Hi Stuart,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.16-rc6 next-20180322]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Stuart-Hayes/dell_rbu-make-firmware-payload-memory-uncachable/20180323-094405
> config: i386-randconfig-x014-201811 (attached as .config)
> compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=i386 
> 

Please disregard this one, will send a "v2" shortly.  Not sure how I managed to send this version...
Thanks!

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-03-23 22:19 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-22  1:05 [PATCH] dell_rbu: make firmware payload memory uncachable Stuart Hayes
2018-03-23  2:51 ` kbuild test robot
2018-03-23  2:58 ` kbuild test robot
2018-03-23 22:19   ` Stuart Hayes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).