Skip to content

Commit b53e975

Browse files
billy-tsaialexandrebelloni
authored andcommitted
i3c: master: mipi-i3c-hci: Fix a kernel panic for accessing DAT_data.
The `i3c_master_bus_init` function may attach the I2C devices before the I3C bus initialization. In this flow, the DAT `alloc_entry`` will be used before the DAT `init`. Additionally, if the `i3c_master_bus_init` fails, the DAT `cleanup` will execute before the device is detached, which will execue DAT `free_entry` function. The above scenario can cause the driver to use DAT_data when it is NULL. Signed-off-by: Billy Tsai <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexandre Belloni <[email protected]>
1 parent 8911eae commit b53e975

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

drivers/i3c/master/mipi-i3c-hci/dat_v1.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,17 @@ static int hci_dat_v1_init(struct i3c_hci *hci)
6464
return -EOPNOTSUPP;
6565
}
6666

67-
/* use a bitmap for faster free slot search */
68-
hci->DAT_data = bitmap_zalloc(hci->DAT_entries, GFP_KERNEL);
69-
if (!hci->DAT_data)
70-
return -ENOMEM;
71-
72-
/* clear them */
73-
for (dat_idx = 0; dat_idx < hci->DAT_entries; dat_idx++) {
74-
dat_w0_write(dat_idx, 0);
75-
dat_w1_write(dat_idx, 0);
67+
if (!hci->DAT_data) {
68+
/* use a bitmap for faster free slot search */
69+
hci->DAT_data = bitmap_zalloc(hci->DAT_entries, GFP_KERNEL);
70+
if (!hci->DAT_data)
71+
return -ENOMEM;
72+
73+
/* clear them */
74+
for (dat_idx = 0; dat_idx < hci->DAT_entries; dat_idx++) {
75+
dat_w0_write(dat_idx, 0);
76+
dat_w1_write(dat_idx, 0);
77+
}
7678
}
7779

7880
return 0;
@@ -87,7 +89,13 @@ static void hci_dat_v1_cleanup(struct i3c_hci *hci)
8789
static int hci_dat_v1_alloc_entry(struct i3c_hci *hci)
8890
{
8991
unsigned int dat_idx;
92+
int ret;
9093

94+
if (!hci->DAT_data) {
95+
ret = hci_dat_v1_init(hci);
96+
if (ret)
97+
return ret;
98+
}
9199
dat_idx = find_first_zero_bit(hci->DAT_data, hci->DAT_entries);
92100
if (dat_idx >= hci->DAT_entries)
93101
return -ENOENT;
@@ -103,7 +111,8 @@ static void hci_dat_v1_free_entry(struct i3c_hci *hci, unsigned int dat_idx)
103111
{
104112
dat_w0_write(dat_idx, 0);
105113
dat_w1_write(dat_idx, 0);
106-
__clear_bit(dat_idx, hci->DAT_data);
114+
if (hci->DAT_data)
115+
__clear_bit(dat_idx, hci->DAT_data);
107116
}
108117

109118
static void hci_dat_v1_set_dynamic_addr(struct i3c_hci *hci,

0 commit comments

Comments
 (0)