With introduction of vmap'ed stacks, stack parameters can no
longer be used for DMA and now leads to kernel panic.
It happens at several places for the wl1251 (e.g. when
accessed through SDIO) making it unuseable on e.g. the
OpenPandora.
We solve this by allocating temporary buffers or use wl1251_read32().
Tested on v5.18-rc5 with OpenPandora.
Fixes:
a1c510d0adc6 ("ARM: implement support for vmap'ed stacks")
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/1676021ae8b6d7aada0b1806fed99b1b8359bdc4.1651495112.git.hns@goldelico.com
msleep(1);
/* read from both event fields */
- wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector,
- sizeof(events_vector));
+ events_vector = wl1251_mem_read32(wl, wl->mbox_ptr[0]);
event = events_vector & mask;
- wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector,
- sizeof(events_vector));
+ events_vector = wl1251_mem_read32(wl, wl->mbox_ptr[1]);
event |= events_vector & mask;
} while (!event);
int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
{
- struct event_mailbox mbox;
+ struct event_mailbox *mbox;
int ret;
wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
if (mbox_num > 1)
return -EINVAL;
+ mbox = kmalloc(sizeof(*mbox), GFP_KERNEL);
+ if (!mbox) {
+ wl1251_error("can not allocate mbox buffer");
+ return -ENOMEM;
+ }
+
/* first we read the mbox descriptor */
- wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
- sizeof(struct event_mailbox));
+ wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], mbox,
+ sizeof(*mbox));
/* process the descriptor */
- ret = wl1251_event_process(wl, &mbox);
+ ret = wl1251_event_process(wl, mbox);
+ kfree(mbox);
+
if (ret < 0)
return ret;
u32 mem_start, u32 mem_size,
u32 reg_start, u32 reg_size)
{
- struct wl1251_partition partition[2];
+ struct wl1251_partition_set *partition;
+
+ partition = kmalloc(sizeof(*partition), GFP_KERNEL);
+ if (!partition) {
+ wl1251_error("can not allocate partition buffer");
+ return;
+ }
wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
mem_start, mem_size);
reg_start, reg_size);
}
- partition[0].start = mem_start;
- partition[0].size = mem_size;
- partition[1].start = reg_start;
- partition[1].size = reg_size;
+ partition->mem.start = mem_start;
+ partition->mem.size = mem_size;
+ partition->reg.start = reg_start;
+ partition->reg.size = reg_size;
wl->physical_mem_addr = mem_start;
wl->physical_reg_addr = reg_start;
wl->virtual_reg_addr = mem_size;
wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition,
- sizeof(partition));
+ sizeof(*partition));
+
+ kfree(partition);
}
void wl1251_tx_complete(struct wl1251 *wl)
{
int i, result_index, num_complete = 0, queue_len;
- struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
+ struct tx_result *result, *result_ptr;
unsigned long flags;
if (unlikely(wl->state != WL1251_STATE_ON))
return;
+ result = kmalloc_array(FW_TX_CMPLT_BLOCK_SIZE, sizeof(*result), GFP_KERNEL);
+ if (!result) {
+ wl1251_error("can not allocate result buffer");
+ return;
+ }
+
/* First we read the result */
- wl1251_mem_read(wl, wl->data_path->tx_complete_addr,
- result, sizeof(result));
+ wl1251_mem_read(wl, wl->data_path->tx_complete_addr, result,
+ FW_TX_CMPLT_BLOCK_SIZE * sizeof(*result));
result_index = wl->next_tx_complete;
- for (i = 0; i < ARRAY_SIZE(result); i++) {
+ for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) {
result_ptr = &result[result_index];
if (result_ptr->done_1 == 1 &&
}
+ kfree(result);
wl->next_tx_complete = result_index;
}