i3c master: GETMRL's 3rd byte is optional even with BCR_IBI_PAYLOAD
authorNicolas Pitre <npitre@baylibre.com>
Wed, 15 Apr 2020 20:30:01 +0000 (16:30 -0400)
committerBoris Brezillon <boris.brezillon@collabora.com>
Thu, 16 Apr 2020 12:27:46 +0000 (14:27 +0200)
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
drivers/i3c/master.c

index d79cd6d54b3a7c1688885b3d68a5c6eb65da683a..97f2e29265da789220cc727fd2990a0252d08b89 100644 (file)
@@ -1008,7 +1008,6 @@ static int i3c_master_getmrl_locked(struct i3c_master_controller *master,
                                    struct i3c_device_info *info)
 {
        struct i3c_ccc_cmd_dest dest;
-       unsigned int expected_len;
        struct i3c_ccc_mrl *mrl;
        struct i3c_ccc_cmd cmd;
        int ret;
@@ -1024,22 +1023,23 @@ static int i3c_master_getmrl_locked(struct i3c_master_controller *master,
        if (!(info->bcr & I3C_BCR_IBI_PAYLOAD))
                dest.payload.len -= 1;
 
-       expected_len = dest.payload.len;
        i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMRL, &dest, 1);
        ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
        if (ret)
                goto out;
 
-       if (dest.payload.len != expected_len) {
+       switch (dest.payload.len) {
+       case 3:
+               info->max_ibi_len = mrl->ibi_len;
+               fallthrough;
+       case 2:
+               info->max_read_len = be16_to_cpu(mrl->read_len);
+               break;
+       default:
                ret = -EIO;
                goto out;
        }
 
-       info->max_read_len = be16_to_cpu(mrl->read_len);
-
-       if (info->bcr & I3C_BCR_IBI_PAYLOAD)
-               info->max_ibi_len = mrl->ibi_len;
-
 out:
        i3c_ccc_cmd_dest_cleanup(&dest);