Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i3c master: GETMRL's 3rd byte is optional even with BCR_IBI_PAYLOAD

According to the I3C spec v1.1 document, GETMRL's payload is 2 bytes,
with an optional 3rd byte if the IBI private payload is larger than
1 byte. The whole GETMRL may also be optional so max_ibi_len already
defaults to 1 if BCR_IBI_PAYLOAD prior to the i3c_master_getmrl_locked()
call.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Link: https://lore.kernel.org/linux-i3c/nycvar.YSQ.7.76.2004151623060.2671@knanqh.ubzr

authored by

Nicolas Pitre and committed by
Boris Brezillon
b4203ce0 8f3d9f35

+8 -8
+8 -8
drivers/i3c/master.c
··· 1008 1008 struct i3c_device_info *info) 1009 1009 { 1010 1010 struct i3c_ccc_cmd_dest dest; 1011 - unsigned int expected_len; 1012 1011 struct i3c_ccc_mrl *mrl; 1013 1012 struct i3c_ccc_cmd cmd; 1014 1013 int ret; ··· 1023 1024 if (!(info->bcr & I3C_BCR_IBI_PAYLOAD)) 1024 1025 dest.payload.len -= 1; 1025 1026 1026 - expected_len = dest.payload.len; 1027 1027 i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMRL, &dest, 1); 1028 1028 ret = i3c_master_send_ccc_cmd_locked(master, &cmd); 1029 1029 if (ret) 1030 1030 goto out; 1031 1031 1032 - if (dest.payload.len != expected_len) { 1032 + switch (dest.payload.len) { 1033 + case 3: 1034 + info->max_ibi_len = mrl->ibi_len; 1035 + fallthrough; 1036 + case 2: 1037 + info->max_read_len = be16_to_cpu(mrl->read_len); 1038 + break; 1039 + default: 1033 1040 ret = -EIO; 1034 1041 goto out; 1035 1042 } 1036 - 1037 - info->max_read_len = be16_to_cpu(mrl->read_len); 1038 - 1039 - if (info->bcr & I3C_BCR_IBI_PAYLOAD) 1040 - info->max_ibi_len = mrl->ibi_len; 1041 1043 1042 1044 out: 1043 1045 i3c_ccc_cmd_dest_cleanup(&dest);