Loading drivers/net/wireless/ath/wil6210/cfg80211.c +7 −3 Original line number Diff line number Diff line Loading @@ -942,7 +942,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, u64 *cookie) { const u8 *buf = params->buf; size_t len = params->len; size_t len = params->len, total; struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; bool tx_status = false; Loading @@ -967,7 +967,11 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, if (len < sizeof(struct ieee80211_hdr_3addr)) return -EINVAL; cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL); total = sizeof(*cmd) + len; if (total < len) return -EINVAL; cmd = kmalloc(total, GFP_KERNEL); if (!cmd) { rc = -ENOMEM; goto out; Loading @@ -977,7 +981,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, cmd->len = cpu_to_le16(len); memcpy(cmd->payload, buf, len); rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len, rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, total, WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); if (rc == 0) tx_status = !evt.evt.status; Loading drivers/net/wireless/ath/wil6210/fw_inc.c +38 −20 Original line number Diff line number Diff line Loading @@ -26,14 +26,17 @@ prefix_type, rowsize, \ groupsize, buf, len, ascii) #define FW_ADDR_CHECK(ioaddr, val, msg) do { \ ioaddr = wmi_buffer(wil, val); \ if (!ioaddr) { \ wil_err_fw(wil, "bad " msg ": 0x%08x\n", \ le32_to_cpu(val)); \ return -EINVAL; \ } \ } while (0) static bool wil_fw_addr_check(struct wil6210_priv *wil, void __iomem **ioaddr, __le32 val, u32 size, const char *msg) { *ioaddr = wmi_buffer_block(wil, val, size); if (!(*ioaddr)) { wil_err_fw(wil, "bad %s: 0x%08x\n", msg, le32_to_cpu(val)); return false; } return true; } /** * wil_fw_verify - verify firmware file validity Loading Loading @@ -160,7 +163,8 @@ static int fw_handle_data(struct wil6210_priv *wil, const void *data, return -EINVAL; } FW_ADDR_CHECK(dst, d->addr, "address"); if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) return -EINVAL; wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(d->addr), s); wil_memcpy_toio_32(dst, d->data, s); Loading Loading @@ -192,7 +196,8 @@ static int fw_handle_fill(struct wil6210_priv *wil, const void *data, return -EINVAL; } FW_ADDR_CHECK(dst, d->addr, "address"); if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) return -EINVAL; v = le32_to_cpu(d->value); wil_dbg_fw(wil, "fill [0x%08x] <== 0x%08x, %zu bytes\n", Loading Loading @@ -248,7 +253,8 @@ static int fw_handle_direct_write(struct wil6210_priv *wil, const void *data, u32 v = le32_to_cpu(block[i].value); u32 x, y; FW_ADDR_CHECK(dst, block[i].addr, "address"); if (!wil_fw_addr_check(wil, &dst, block[i].addr, 0, "address")) return -EINVAL; x = readl(dst); y = (x & m) | (v & ~m); Loading Loading @@ -314,10 +320,15 @@ static int fw_handle_gateway_data(struct wil6210_priv *wil, const void *data, wil_dbg_fw(wil, "gw write record [%3d] blocks, cmd 0x%08x\n", n, gw_cmd); FW_ADDR_CHECK(gwa_addr, d->gateway_addr_addr, "gateway_addr_addr"); FW_ADDR_CHECK(gwa_val, d->gateway_value_addr, "gateway_value_addr"); FW_ADDR_CHECK(gwa_cmd, d->gateway_cmd_addr, "gateway_cmd_addr"); FW_ADDR_CHECK(gwa_ctl, d->gateway_ctrl_address, "gateway_ctrl_address"); if (!wil_fw_addr_check(wil, &gwa_addr, d->gateway_addr_addr, 0, "gateway_addr_addr") || !wil_fw_addr_check(wil, &gwa_val, d->gateway_value_addr, 0, "gateway_value_addr") || !wil_fw_addr_check(wil, &gwa_cmd, d->gateway_cmd_addr, 0, "gateway_cmd_addr") || !wil_fw_addr_check(wil, &gwa_ctl, d->gateway_ctrl_address, 0, "gateway_ctrl_address")) return -EINVAL; wil_dbg_fw(wil, "gw addresses: addr 0x%08x val 0x%08x" " cmd 0x%08x ctl 0x%08x\n", Loading Loading @@ -373,12 +384,19 @@ static int fw_handle_gateway_data4(struct wil6210_priv *wil, const void *data, wil_dbg_fw(wil, "gw4 write record [%3d] blocks, cmd 0x%08x\n", n, gw_cmd); FW_ADDR_CHECK(gwa_addr, d->gateway_addr_addr, "gateway_addr_addr"); if (!wil_fw_addr_check(wil, &gwa_addr, d->gateway_addr_addr, 0, "gateway_addr_addr")) return -EINVAL; for (k = 0; k < ARRAY_SIZE(block->value); k++) FW_ADDR_CHECK(gwa_val[k], d->gateway_value_addr[k], "gateway_value_addr"); FW_ADDR_CHECK(gwa_cmd, d->gateway_cmd_addr, "gateway_cmd_addr"); FW_ADDR_CHECK(gwa_ctl, d->gateway_ctrl_address, "gateway_ctrl_address"); if (!wil_fw_addr_check(wil, &gwa_val[k], d->gateway_value_addr[k], 0, "gateway_value_addr")) return -EINVAL; if (!wil_fw_addr_check(wil, &gwa_cmd, d->gateway_cmd_addr, 0, "gateway_cmd_addr") || !wil_fw_addr_check(wil, &gwa_ctl, d->gateway_ctrl_address, 0, "gateway_ctrl_address")) return -EINVAL; wil_dbg_fw(wil, "gw4 addresses: addr 0x%08x cmd 0x%08x ctl 0x%08x\n", le32_to_cpu(d->gateway_addr_addr), Loading drivers/net/wireless/ath/wil6210/interrupt.c +21 −1 Original line number Diff line number Diff line Loading @@ -356,6 +356,25 @@ static void wil_cache_mbox_regs(struct wil6210_priv *wil) wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); } static bool wil_validate_mbox_regs(struct wil6210_priv *wil) { size_t min_size = sizeof(struct wil6210_mbox_hdr) + sizeof(struct wmi_cmd_hdr); if (wil->mbox_ctl.rx.entry_size < min_size) { wil_err(wil, "rx mbox entry too small (%d)\n", wil->mbox_ctl.rx.entry_size); return false; } if (wil->mbox_ctl.tx.entry_size < min_size) { wil_err(wil, "tx mbox entry too small (%d)\n", wil->mbox_ctl.tx.entry_size); return false; } return true; } static irqreturn_t wil6210_irq_misc(int irq, void *cookie) { struct wil6210_priv *wil = cookie; Loading Loading @@ -391,6 +410,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) if (isr & ISR_MISC_FW_READY) { wil_dbg_irq(wil, "IRQ: FW ready\n"); wil_cache_mbox_regs(wil); if (wil_validate_mbox_regs(wil)) set_bit(wil_status_mbox_ready, wil->status); /** * Actual FW ready indicated by the Loading drivers/net/wireless/ath/wil6210/wil6210.h +1 −0 Original line number Diff line number Diff line Loading @@ -866,6 +866,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); int wil_find_cid(struct wil6210_priv *wil, const u8 *mac); void wil_set_ethtoolops(struct net_device *ndev); void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr, u32 size); void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, Loading drivers/net/wireless/ath/wil6210/wmi.c +18 −3 Original line number Diff line number Diff line Loading @@ -141,13 +141,15 @@ static u32 wmi_addr_remap(u32 x) /** * Check address validity for WMI buffer; remap if needed * @ptr - internal (linker) fw/ucode address * @size - if non zero, validate the block does not * exceed the device memory (bar) * * Valid buffer should be DWORD aligned * * return address for accessing buffer from the host; * if buffer is not valid, return NULL. */ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr_, u32 size) { u32 off; u32 ptr = le32_to_cpu(ptr_); Loading @@ -162,10 +164,17 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) off = HOSTADDR(ptr); if (off > wil->bar_size - 4) return NULL; if (size && ((off + size > wil->bar_size) || (off + size < off))) return NULL; return wil->csr + off; } void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) { return wmi_buffer_block(wil, ptr_, 0); } /** * Check address validity */ Loading Loading @@ -223,7 +232,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) uint retry; int rc = 0; if (sizeof(cmd) + len > r->entry_size) { if (len > r->entry_size - sizeof(cmd)) { wil_err(wil, "WMI size too large: %d bytes, max is %d\n", (int)(sizeof(cmd) + len), r->entry_size); return -ERANGE; Loading Loading @@ -1406,8 +1415,14 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) }; int rc; u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len; struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL); struct wmi_set_appie_cmd *cmd; if (len < ie_len) { rc = -EINVAL; goto out; } cmd = kzalloc(len, GFP_KERNEL); if (!cmd) { rc = -ENOMEM; goto out; Loading Loading
drivers/net/wireless/ath/wil6210/cfg80211.c +7 −3 Original line number Diff line number Diff line Loading @@ -942,7 +942,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, u64 *cookie) { const u8 *buf = params->buf; size_t len = params->len; size_t len = params->len, total; struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; bool tx_status = false; Loading @@ -967,7 +967,11 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, if (len < sizeof(struct ieee80211_hdr_3addr)) return -EINVAL; cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL); total = sizeof(*cmd) + len; if (total < len) return -EINVAL; cmd = kmalloc(total, GFP_KERNEL); if (!cmd) { rc = -ENOMEM; goto out; Loading @@ -977,7 +981,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, cmd->len = cpu_to_le16(len); memcpy(cmd->payload, buf, len); rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len, rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, total, WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); if (rc == 0) tx_status = !evt.evt.status; Loading
drivers/net/wireless/ath/wil6210/fw_inc.c +38 −20 Original line number Diff line number Diff line Loading @@ -26,14 +26,17 @@ prefix_type, rowsize, \ groupsize, buf, len, ascii) #define FW_ADDR_CHECK(ioaddr, val, msg) do { \ ioaddr = wmi_buffer(wil, val); \ if (!ioaddr) { \ wil_err_fw(wil, "bad " msg ": 0x%08x\n", \ le32_to_cpu(val)); \ return -EINVAL; \ } \ } while (0) static bool wil_fw_addr_check(struct wil6210_priv *wil, void __iomem **ioaddr, __le32 val, u32 size, const char *msg) { *ioaddr = wmi_buffer_block(wil, val, size); if (!(*ioaddr)) { wil_err_fw(wil, "bad %s: 0x%08x\n", msg, le32_to_cpu(val)); return false; } return true; } /** * wil_fw_verify - verify firmware file validity Loading Loading @@ -160,7 +163,8 @@ static int fw_handle_data(struct wil6210_priv *wil, const void *data, return -EINVAL; } FW_ADDR_CHECK(dst, d->addr, "address"); if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) return -EINVAL; wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(d->addr), s); wil_memcpy_toio_32(dst, d->data, s); Loading Loading @@ -192,7 +196,8 @@ static int fw_handle_fill(struct wil6210_priv *wil, const void *data, return -EINVAL; } FW_ADDR_CHECK(dst, d->addr, "address"); if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) return -EINVAL; v = le32_to_cpu(d->value); wil_dbg_fw(wil, "fill [0x%08x] <== 0x%08x, %zu bytes\n", Loading Loading @@ -248,7 +253,8 @@ static int fw_handle_direct_write(struct wil6210_priv *wil, const void *data, u32 v = le32_to_cpu(block[i].value); u32 x, y; FW_ADDR_CHECK(dst, block[i].addr, "address"); if (!wil_fw_addr_check(wil, &dst, block[i].addr, 0, "address")) return -EINVAL; x = readl(dst); y = (x & m) | (v & ~m); Loading Loading @@ -314,10 +320,15 @@ static int fw_handle_gateway_data(struct wil6210_priv *wil, const void *data, wil_dbg_fw(wil, "gw write record [%3d] blocks, cmd 0x%08x\n", n, gw_cmd); FW_ADDR_CHECK(gwa_addr, d->gateway_addr_addr, "gateway_addr_addr"); FW_ADDR_CHECK(gwa_val, d->gateway_value_addr, "gateway_value_addr"); FW_ADDR_CHECK(gwa_cmd, d->gateway_cmd_addr, "gateway_cmd_addr"); FW_ADDR_CHECK(gwa_ctl, d->gateway_ctrl_address, "gateway_ctrl_address"); if (!wil_fw_addr_check(wil, &gwa_addr, d->gateway_addr_addr, 0, "gateway_addr_addr") || !wil_fw_addr_check(wil, &gwa_val, d->gateway_value_addr, 0, "gateway_value_addr") || !wil_fw_addr_check(wil, &gwa_cmd, d->gateway_cmd_addr, 0, "gateway_cmd_addr") || !wil_fw_addr_check(wil, &gwa_ctl, d->gateway_ctrl_address, 0, "gateway_ctrl_address")) return -EINVAL; wil_dbg_fw(wil, "gw addresses: addr 0x%08x val 0x%08x" " cmd 0x%08x ctl 0x%08x\n", Loading Loading @@ -373,12 +384,19 @@ static int fw_handle_gateway_data4(struct wil6210_priv *wil, const void *data, wil_dbg_fw(wil, "gw4 write record [%3d] blocks, cmd 0x%08x\n", n, gw_cmd); FW_ADDR_CHECK(gwa_addr, d->gateway_addr_addr, "gateway_addr_addr"); if (!wil_fw_addr_check(wil, &gwa_addr, d->gateway_addr_addr, 0, "gateway_addr_addr")) return -EINVAL; for (k = 0; k < ARRAY_SIZE(block->value); k++) FW_ADDR_CHECK(gwa_val[k], d->gateway_value_addr[k], "gateway_value_addr"); FW_ADDR_CHECK(gwa_cmd, d->gateway_cmd_addr, "gateway_cmd_addr"); FW_ADDR_CHECK(gwa_ctl, d->gateway_ctrl_address, "gateway_ctrl_address"); if (!wil_fw_addr_check(wil, &gwa_val[k], d->gateway_value_addr[k], 0, "gateway_value_addr")) return -EINVAL; if (!wil_fw_addr_check(wil, &gwa_cmd, d->gateway_cmd_addr, 0, "gateway_cmd_addr") || !wil_fw_addr_check(wil, &gwa_ctl, d->gateway_ctrl_address, 0, "gateway_ctrl_address")) return -EINVAL; wil_dbg_fw(wil, "gw4 addresses: addr 0x%08x cmd 0x%08x ctl 0x%08x\n", le32_to_cpu(d->gateway_addr_addr), Loading
drivers/net/wireless/ath/wil6210/interrupt.c +21 −1 Original line number Diff line number Diff line Loading @@ -356,6 +356,25 @@ static void wil_cache_mbox_regs(struct wil6210_priv *wil) wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); } static bool wil_validate_mbox_regs(struct wil6210_priv *wil) { size_t min_size = sizeof(struct wil6210_mbox_hdr) + sizeof(struct wmi_cmd_hdr); if (wil->mbox_ctl.rx.entry_size < min_size) { wil_err(wil, "rx mbox entry too small (%d)\n", wil->mbox_ctl.rx.entry_size); return false; } if (wil->mbox_ctl.tx.entry_size < min_size) { wil_err(wil, "tx mbox entry too small (%d)\n", wil->mbox_ctl.tx.entry_size); return false; } return true; } static irqreturn_t wil6210_irq_misc(int irq, void *cookie) { struct wil6210_priv *wil = cookie; Loading Loading @@ -391,6 +410,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) if (isr & ISR_MISC_FW_READY) { wil_dbg_irq(wil, "IRQ: FW ready\n"); wil_cache_mbox_regs(wil); if (wil_validate_mbox_regs(wil)) set_bit(wil_status_mbox_ready, wil->status); /** * Actual FW ready indicated by the Loading
drivers/net/wireless/ath/wil6210/wil6210.h +1 −0 Original line number Diff line number Diff line Loading @@ -866,6 +866,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); int wil_find_cid(struct wil6210_priv *wil, const u8 *mac); void wil_set_ethtoolops(struct net_device *ndev); void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr, u32 size); void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, Loading
drivers/net/wireless/ath/wil6210/wmi.c +18 −3 Original line number Diff line number Diff line Loading @@ -141,13 +141,15 @@ static u32 wmi_addr_remap(u32 x) /** * Check address validity for WMI buffer; remap if needed * @ptr - internal (linker) fw/ucode address * @size - if non zero, validate the block does not * exceed the device memory (bar) * * Valid buffer should be DWORD aligned * * return address for accessing buffer from the host; * if buffer is not valid, return NULL. */ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr_, u32 size) { u32 off; u32 ptr = le32_to_cpu(ptr_); Loading @@ -162,10 +164,17 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) off = HOSTADDR(ptr); if (off > wil->bar_size - 4) return NULL; if (size && ((off + size > wil->bar_size) || (off + size < off))) return NULL; return wil->csr + off; } void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) { return wmi_buffer_block(wil, ptr_, 0); } /** * Check address validity */ Loading Loading @@ -223,7 +232,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) uint retry; int rc = 0; if (sizeof(cmd) + len > r->entry_size) { if (len > r->entry_size - sizeof(cmd)) { wil_err(wil, "WMI size too large: %d bytes, max is %d\n", (int)(sizeof(cmd) + len), r->entry_size); return -ERANGE; Loading Loading @@ -1406,8 +1415,14 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) }; int rc; u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len; struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL); struct wmi_set_appie_cmd *cmd; if (len < ie_len) { rc = -EINVAL; goto out; } cmd = kzalloc(len, GFP_KERNEL); if (!cmd) { rc = -ENOMEM; goto out; Loading