279 lines
7.0 KiB
Diff
279 lines
7.0 KiB
Diff
|
From 41a8983a6d1362aa5f62b57112d8e303f70fd032 Mon Sep 17 00:00:00 2001
|
||
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||
|
Date: Tue, 22 Jun 2021 22:12:12 +0200
|
||
|
Subject: [PATCH 418/464] cw1200: use kmalloc() allocation instead of stack
|
||
|
|
||
|
It turns out that if CONFIG_VMAP_STACK is enabled and src or dst is
|
||
|
memory allocated on stack, SDIO operations fail due to invalid memory
|
||
|
address conversion.
|
||
|
|
||
|
Fix that by using kmalloc() allocated memory for read/write 16/32
|
||
|
funtions.
|
||
|
|
||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||
|
---
|
||
|
drivers/net/wireless/st/cw1200/bh.c | 11 +++-
|
||
|
drivers/net/wireless/st/cw1200/hwio.c | 52 ++++++++++++---
|
||
|
drivers/net/wireless/st/cw1200/hwio.h | 93 +++++++++++++++++++++------
|
||
|
3 files changed, 126 insertions(+), 30 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/net/wireless/st/cw1200/bh.c b/drivers/net/wireless/st/cw1200/bh.c
|
||
|
index 3b4ded2ac801..ad90549f2e8b 100644
|
||
|
--- a/drivers/net/wireless/st/cw1200/bh.c
|
||
|
+++ b/drivers/net/wireless/st/cw1200/bh.c
|
||
|
@@ -415,9 +415,13 @@ static int cw1200_bh(void *arg)
|
||
|
int pending_tx = 0;
|
||
|
int tx_burst;
|
||
|
long status;
|
||
|
- u32 dummy;
|
||
|
+ u32 *dummy;
|
||
|
int ret;
|
||
|
|
||
|
+ dummy = kmalloc(sizeof(*dummy), GFP_KERNEL);
|
||
|
+ if (!dummy)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
for (;;) {
|
||
|
if (!priv->hw_bufs_used &&
|
||
|
priv->powersave_enabled &&
|
||
|
@@ -439,7 +443,7 @@ static int cw1200_bh(void *arg)
|
||
|
(atomic_read(&priv->bh_rx) == 0) &&
|
||
|
(atomic_read(&priv->bh_tx) == 0))
|
||
|
cw1200_reg_read(priv, ST90TDS_CONFIG_REG_ID,
|
||
|
- &dummy, sizeof(dummy));
|
||
|
+ dummy, sizeof(*dummy));
|
||
|
|
||
|
pr_debug("[BH] waiting ...\n");
|
||
|
status = wait_event_interruptible_timeout(priv->bh_wq, ({
|
||
|
@@ -601,5 +605,8 @@ static int cw1200_bh(void *arg)
|
||
|
priv->bh_error = 1;
|
||
|
/* TODO: schedule_work(recovery) */
|
||
|
}
|
||
|
+
|
||
|
+ kfree(dummy);
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
diff --git a/drivers/net/wireless/st/cw1200/hwio.c b/drivers/net/wireless/st/cw1200/hwio.c
|
||
|
index 3ba462de8e91..5521cb7f2233 100644
|
||
|
--- a/drivers/net/wireless/st/cw1200/hwio.c
|
||
|
+++ b/drivers/net/wireless/st/cw1200/hwio.c
|
||
|
@@ -66,33 +66,65 @@ static int __cw1200_reg_write(struct cw1200_common *priv, u16 addr,
|
||
|
static inline int __cw1200_reg_read_32(struct cw1200_common *priv,
|
||
|
u16 addr, u32 *val)
|
||
|
{
|
||
|
- __le32 tmp;
|
||
|
- int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0);
|
||
|
- *val = le32_to_cpu(tmp);
|
||
|
+ __le32 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ i = __cw1200_reg_read(priv, addr, tmp, sizeof(*tmp), 0);
|
||
|
+ *val = le32_to_cpu(*tmp);
|
||
|
+ kfree(tmp);
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
static inline int __cw1200_reg_write_32(struct cw1200_common *priv,
|
||
|
u16 addr, u32 val)
|
||
|
{
|
||
|
- __le32 tmp = cpu_to_le32(val);
|
||
|
- return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0);
|
||
|
+ __le32 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ *tmp = cpu_to_le32(val);
|
||
|
+ i = __cw1200_reg_write(priv, addr, tmp, sizeof(*tmp), 0);
|
||
|
+ kfree(tmp);
|
||
|
+ return i;
|
||
|
}
|
||
|
|
||
|
static inline int __cw1200_reg_read_16(struct cw1200_common *priv,
|
||
|
u16 addr, u16 *val)
|
||
|
{
|
||
|
- __le16 tmp;
|
||
|
- int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0);
|
||
|
- *val = le16_to_cpu(tmp);
|
||
|
+ __le16 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ i = __cw1200_reg_read(priv, addr, tmp, sizeof(*tmp), 0);
|
||
|
+ *val = le16_to_cpu(*tmp);
|
||
|
+ kfree(tmp);
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
static inline int __cw1200_reg_write_16(struct cw1200_common *priv,
|
||
|
u16 addr, u16 val)
|
||
|
{
|
||
|
- __le16 tmp = cpu_to_le16(val);
|
||
|
- return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0);
|
||
|
+ __le16 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ *tmp = cpu_to_le16(val);
|
||
|
+ i = __cw1200_reg_write(priv, addr, tmp, sizeof(*tmp), 0);
|
||
|
+ kfree(tmp);
|
||
|
+ return i;
|
||
|
}
|
||
|
|
||
|
int cw1200_reg_read(struct cw1200_common *priv, u16 addr, void *buf,
|
||
|
diff --git a/drivers/net/wireless/st/cw1200/hwio.h b/drivers/net/wireless/st/cw1200/hwio.h
|
||
|
index e2d0fb2d02ef..49387f43e37b 100644
|
||
|
--- a/drivers/net/wireless/st/cw1200/hwio.h
|
||
|
+++ b/drivers/net/wireless/st/cw1200/hwio.h
|
||
|
@@ -167,34 +167,65 @@ int cw1200_reg_write(struct cw1200_common *priv, u16 addr,
|
||
|
static inline int cw1200_reg_read_16(struct cw1200_common *priv,
|
||
|
u16 addr, u16 *val)
|
||
|
{
|
||
|
- __le32 tmp;
|
||
|
+ __le32 *tmp;
|
||
|
int i;
|
||
|
- i = cw1200_reg_read(priv, addr, &tmp, sizeof(tmp));
|
||
|
- *val = le32_to_cpu(tmp) & 0xfffff;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ i = cw1200_reg_read(priv, addr, tmp, sizeof(*tmp));
|
||
|
+ *val = le32_to_cpu(*tmp) & 0xfffff;
|
||
|
+ kfree(tmp);
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
static inline int cw1200_reg_write_16(struct cw1200_common *priv,
|
||
|
u16 addr, u16 val)
|
||
|
{
|
||
|
- __le32 tmp = cpu_to_le32((u32)val);
|
||
|
- return cw1200_reg_write(priv, addr, &tmp, sizeof(tmp));
|
||
|
+ __le32 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ *tmp = cpu_to_le32((u32)val);
|
||
|
+ i = cw1200_reg_write(priv, addr, tmp, sizeof(*tmp));
|
||
|
+ kfree(tmp);
|
||
|
+ return i;
|
||
|
}
|
||
|
|
||
|
static inline int cw1200_reg_read_32(struct cw1200_common *priv,
|
||
|
u16 addr, u32 *val)
|
||
|
{
|
||
|
- __le32 tmp;
|
||
|
- int i = cw1200_reg_read(priv, addr, &tmp, sizeof(tmp));
|
||
|
- *val = le32_to_cpu(tmp);
|
||
|
+ __le32 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ i = cw1200_reg_read(priv, addr, tmp, sizeof(*tmp));
|
||
|
+ *val = le32_to_cpu(*tmp);
|
||
|
+ kfree(tmp);
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
static inline int cw1200_reg_write_32(struct cw1200_common *priv,
|
||
|
u16 addr, u32 val)
|
||
|
{
|
||
|
- __le32 tmp = cpu_to_le32(val);
|
||
|
- return cw1200_reg_write(priv, addr, &tmp, sizeof(val));
|
||
|
+ __le32 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ *tmp = cpu_to_le32(val);
|
||
|
+ i = cw1200_reg_write(priv, addr, tmp, sizeof(val));
|
||
|
+ kfree(tmp);
|
||
|
+ return i;
|
||
|
}
|
||
|
|
||
|
int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf,
|
||
|
@@ -221,24 +252,50 @@ static inline int cw1200_ahb_read(struct cw1200_common *priv, u32 addr,
|
||
|
static inline int cw1200_apb_read_32(struct cw1200_common *priv,
|
||
|
u32 addr, u32 *val)
|
||
|
{
|
||
|
- __le32 tmp;
|
||
|
- int i = cw1200_apb_read(priv, addr, &tmp, sizeof(tmp));
|
||
|
- *val = le32_to_cpu(tmp);
|
||
|
+ __le32 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ i = cw1200_apb_read(priv, addr, tmp, sizeof(*tmp));
|
||
|
+ *val = le32_to_cpu(*tmp);
|
||
|
+ kfree(tmp);
|
||
|
+
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
static inline int cw1200_apb_write_32(struct cw1200_common *priv,
|
||
|
u32 addr, u32 val)
|
||
|
{
|
||
|
- __le32 tmp = cpu_to_le32(val);
|
||
|
- return cw1200_apb_write(priv, addr, &tmp, sizeof(val));
|
||
|
+ __le32 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ *tmp = cpu_to_le32(val);
|
||
|
+ i = cw1200_apb_write(priv, addr, tmp, sizeof(*tmp));
|
||
|
+ kfree(tmp);
|
||
|
+
|
||
|
+ return i;
|
||
|
}
|
||
|
static inline int cw1200_ahb_read_32(struct cw1200_common *priv,
|
||
|
u32 addr, u32 *val)
|
||
|
{
|
||
|
- __le32 tmp;
|
||
|
- int i = cw1200_ahb_read(priv, addr, &tmp, sizeof(tmp));
|
||
|
- *val = le32_to_cpu(tmp);
|
||
|
+ __le32 *tmp;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||
|
+ if (!tmp)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ i = cw1200_ahb_read(priv, addr, tmp, sizeof(*tmp));
|
||
|
+ *val = le32_to_cpu(*tmp);
|
||
|
+ kfree(tmp);
|
||
|
+
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.34.1
|
||
|
|