2024-05-31 16:29:55

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH] [v2] HID: intel-ish-hid: fix endian-conversion

From: Arnd Bergmann <[email protected]>

The newly added file causes a ton of sparse warnings about the
incorrect use of __le32 and similar types:

drivers/hid/intel-ish-hid/ishtp/loader.h:41:23: error: invalid bitfield specifier for type restricted __le32.
drivers/hid/intel-ish-hid/ishtp/loader.h:42:27: error: invalid bitfield specifier for type restricted __le32.
drivers/hid/intel-ish-hid/ishtp/loader.h:43:24: error: invalid bitfield specifier for type restricted __le32.
drivers/hid/intel-ish-hid/ishtp/loader.h:44:24: error: invalid bitfield specifier for type restricted __le32.
drivers/hid/intel-ish-hid/ishtp/loader.h:45:22: error: invalid bitfield specifier for type restricted __le32.
drivers/hid/intel-ish-hid/ishtp/loader.c:172:33: warning: restricted __le32 degrades to integer
drivers/hid/intel-ish-hid/ishtp/loader.c:178:50: warning: incorrect type in assignment (different base types)
drivers/hid/intel-ish-hid/ishtp/loader.c:178:50: expected restricted __le32 [usertype] length
drivers/hid/intel-ish-hid/ishtp/loader.c:178:50: got unsigned long
drivers/hid/intel-ish-hid/ishtp/loader.c:179:50: warning: incorrect type in assignment (different base types)
drivers/hid/intel-ish-hid/ishtp/loader.c:179:50: expected restricted __le32 [usertype] fw_off
drivers/hid/intel-ish-hid/ishtp/loader.c:179:50: got unsigned int [usertype] offset
drivers/hid/intel-ish-hid/ishtp/loader.c:180:17: warning: cast from restricted __le32
drivers/hid/intel-ish-hid/ishtp/loader.c:183:24: warning: invalid assignment: +=
drivers/hid/intel-ish-hid/ishtp/loader.c:183:24: left side has type unsigned int
drivers/hid/intel-ish-hid/ishtp/loader.c:183:24: right side has type restricted __le32

Add the necessary conversions and use temporary variables where appropriate
to avoid converting back.

Fixes: 579a267e4617 ("HID: intel-ish-hid: Implement loading firmware from host feature")
Signed-off-by: Arnd Bergmann <[email protected]>
---
v2:
- fix minor issues introduced in rebasing
- rebase again on linux-next without the cache management patch
- fix up changelog text
---
drivers/hid/intel-ish-hid/ishtp/loader.c | 68 +++++++++++++-----------
drivers/hid/intel-ish-hid/ishtp/loader.h | 33 +++++++-----
2 files changed, 56 insertions(+), 45 deletions(-)

