diff mbox series

[1/2] HID: intel-ish-hid: fix cache management mistake

Message ID 20240528115802.3122955-1-arnd@kernel.org (mailing list archive)
State New
Delegated to: Jiri Kosina
Headers show
Series [1/2] HID: intel-ish-hid: fix cache management mistake | expand

Commit Message

Arnd Bergmann May 28, 2024, 11:57 a.m. UTC
From: Arnd Bergmann <arnd@arndb.de>

The low-level cache operation on a coherent buffer is incorrect,
as coherent DMA memory may not actually be cached. Instead, use a DMA
barrier that ensures that the data is visible to the DMA master before
the address is and move the memcpy() before the reference.

Fixes: 579a267e4617 ("HID: intel-ish-hid: Implement loading firmware from host feature")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
I noticed this one while looking at the bug that was fixed in
236049723826 ("HID: intel-ish-hid: Fix build error for COMPILE_TEST")
---
 drivers/hid/intel-ish-hid/ishtp/loader.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Comments

Zhang, Lixu May 29, 2024, 6:46 a.m. UTC | #1
>-----Original Message-----
>From: Arnd Bergmann <arnd@kernel.org>
>Sent: Tuesday, May 28, 2024 7:58 PM
>To: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>; Jiri Kosina
><jikos@kernel.org>; Benjamin Tissoires <bentiss@kernel.org>; Zhang, Lixu
><lixu.zhang@intel.com>
>Cc: Arnd Bergmann <arnd@arndb.de>; linux-input@vger.kernel.org; linux-
>kernel@vger.kernel.org
>Subject: [PATCH 1/2] HID: intel-ish-hid: fix cache management mistake
>
>From: Arnd Bergmann <arnd@arndb.de>
>
>The low-level cache operation on a coherent buffer is incorrect, as coherent
>DMA memory may not actually be cached. Instead, use a DMA barrier that
>ensures that the data is visible to the DMA master before the address is and
>move the memcpy() before the reference.
>
>Fixes: 579a267e4617 ("HID: intel-ish-hid: Implement loading firmware from
>host feature")
>Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>---
>I noticed this one while looking at the bug that was fixed in
>236049723826 ("HID: intel-ish-hid: Fix build error for COMPILE_TEST")
>---
> drivers/hid/intel-ish-hid/ishtp/loader.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
>diff --git a/drivers/hid/intel-ish-hid/ishtp/loader.c b/drivers/hid/intel-ish-
>hid/ishtp/loader.c
>index 2785b04a2f5a..062d1b25eaa7 100644
>--- a/drivers/hid/intel-ish-hid/ishtp/loader.c
>+++ b/drivers/hid/intel-ish-hid/ishtp/loader.c
>@@ -33,7 +33,6 @@
>
> #define dev_fmt(fmt) "ISH loader: " fmt
>
>-#include <linux/cacheflush.h>
> #include <linux/container_of.h>
> #include <linux/dev_printk.h>
> #include <linux/dma-mapping.h>
>@@ -175,10 +174,11 @@ static int prepare_dma_bufs(struct ishtp_device
>*dev,
> 			return -ENOMEM;
>
> 		fragment->fragment_tbl[i].ddr_adrs =
>cpu_to_le64(dma_addr);
>+
>+		memcpy(dma_bufs[i], ish_fw->data + offset, fragment-
>>fragment_tbl[i].length);
fragment->fragment_tbl[i].length was used before assignment.
 
>+		dma_wmb();
I tested it on the platform, but it didn't wok.

Thanks,
Lixu

> 		fragment->fragment_tbl[i].length = clamp(ish_fw->size -
>offset, 0, fragment_size);
> 		fragment->fragment_tbl[i].fw_off = offset;
>-		memcpy(dma_bufs[i], ish_fw->data + offset, fragment-
>>fragment_tbl[i].length);
>-		clflush_cache_range(dma_bufs[i], fragment_size);
>
> 		offset += fragment->fragment_tbl[i].length;
> 	}
>--
>2.39.2
Arnd Bergmann May 29, 2024, 7:06 a.m. UTC | #2
On Wed, May 29, 2024, at 08:46, Zhang, Lixu wrote:
>>
>>-#include <linux/cacheflush.h>
>> #include <linux/container_of.h>
>> #include <linux/dev_printk.h>
>> #include <linux/dma-mapping.h>
>>@@ -175,10 +174,11 @@ static int prepare_dma_bufs(struct ishtp_device
>>*dev,
>> 			return -ENOMEM;
>>
>> 		fragment->fragment_tbl[i].ddr_adrs =
>>cpu_to_le64(dma_addr);
>>+
>>+		memcpy(dma_bufs[i], ish_fw->data + offset, fragment-
>>>fragment_tbl[i].length);
> fragment->fragment_tbl[i].length was used before assignment.
> 
>>+		dma_wmb();
> I tested it on the platform, but it didn't wok.
>

What behavior do you see instead? If the manual cache
flush works around a bug, that would indicate that the
device itself is not coherent and the dma_alloc_coherent()
in the architecture is broken.

     Arnd
srinivas pandruvada May 29, 2024, 10:25 p.m. UTC | #3
On Wed, 2024-05-29 at 09:06 +0200, Arnd Bergmann wrote:
> On Wed, May 29, 2024, at 08:46, Zhang, Lixu wrote:
> > > 
> > > -#include <linux/cacheflush.h>
> > > #include <linux/container_of.h>
> > > #include <linux/dev_printk.h>
> > > #include <linux/dma-mapping.h>
> > > @@ -175,10 +174,11 @@ static int prepare_dma_bufs(struct
> > > ishtp_device
> > > *dev,
> > > 			return -ENOMEM;
> > > 
> > > 		fragment->fragment_tbl[i].ddr_adrs =
> > > cpu_to_le64(dma_addr);
> > > +
> > > +		memcpy(dma_bufs[i], ish_fw->data + offset,
> > > fragment-
> > > > fragment_tbl[i].length);
> > fragment->fragment_tbl[i].length was used before assignment.
> > 
> > > +		dma_wmb();
> > I tested it on the platform, but it didn't wok.
> > 
> 
> What behavior do you see instead? If the manual cache
> flush works around a bug, that would indicate that the
> device itself is not coherent and the dma_alloc_coherent()
> in the architecture is broken.

Lixu,

What happens if you remove manual cache flush in your code?
It is possible that boot loader at this time not ready to do fully
coherent ops.

Thanks,
Srinivas



> 
>      Arnd
Zhang, Lixu May 30, 2024, 7:41 a.m. UTC | #4
>-----Original Message-----
>From: srinivas pandruvada <srinivas.pandruvada@linux.intel.com>
>Sent: Thursday, May 30, 2024 6:25 AM
>To: Arnd Bergmann <arnd@arndb.de>; Zhang, Lixu <lixu.zhang@intel.com>;
>Arnd Bergmann <arnd@kernel.org>; Jiri Kosina <jikos@kernel.org>; Benjamin
>Tissoires <bentiss@kernel.org>
>Cc: linux-input@vger.kernel.org; linux-kernel@vger.kernel.org
>Subject: Re: [PATCH 1/2] HID: intel-ish-hid: fix cache management mistake
>
>On Wed, 2024-05-29 at 09:06 +0200, Arnd Bergmann wrote:
>> On Wed, May 29, 2024, at 08:46, Zhang, Lixu wrote:
>> > >
>> >
>> > > +		dma_wmb();
>> > I tested it on the platform, but it didn't wok.
>> >
>>
>> What behavior do you see instead? 
Hi Arnd, please refer to the information below.

>> If the manual cache flush works
>> around a bug, that would indicate that the device itself is not
>> coherent and the dma_alloc_coherent() in the architecture is broken.
>
>Lixu,
>
>What happens if you remove manual cache flush in your code?
When the driver side sends the next start command, it receives an error response, which is likely because the bootloader failed to verify the firmware image.

Thanks,
Lixu

>It is possible that boot loader at this time not ready to do fully coherent ops.
>
>Thanks,
>Srinivas
>
>>      Arnd
Zhang, Lixu May 31, 2024, 8:51 a.m. UTC | #5
>-----Original Message-----
>From: Zhang, Lixu
>Sent: Thursday, May 30, 2024 3:42 PM
>To: srinivas pandruvada <srinivas.pandruvada@linux.intel.com>; Arnd
>Bergmann <arnd@arndb.de>; Arnd Bergmann <arnd@kernel.org>; Jiri Kosina
><jikos@kernel.org>; Benjamin Tissoires <bentiss@kernel.org>; Xu, Even
><even.xu@intel.com>
>Cc: linux-input@vger.kernel.org; linux-kernel@vger.kernel.org
>Subject: RE: [PATCH 1/2] HID: intel-ish-hid: fix cache management mistake
>
>>-----Original Message-----
>>From: srinivas pandruvada <srinivas.pandruvada@linux.intel.com>
>>Sent: Thursday, May 30, 2024 6:25 AM
>>To: Arnd Bergmann <arnd@arndb.de>; Zhang, Lixu <lixu.zhang@intel.com>;
>>Arnd Bergmann <arnd@kernel.org>; Jiri Kosina <jikos@kernel.org>;
>>Benjamin Tissoires <bentiss@kernel.org>
>>Cc: linux-input@vger.kernel.org; linux-kernel@vger.kernel.org
>>Subject: Re: [PATCH 1/2] HID: intel-ish-hid: fix cache management
>>mistake
>>
>>On Wed, 2024-05-29 at 09:06 +0200, Arnd Bergmann wrote:
>>> On Wed, May 29, 2024, at 08:46, Zhang, Lixu wrote:
>>> > >
>>> >
>>> > > +		dma_wmb();
>>> > I tested it on the platform, but it didn't wok.
>>> >
>>>
>>> What behavior do you see instead?
>Hi Arnd, please refer to the information below.
>
>>> If the manual cache flush works
>>> around a bug, that would indicate that the device itself is not
>>> coherent and the dma_alloc_coherent() in the architecture is broken.
>>
Hi Arnd,

Flush cache is necessary for some performance reason on this device.

Thanks,
Lixu
diff mbox series

Patch

diff --git a/drivers/hid/intel-ish-hid/ishtp/loader.c b/drivers/hid/intel-ish-hid/ishtp/loader.c
index 2785b04a2f5a..062d1b25eaa7 100644
--- a/drivers/hid/intel-ish-hid/ishtp/loader.c
+++ b/drivers/hid/intel-ish-hid/ishtp/loader.c
@@ -33,7 +33,6 @@ 
 
 #define dev_fmt(fmt) "ISH loader: " fmt
 
-#include <linux/cacheflush.h>
 #include <linux/container_of.h>
 #include <linux/dev_printk.h>
 #include <linux/dma-mapping.h>
@@ -175,10 +174,11 @@  static int prepare_dma_bufs(struct ishtp_device *dev,
 			return -ENOMEM;
 
 		fragment->fragment_tbl[i].ddr_adrs = cpu_to_le64(dma_addr);
+
+		memcpy(dma_bufs[i], ish_fw->data + offset, fragment->fragment_tbl[i].length);
+		dma_wmb();
 		fragment->fragment_tbl[i].length = clamp(ish_fw->size - offset, 0, fragment_size);
 		fragment->fragment_tbl[i].fw_off = offset;
-		memcpy(dma_bufs[i], ish_fw->data + offset, fragment->fragment_tbl[i].length);
-		clflush_cache_range(dma_bufs[i], fragment_size);
 
 		offset += fragment->fragment_tbl[i].length;
 	}