diff --git a/drivers/hid/intel-ish-hid/ishtp/loader.c b/drivers/hid/intel-ish-hid/ishtp/loader.c
index 2785b04a2f5a..d2ebf63d0b3e 100644
--- a/drivers/hid/intel-ish-hid/ishtp/loader.c
+++ b/drivers/hid/intel-ish-hid/ishtp/loader.c
@@ -84,8 +84,8 @@ static int loader_write_message(struct ishtp_device *dev, void *buf, int len)
static int loader_xfer_cmd(struct ishtp_device *dev, void *req, int req_len,
void *resp, int resp_len)
{
- struct loader_msg_header *req_hdr = req;
- struct loader_msg_header *resp_hdr = resp;
+ union loader_msg_header req_hdr;
+ union loader_msg_header resp_hdr;
struct device *devc = dev->devc;
int rv;

@@ -93,34 +93,37 @@ static int loader_xfer_cmd(struct ishtp_device *dev, void *req, int req_len,
dev->fw_loader_rx_size = resp_len;

rv = loader_write_message(dev, req, req_len);
+ req_hdr.val32 = le32_to_cpup(req);
+
if (rv < 0) {
- dev_err(devc, "write cmd %u failed:%d\n", req_hdr->command, rv);
+ dev_err(devc, "write cmd %u failed:%d\n", req_hdr.command, rv);
return rv;
}

/* Wait the ACK */
wait_event_interruptible_timeout(dev->wait_loader_recvd_msg, dev->fw_loader_received,
ISHTP_LOADER_TIMEOUT);
+ resp_hdr.val32 = le32_to_cpup(resp);
dev->fw_loader_rx_size = 0;
dev->fw_loader_rx_buf = NULL;
if (!dev->fw_loader_received) {
- dev_err(devc, "wait response of cmd %u timeout\n", req_hdr->command);
+ dev_err(devc, "wait response of cmd %u timeout\n", req_hdr.command);
return -ETIMEDOUT;
}

- if (!resp_hdr->is_response) {
- dev_err(devc, "not a response for %u\n", req_hdr->command);
+ if (!resp_hdr.is_response) {
+ dev_err(devc, "not a response for %u\n", req_hdr.command);
return -EBADMSG;
}

- if (req_hdr->command != resp_hdr->command) {
- dev_err(devc, "unexpected cmd response %u:%u\n", req_hdr->command,
- resp_hdr->command);
+ if (req_hdr.command != resp_hdr.command) {
+ dev_err(devc, "unexpected cmd response %u:%u\n", req_hdr.command,
+ resp_hdr.command);
return -EBADMSG;
}

- if (resp_hdr->status) {
- dev_err(devc, "cmd %u failed %u\n", req_hdr->command, resp_hdr->status);
+ if (resp_hdr.status) {
+ dev_err(devc, "cmd %u failed %u\n", req_hdr.command, resp_hdr.status);
return -EIO;
}

@@ -163,24 +166,26 @@ static void release_dma_bufs(struct ishtp_device *dev,
static int prepare_dma_bufs(struct ishtp_device *dev,
const struct firmware *ish_fw,
struct loader_xfer_dma_fragment *fragment,
- void **dma_bufs, u32 fragment_size)
+ void **dma_bufs, u32 fragment_size, u32 fragment_count)
{
dma_addr_t dma_addr;
u32 offset = 0;
+ u32 length;
int i;

- for (i = 0; i < fragment->fragment_cnt && offset < ish_fw->size; i++) {
+ for (i = 0; i < fragment_count && offset < ish_fw->size; i++) {
dma_bufs[i] = dma_alloc_coherent(dev->devc, fragment_size, &dma_addr, GFP_KERNEL);
if (!dma_bufs[i])
return -ENOMEM;

fragment->fragment_tbl[i].ddr_adrs = cpu_to_le64(dma_addr);
- 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);
+ length = clamp(ish_fw->size - offset, 0, fragment_size);
+ fragment->fragment_tbl[i].length = cpu_to_le32(length);
+ fragment->fragment_tbl[i].fw_off = cpu_to_le32(offset);
+ memcpy(dma_bufs[i], ish_fw->data + offset, length);
clflush_cache_range(dma_bufs[i], fragment_size);

- offset += fragment->fragment_tbl[i].length;
+ offset += length;
}

return 0;
@@ -208,17 +213,17 @@ void ishtp_loader_work(struct work_struct *work)
{
DEFINE_RAW_FLEX(struct loader_xfer_dma_fragment, fragment, fragment_tbl, FRAGMENT_MAX_NUM);
struct ishtp_device *dev = container_of(work, struct ishtp_device, work_fw_loader);
- struct loader_xfer_query query = {
- .header.command = LOADER_CMD_XFER_QUERY,
- };
- struct loader_start start = {
- .header.command = LOADER_CMD_START,
- };
+ union loader_msg_header query_hdr = { .command = LOADER_CMD_XFER_QUERY, };
+ union loader_msg_header start_hdr = { .command = LOADER_CMD_START, };
+ union loader_msg_header fragment_hdr = { .command = LOADER_CMD_XFER_FRAGMENT, };
+ struct loader_xfer_query query = { .header = cpu_to_le32(query_hdr.val32), };
+ struct loader_start start = { .header = cpu_to_le32(start_hdr.val32), };
union loader_recv_message recv_msg;
char *filename = dev->driver_data->fw_filename;
const struct firmware *ish_fw;
void *dma_bufs[FRAGMENT_MAX_NUM] = {};
u32 fragment_size;
+ u32 fragment_count;
int retry = ISHTP_LOADER_RETRY_TIMES;
int rv;

@@ -228,23 +233,24 @@ void ishtp_loader_work(struct work_struct *work)
return;
}

- fragment->fragment.header.command = LOADER_CMD_XFER_FRAGMENT;
- fragment->fragment.xfer_mode = LOADER_XFER_MODE_DMA;
- fragment->fragment.is_last = 1;
- fragment->fragment.size = ish_fw->size;
+ fragment->fragment.header = cpu_to_le32(fragment_hdr.val32);;
+ fragment->fragment.xfer_mode = cpu_to_le32(LOADER_XFER_MODE_DMA);
+ fragment->fragment.is_last = cpu_to_le32(1);
+ fragment->fragment.size = cpu_to_le32(ish_fw->size);
/* Calculate the size of a single DMA fragment */
fragment_size = PFN_ALIGN(DIV_ROUND_UP(ish_fw->size, FRAGMENT_MAX_NUM));
/* Calculate the count of DMA fragments */
- fragment->fragment_cnt = DIV_ROUND_UP(ish_fw->size, fragment_size);
+ fragment_count = DIV_ROUND_UP(ish_fw->size, fragment_size);
+ fragment->fragment_cnt = cpu_to_le32(fragment_count);

- rv = prepare_dma_bufs(dev, ish_fw, fragment, dma_bufs, fragment_size);
+ rv = prepare_dma_bufs(dev, ish_fw, fragment, dma_bufs, fragment_size, fragment_count);
if (rv) {
dev_err(dev->devc, "prepare DMA buffer failed.\n");
goto out;
}

do {
- query.image_size = ish_fw->size;
+ query.image_size = cpu_to_le32(ish_fw->size);
rv = loader_xfer_cmd(dev, &query, sizeof(query), recv_msg.raw_data,
sizeof(struct loader_xfer_query_ack));
if (rv)
@@ -257,7 +263,7 @@ void ishtp_loader_work(struct work_struct *work)
recv_msg.query_ack.version_build);

rv = loader_xfer_cmd(dev, fragment,
- struct_size(fragment, fragment_tbl, fragment->fragment_cnt),
+ struct_size(fragment, fragment_tbl, fragment_count),
recv_msg.raw_data, sizeof(struct loader_xfer_fragment_ack));
if (rv)
continue; /* try again if failed */
diff --git a/drivers/hid/intel-ish-hid/ishtp/loader.h b/drivers/hid/intel-ish-hid/ishtp/loader.h
index 7aa45ebc3f7b..308b96085a4d 100644
--- a/drivers/hid/intel-ish-hid/ishtp/loader.h
+++ b/drivers/hid/intel-ish-hid/ishtp/loader.h
@@ -30,19 +30,23 @@ struct work_struct;
#define LOADER_XFER_MODE_DMA BIT(0)

/**
- * struct loader_msg_header - ISHTP firmware loader message header
+ * union loader_msg_header - ISHTP firmware loader message header
* @command: Command type
* @is_response: Indicates if the message is a response
* @has_next: Indicates if there is a next message
* @reserved: Reserved for future use
* @status: Status of the message
- */
-struct loader_msg_header {
- __le32 command:7;
- __le32 is_response:1;
- __le32 has_next:1;
- __le32 reserved:15;
- __le32 status:8;
+ * @val32: entire header as a 32-bit value
+ */
+union loader_msg_header {
+ struct {
+ __u32 command:7;
+ __u32 is_response:1;
+ __u32 has_next:1;
+ __u32 reserved:15;
+ __u32 status:8;
+ };
+ __u32 val32;
};

/**
@@ -51,7 +55,7 @@ struct loader_msg_header {
* @image_size: Size of the image
*/
struct loader_xfer_query {
- struct loader_msg_header header;
+ __le32 header;
__le32 image_size;
};

@@ -103,7 +107,7 @@ struct loader_capability {
* @capability: Loader capability
*/
struct loader_xfer_query_ack {
- struct loader_msg_header header;
+ __le32 header;
__le16 version_major;
__le16 version_minor;
__le16 version_hotfix;
@@ -122,7 +126,7 @@ struct loader_xfer_query_ack {
* @is_last: Is last
*/
struct loader_xfer_fragment {
- struct loader_msg_header header;
+ __le32 header;
__le32 xfer_mode;
__le32 offset;
__le32 size;
@@ -134,7 +138,7 @@ struct loader_xfer_fragment {
* @header: Header of the message
*/
struct loader_xfer_fragment_ack {
- struct loader_msg_header header;
+ __le32 header;
};

/**
@@ -170,7 +174,7 @@ struct loader_xfer_dma_fragment {
* @header: Header of the message
*/
struct loader_start {
- struct loader_msg_header header;
+ __le32 header;
};

/**
@@ -178,10 +182,11 @@ struct loader_start {
* @header: Header of the message
*/
struct loader_start_ack {
- struct loader_msg_header header;
+ __le32 header;
};

union loader_recv_message {
+ __le32 header;
struct loader_xfer_query_ack query_ack;
struct loader_xfer_fragment_ack fragment_ack;
struct loader_start_ack start_ack;
--
2.39.2



2024-06-01 05:19:18

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] [v2] HID: intel-ish-hid: fix endian-conversion

Hi Arnd,

kernel test robot noticed the following build warnings:

[auto build test WARNING on hid/for-next]
[also build test WARNING on next-20240531]
[cannot apply to linus/master v6.10-rc1]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Arnd-Bergmann/HID-intel-ish-hid-fix-endian-conversion/20240601-003303
base: https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-next
patch link: https://lore.kernel.org/r/20240531162836.157891-1-arnd%40kernel.org
patch subject: [PATCH] [v2] HID: intel-ish-hid: fix endian-conversion
config: x86_64-buildonly-randconfig-002-20240601 (https://download.01.org/0day-ci/archive/20240601/[email protected]/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240601/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> drivers/hid/intel-ish-hid/ishtp/loader.c:170: warning: Function parameter or struct member 'fragment_count' not described in 'prepare_dma_bufs'


vim +170 drivers/hid/intel-ish-hid/ishtp/loader.c

579a267e4617d7 Zhang Lixu 2024-05-06 155
579a267e4617d7 Zhang Lixu 2024-05-06 156 /**
579a267e4617d7 Zhang Lixu 2024-05-06 157 * prepare_dma_bufs() - Prepare the DMA buffer for transferring firmware fragments
579a267e4617d7 Zhang Lixu 2024-05-06 158 * @dev: The ISHTP device
579a267e4617d7 Zhang Lixu 2024-05-06 159 * @ish_fw: The ISH firmware
579a267e4617d7 Zhang Lixu 2024-05-06 160 * @fragment: The ISHTP firmware fragment descriptor
579a267e4617d7 Zhang Lixu 2024-05-06 161 * @dma_bufs: The array of DMA fragment buffers
579a267e4617d7 Zhang Lixu 2024-05-06 162 * @fragment_size: The size of a single DMA fragment
579a267e4617d7 Zhang Lixu 2024-05-06 163 *
579a267e4617d7 Zhang Lixu 2024-05-06 164 * Return: 0 on success, negative error code on failure
579a267e4617d7 Zhang Lixu 2024-05-06 165 */
579a267e4617d7 Zhang Lixu 2024-05-06 166 static int prepare_dma_bufs(struct ishtp_device *dev,
579a267e4617d7 Zhang Lixu 2024-05-06 167 const struct firmware *ish_fw,
579a267e4617d7 Zhang Lixu 2024-05-06 168 struct loader_xfer_dma_fragment *fragment,
5180be24abbcc0 Arnd Bergmann 2024-05-31 169 void **dma_bufs, u32 fragment_size, u32 fragment_count)
579a267e4617d7 Zhang Lixu 2024-05-06 @170 {
2360497238261f Zhang Lixu 2024-05-23 171 dma_addr_t dma_addr;
579a267e4617d7 Zhang Lixu 2024-05-06 172 u32 offset = 0;
5180be24abbcc0 Arnd Bergmann 2024-05-31 173 u32 length;
579a267e4617d7 Zhang Lixu 2024-05-06 174 int i;
579a267e4617d7 Zhang Lixu 2024-05-06 175
5180be24abbcc0 Arnd Bergmann 2024-05-31 176 for (i = 0; i < fragment_count && offset < ish_fw->size; i++) {
2360497238261f Zhang Lixu 2024-05-23 177 dma_bufs[i] = dma_alloc_coherent(dev->devc, fragment_size, &dma_addr, GFP_KERNEL);
579a267e4617d7 Zhang Lixu 2024-05-06 178 if (!dma_bufs[i])
579a267e4617d7 Zhang Lixu 2024-05-06 179 return -ENOMEM;
579a267e4617d7 Zhang Lixu 2024-05-06 180
2360497238261f Zhang Lixu 2024-05-23 181 fragment->fragment_tbl[i].ddr_adrs = cpu_to_le64(dma_addr);
5180be24abbcc0 Arnd Bergmann 2024-05-31 182 length = clamp(ish_fw->size - offset, 0, fragment_size);
5180be24abbcc0 Arnd Bergmann 2024-05-31 183 fragment->fragment_tbl[i].length = cpu_to_le32(length);
5180be24abbcc0 Arnd Bergmann 2024-05-31 184 fragment->fragment_tbl[i].fw_off = cpu_to_le32(offset);
5180be24abbcc0 Arnd Bergmann 2024-05-31 185 memcpy(dma_bufs[i], ish_fw->data + offset, length);
579a267e4617d7 Zhang Lixu 2024-05-06 186 clflush_cache_range(dma_bufs[i], fragment_size);
579a267e4617d7 Zhang Lixu 2024-05-06 187
5180be24abbcc0 Arnd Bergmann 2024-05-31 188 offset += length;
579a267e4617d7 Zhang Lixu 2024-05-06 189 }
579a267e4617d7 Zhang Lixu 2024-05-06 190
579a267e4617d7 Zhang Lixu 2024-05-06 191 return 0;
579a267e4617d7 Zhang Lixu 2024-05-06 192 }
579a267e4617d7 Zhang Lixu 2024-05-06 193

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2024-06-03 02:58:37

by Zhang, Lixu

[permalink] [raw]
Subject: RE: [PATCH] [v2] HID: intel-ish-hid: fix endian-conversion

>-----Original Message-----
>From: Arnd Bergmann <[email protected]>
>Sent: Saturday, June 1, 2024 12:28 AM
>To: Srinivas Pandruvada <[email protected]>; Jiri Kosina
><[email protected]>; Benjamin Tissoires <[email protected]>; Zhang, Lixu
><[email protected]>
>Cc: Arnd Bergmann <[email protected]>; [email protected]; linux-
>[email protected]
>Subject: [PATCH] [v2] HID: intel-ish-hid: fix endian-conversion
>
>From: Arnd Bergmann <[email protected]>
>
>The newly added file causes a ton of sparse warnings about the incorrect use of
>__le32 and similar types:
>
>drivers/hid/intel-ish-hid/ishtp/loader.h:41:23: error: invalid bitfield specifier for
>type restricted __le32.
>drivers/hid/intel-ish-hid/ishtp/loader.h:42:27: error: invalid bitfield specifier for
>type restricted __le32.
>drivers/hid/intel-ish-hid/ishtp/loader.h:43:24: error: invalid bitfield specifier for
>type restricted __le32.
>drivers/hid/intel-ish-hid/ishtp/loader.h:44:24: error: invalid bitfield specifier for
>type restricted __le32.
>drivers/hid/intel-ish-hid/ishtp/loader.h:45:22: error: invalid bitfield specifier for
>type restricted __le32.
>drivers/hid/intel-ish-hid/ishtp/loader.c:172:33: warning: restricted __le32
>degrades to integer
>drivers/hid/intel-ish-hid/ishtp/loader.c:178:50: warning: incorrect type in
>assignment (different base types)
>drivers/hid/intel-ish-hid/ishtp/loader.c:178:50: expected restricted __le32
>[usertype] length
>drivers/hid/intel-ish-hid/ishtp/loader.c:178:50: got unsigned long
>drivers/hid/intel-ish-hid/ishtp/loader.c:179:50: warning: incorrect type in
>assignment (different base types)
>drivers/hid/intel-ish-hid/ishtp/loader.c:179:50: expected restricted __le32
>[usertype] fw_off
>drivers/hid/intel-ish-hid/ishtp/loader.c:179:50: got unsigned int [usertype]
>offset
>drivers/hid/intel-ish-hid/ishtp/loader.c:180:17: warning: cast from restricted
>__le32
>drivers/hid/intel-ish-hid/ishtp/loader.c:183:24: warning: invalid assignment: +=
>drivers/hid/intel-ish-hid/ishtp/loader.c:183:24: left side has type unsigned int
>drivers/hid/intel-ish-hid/ishtp/loader.c:183:24: right side has type restricted
>__le32
>
>Add the necessary conversions and use temporary variables where appropriate
>to avoid converting back.
>
>Fixes: 579a267e4617 ("HID: intel-ish-hid: Implement loading firmware from
>host feature")
>Signed-off-by: Arnd Bergmann <[email protected]>
>---
>v2:
> - fix minor issues introduced in rebasing
> - rebase again on linux-next without the cache management patch
> - fix up changelog text
>---

Thanks for your patch. I have tested it on LNL platform, it works fine.

Please fix the build warning reported by kernel test robot. https://lore.kernel.org/oe-kbuild-all/[email protected]/

drivers/hid/intel-ish-hid/ishtp/loader.c:170: warning: Function parameter or struct member 'fragment_count' not described in 'prepare_dma_bufs'

After that, please add my name.
Reviewed-by: Zhang Lixu <[email protected]>
Tested-by: Zhang Lixu <[email protected]>

Thanks,
Lixu

2024-06-03 03:10:46

by Zhang, Lixu

[permalink] [raw]
Subject: RE: [PATCH] [v2] HID: intel-ish-hid: fix endian-conversion

>-----Original Message-----
>From: Arnd Bergmann <[email protected]>
>Sent: Saturday, June 1, 2024 12:28 AM
>To: Srinivas Pandruvada <[email protected]>; Jiri Kosina
><[email protected]>; Benjamin Tissoires <[email protected]>; Zhang, Lixu
><[email protected]>
>Cc: Arnd Bergmann <[email protected]>; [email protected]; linux-
>[email protected]
>Subject: [PATCH] [v2] HID: intel-ish-hid: fix endian-conversion
>
>@@ -228,23 +233,24 @@ void ishtp_loader_work(struct work_struct *work)
> return;
> }
>
>- fragment->fragment.header.command =
>LOADER_CMD_XFER_FRAGMENT;
>- fragment->fragment.xfer_mode = LOADER_XFER_MODE_DMA;
>- fragment->fragment.is_last = 1;
>- fragment->fragment.size = ish_fw->size;
>+ fragment->fragment.header = cpu_to_le32(fragment_hdr.val32);;
s/;;/;/

>+ fragment->fragment.xfer_mode =
>cpu_to_le32(LOADER_XFER_MODE_DMA);
>+ fragment->fragment.is_last = cpu_to_le32(1);
>+ fragment->fragment.size = cpu_to_le32(ish_fw->size);
> /* Calculate the size of a single DMA fragment */
> fragment_size = PFN_ALIGN(DIV_ROUND_UP(ish_fw->size,