summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bluetooth/btintel_pcie.c8
-rw-r--r--drivers/bluetooth/btmtk.c7
-rw-r--r--drivers/bluetooth/btmtksdio.c24
-rw-r--r--drivers/bluetooth/btmtkuart.c20
-rw-r--r--drivers/bluetooth/btusb.c17
-rw-r--r--drivers/bluetooth/hci_qca.c14
-rw-r--r--drivers/dpll/dpll_netlink.c17
-rw-r--r--drivers/gpio/gpio-virtuser.c3
-rw-r--r--drivers/gpio/gpiolib-of.c6
-rw-r--r--drivers/gpio/gpiolib-shared.c9
-rw-r--r--drivers/net/dsa/mxl862xx/mxl862xx.c23
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c19
-rw-r--r--drivers/net/ethernet/cadence/macb_ptp.c9
-rw-r--r--drivers/net/ethernet/cortina/gemini.c2
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c3
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_txrx.c42
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_txrx.h9
-rw-r--r--drivers/net/ethernet/microchip/lan743x_main.c2
-rw-r--r--drivers/net/ethernet/socionext/netsec.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c99
-rw-r--r--drivers/net/fddi/skfp/skfddi.c3
-rw-r--r--drivers/net/phy/mediatek/mtk-phy-lib.c27
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c25
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/ahb.c51
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c4
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2100.c4
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2200.c9
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c12
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_rx.c6
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.c2
-rw-r--r--drivers/net/wireless/intersil/p54/eeprom.c22
-rw-r--r--drivers/net/wireless/marvell/libertas_tf/main.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c12
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/scan.c54
-rw-r--r--drivers/net/wireless/marvell/mwifiex/util.c10
-rw-r--r--drivers/net/wireless/microchip/wilc1000/cfg80211.c14
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan.c9
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mgmt.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c4
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim_main.c39
-rw-r--r--drivers/net/wireless/virtual/virt_wifi.c4
-rw-r--r--drivers/net/wwan/mhi_wwan_mbim.c28
-rw-r--r--drivers/net/wwan/t7xx/t7xx_netdev.c4
-rw-r--r--drivers/power/sequencing/Kconfig3
-rw-r--r--drivers/power/sequencing/core.c11
52 files changed, 496 insertions, 221 deletions
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 6d9649776ae7..6e6e2b19815c 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -404,6 +404,12 @@ static int btintel_pcie_send_sync(struct btintel_pcie_data *data,
if (tfd_index > txq->count)
return -ERANGE;
+ if (skb->len > BTINTEL_PCIE_BUFFER_SIZE - BTINTEL_PCIE_HCI_TYPE_LEN) {
+ bt_dev_err(hdev, "TX skb too large (%u > %u)", skb->len,
+ BTINTEL_PCIE_BUFFER_SIZE - BTINTEL_PCIE_HCI_TYPE_LEN);
+ return -EMSGSIZE;
+ }
+
/* Firmware raises alive interrupt on HCI_OP_RESET or
* BTINTEL_HCI_OP_RESET
*/
@@ -502,7 +508,7 @@ static int btintel_pcie_submit_rx(struct btintel_pcie_data *data)
frbd_index = data->ia.tr_hia[BTINTEL_PCIE_RXQ_NUM];
- if (frbd_index > rxq->count)
+ if (frbd_index >= rxq->count)
return -ERANGE;
/* Prepare for RX submit. It updates the FRBD with the address of DMA
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 26d525acd659..7ea8bcd8a7ec 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -721,7 +721,12 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
case BTMTK_WMT_FUNC_CTRL:
if (!skb_pull_data(data->evt_skb,
sizeof(wmt_evt_funcc->status))) {
- status = BTMTK_WMT_ON_UNDONE;
+ /* A plain enable/disable request is acked with just
+ * the WMT header and no trailing status word; the
+ * result is carried in the header's own flag byte.
+ */
+ status = wmt_evt->whdr.flag ? BTMTK_WMT_ON_UNDONE :
+ BTMTK_WMT_ON_DONE;
break;
}
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index 94aa60d9cc20..a15ae6598c66 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -217,7 +217,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
}
/* Parse and handle the return WMT event */
- wmt_evt = (struct btmtk_hci_wmt_evt *)bdev->evt_skb->data;
+ wmt_evt = skb_pull_data(bdev->evt_skb, sizeof(*wmt_evt));
+ if (!wmt_evt) {
+ bt_dev_err(hdev, "WMT event too short (%u bytes)",
+ bdev->evt_skb->len);
+ err = -EINVAL;
+ goto err_free_skb;
+ }
+
if (wmt_evt->whdr.op != hdr->op) {
bt_dev_err(hdev, "Wrong op received %d expected %d",
wmt_evt->whdr.op, hdr->op);
@@ -233,6 +240,17 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
status = BTMTK_WMT_PATCH_DONE;
break;
case BTMTK_WMT_FUNC_CTRL:
+ if (!skb_pull_data(bdev->evt_skb,
+ sizeof(wmt_evt_funcc->status))) {
+ /* A plain enable/disable request is acked with just
+ * the WMT header and no trailing status word; the
+ * result is carried in the header's own flag byte.
+ */
+ status = wmt_evt->whdr.flag ? BTMTK_WMT_ON_UNDONE :
+ BTMTK_WMT_ON_DONE;
+ break;
+ }
+
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
status = BTMTK_WMT_ON_DONE;
@@ -1244,10 +1262,8 @@ static int btmtksdio_shutdown(struct hci_dev *hdev)
wmt_params.status = NULL;
err = mtk_hci_wmt_sync(hdev, &wmt_params);
- if (err < 0) {
+ if (err < 0)
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
- return err;
- }
ignore_wmt_cmd:
pm_runtime_put_noidle(bdev->dev);
diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c
index 27aa48ff3ac2..4af6fbbbd302 100644
--- a/drivers/bluetooth/btmtkuart.c
+++ b/drivers/bluetooth/btmtkuart.c
@@ -151,7 +151,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
}
/* Parse and handle the return WMT event */
- wmt_evt = (struct btmtk_hci_wmt_evt *)bdev->evt_skb->data;
+ wmt_evt = skb_pull_data(bdev->evt_skb, sizeof(*wmt_evt));
+ if (!wmt_evt) {
+ bt_dev_err(hdev, "WMT event too short (%u bytes)",
+ bdev->evt_skb->len);
+ err = -EINVAL;
+ goto err_free_wc;
+ }
+
if (wmt_evt->whdr.op != hdr->op) {
bt_dev_err(hdev, "Wrong op received %d expected %d",
wmt_evt->whdr.op, hdr->op);
@@ -167,6 +174,17 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
status = BTMTK_WMT_PATCH_DONE;
break;
case BTMTK_WMT_FUNC_CTRL:
+ if (!skb_pull_data(bdev->evt_skb,
+ sizeof(wmt_evt_funcc->status))) {
+ /* A plain enable/disable request is acked with just
+ * the WMT header and no trailing status word; the
+ * result is carried in the header's own flag byte.
+ */
+ status = wmt_evt->whdr.flag ? BTMTK_WMT_ON_UNDONE :
+ BTMTK_WMT_ON_DONE;
+ break;
+ }
+
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
status = BTMTK_WMT_ON_DONE;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 002b9f975710..dc7191bf4234 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -71,6 +71,15 @@ static struct usb_driver btusb_driver;
#define BTUSB_BROKEN_EXT_SCAN BIT(29)
static const struct usb_device_id btusb_table[] = {
+ /*
+ * NXP IW610 (0471:0215): the composite device reports Bluetooth
+ * class at the whole-device level, so the generic entry below
+ * would also match this WiFi vendor interface. Ignore it here
+ * first so mwifiex-nxp can bind it instead.
+ */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0471, 0x0215, 0xff, 0xff, 0xff),
+ .driver_info = BTUSB_IGNORE },
+
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
@@ -477,6 +486,14 @@ static const struct usb_device_id quirks_table[] = {
{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
+ /*
+ * NXP IW610 BT interfaces (Marvell-lineage silicon, same quirk as
+ * the 0x1286 entries above). Scoped to the BT interface class,
+ * not just VID/PID -- see the btusb_table entry above.
+ */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0471, 0x0215, 0xe0, 0x01, 0x01),
+ .driver_info = BTUSB_MARVELL },
+
/* Intel Bluetooth devices */
{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_COMBINED },
{ USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_COMBINED },
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index faa964735adb..7089e9b639b2 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -2228,8 +2228,8 @@ static void qca_power_off(struct hci_uart *hu)
bool sw_ctrl_state;
struct qca_power *power;
- /* From this point we go into power off state. But serial port is
- * still open, stop queueing the IBS data and flush all the buffered
+ /* From this point we go into power off state. But serial port may
+ * still be open, stop queueing the IBS data and flush all the buffered
* data in skb's.
*/
spin_lock_irqsave(&qca->hci_ibs_lock, flags);
@@ -2251,8 +2251,14 @@ static void qca_power_off(struct hci_uart *hu)
case QCA_WCN3990:
case QCA_WCN3991:
case QCA_WCN3998:
- host_set_baudrate(hu, 2400);
- qca_send_power_pulse(hu, false);
+ /* Both of these write to the serial port which may have
+ * already been closed by hci_uart_close(), which closes
+ * the port if HCI_QUIRK_NON_PERSISTENT_SETUP is set.
+ */
+ if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
+ host_set_baudrate(hu, 2400);
+ qca_send_power_pulse(hu, false);
+ }
break;
default:
break;
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 523d76a5fd49..45365214fbef 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -1202,6 +1202,7 @@ dpll_pin_ref_sync_state_set(struct dpll_pin *pin,
const enum dpll_pin_state state,
struct netlink_ext_ack *extack)
{
+ void *pin_priv, *ref_sync_pin_priv;
const struct dpll_pin_ops *ops;
enum dpll_pin_state old_state;
struct dpll_pin *ref_sync_pin;
@@ -1230,9 +1231,15 @@ dpll_pin_ref_sync_state_set(struct dpll_pin *pin,
return -EOPNOTSUPP;
}
dpll = ref->dpll;
- ret = ops->ref_sync_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
- ref_sync_pin,
- dpll_pin_on_dpll_priv(dpll, ref_sync_pin),
+ pin_priv = dpll_pin_on_dpll_priv(dpll, pin);
+ ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin);
+ /* Pin may have been unregistered from this dpll already */
+ if (!ref_sync_pin_priv) {
+ NL_SET_ERR_MSG(extack,
+ "reference sync pin not registered with the dpll");
+ return -ENODEV;
+ }
+ ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin, ref_sync_pin_priv,
&old_state, extack);
if (ret) {
NL_SET_ERR_MSG(extack, "unable to get old reference sync state");
@@ -1241,9 +1248,7 @@ dpll_pin_ref_sync_state_set(struct dpll_pin *pin,
if (state == old_state)
return 0;
- ret = ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
- ref_sync_pin,
- dpll_pin_on_dpll_priv(dpll, ref_sync_pin),
+ ret = ops->ref_sync_set(pin, pin_priv, ref_sync_pin, ref_sync_pin_priv,
state, extack);
if (ret) {
NL_SET_ERR_MSG_FMT(extack,
diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c
index 449fb1aed24b..70ddccccc1c4 100644
--- a/drivers/gpio/gpio-virtuser.c
+++ b/drivers/gpio/gpio-virtuser.c
@@ -692,7 +692,8 @@ static int gpio_virtuser_interrupts_set(void *data, u64 val)
atomic_set(&ld->irq, irq);
} else {
irq = atomic_xchg(&ld->irq, 0);
- free_irq(irq, ld);
+ if (irq)
+ free_irq(irq, ld);
}
return 0;
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 940b566946ce..f36e4b171fa7 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -788,13 +788,13 @@ static int of_gpio_notify(struct notifier_block *nb, unsigned long action,
if (!of_property_read_bool(rd->dn, "gpio-hog"))
return NOTIFY_DONE; /* not for us */
- if (of_node_test_and_set_flag(rd->dn, OF_POPULATED))
- return NOTIFY_DONE;
-
gdev = of_find_gpio_device_by_node(rd->dn->parent);
if (!gdev)
return NOTIFY_DONE; /* not for us */
+ if (of_node_test_and_set_flag(rd->dn, OF_POPULATED))
+ return NOTIFY_DONE;
+
ret = gpiochip_add_hog(gpio_device_get_chip(gdev), of_fwnode_handle(rd->dn));
if (ret < 0) {
pr_err("%s: failed to add hogs for %pOF\n", __func__,
diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
index 495bd3d0ddf0..5f9623e40b0f 100644
--- a/drivers/gpio/gpiolib-shared.c
+++ b/drivers/gpio/gpiolib-shared.c
@@ -261,10 +261,13 @@ static int gpio_shared_of_traverse(struct device_node *curr)
con_id[con_id_len - suffix_len] = '\0';
}
- ref = gpio_shared_make_ref(fwnode_handle_get(of_fwnode_handle(curr)),
- con_id, args.args[1]);
- if (!ref)
+ struct fwnode_handle *curr_fwnode =
+ fwnode_handle_get(of_fwnode_handle(curr));
+ ref = gpio_shared_make_ref(curr_fwnode, con_id, args.args[1]);
+ if (!ref) {
+ fwnode_handle_put(curr_fwnode);
return -ENOMEM;
+ }
if (!list_empty(&entry->refs))
pr_debug("GPIO %u at %s is shared by multiple firmware nodes\n",
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx.c b/drivers/net/dsa/mxl862xx/mxl862xx.c
index cfa7e3e269a2..e05ad52cd297 100644
--- a/drivers/net/dsa/mxl862xx/mxl862xx.c
+++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
@@ -685,10 +685,22 @@ static int mxl862xx_setup(struct dsa_switch *ds)
if (ret)
return ret;
+ ret = mxl862xx_setup_mdio(ds);
+ if (ret)
+ return ret;
+
schedule_delayed_work(&priv->stats_work,
MXL862XX_STATS_POLL_INTERVAL);
- return mxl862xx_setup_mdio(ds);
+ return 0;
+}
+
+static void mxl862xx_teardown(struct dsa_switch *ds)
+{
+ struct mxl862xx_priv *priv = ds->priv;
+
+ set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
+ disable_delayed_work_sync(&priv->stats_work);
}
static int mxl862xx_port_state(struct dsa_switch *ds, int port, bool enable)
@@ -2047,9 +2059,7 @@ static void mxl862xx_get_stats64(struct dsa_switch *ds, int port,
spin_unlock_bh(&priv->ports[port].stats_lock);
- /* Trigger a fresh poll so the next read sees up-to-date counters.
- * No-op if the work is already pending, running, or teardown started.
- */
+ /* Trigger a fresh poll so the next read sees up-to-date counters. */
if (!test_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags))
schedule_delayed_work(&priv->stats_work, 0);
}
@@ -2057,6 +2067,7 @@ static void mxl862xx_get_stats64(struct dsa_switch *ds, int port,
static const struct dsa_switch_ops mxl862xx_switch_ops = {
.get_tag_protocol = mxl862xx_get_tag_protocol,
.setup = mxl862xx_setup,
+ .teardown = mxl862xx_teardown,
.port_setup = mxl862xx_port_setup,
.port_teardown = mxl862xx_port_teardown,
.phylink_get_caps = mxl862xx_phylink_get_caps,
@@ -2131,7 +2142,6 @@ static int mxl862xx_probe(struct mdio_device *mdiodev)
err = dsa_register_switch(ds);
if (err) {
set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
- cancel_delayed_work_sync(&priv->stats_work);
mxl862xx_host_shutdown(priv);
for (i = 0; i < MXL862XX_MAX_PORTS; i++)
cancel_work_sync(&priv->ports[i].host_flood_work);
@@ -2152,7 +2162,6 @@ static void mxl862xx_remove(struct mdio_device *mdiodev)
priv = ds->priv;
set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
- cancel_delayed_work_sync(&priv->stats_work);
dsa_unregister_switch(ds);
@@ -2181,7 +2190,7 @@ static void mxl862xx_shutdown(struct mdio_device *mdiodev)
dsa_switch_shutdown(ds);
set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
- cancel_delayed_work_sync(&priv->stats_work);
+ disable_delayed_work_sync(&priv->stats_work);
mxl862xx_host_shutdown(priv);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index a2305e6428d1..b916080f4ff1 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -749,8 +749,17 @@ static void bcmgenet_hfb_init(struct bcmgenet_priv *priv)
INIT_LIST_HEAD(&priv->rxnfc_rules[i].list);
priv->rxnfc_rules[i].state = BCMGENET_RXNFC_STATE_UNUSED;
}
+}
+
+static void bcmgenet_hfb_restore(struct bcmgenet_priv *priv)
+{
+ struct bcmgenet_rxnfc_rule *rule;
bcmgenet_hfb_clear(priv);
+
+ list_for_each_entry(rule, &priv->rxnfc_list, list)
+ if (rule->state != BCMGENET_RXNFC_STATE_UNUSED)
+ bcmgenet_hfb_create_rxnfc_filter(priv, rule);
}
static int bcmgenet_begin(struct net_device *dev)
@@ -3376,8 +3385,8 @@ static int bcmgenet_open(struct net_device *dev)
bcmgenet_set_hw_addr(priv, dev->dev_addr);
- /* HFB init */
- bcmgenet_hfb_init(priv);
+ /* Restore the filters, the MAC was reset above */
+ bcmgenet_hfb_restore(priv);
/* Reinitialize TDMA and RDMA and SW housekeeping */
ret = bcmgenet_init_dma(priv, true);
@@ -4075,6 +4084,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
/* Mii wait queue */
init_waitqueue_head(&priv->wq);
+ bcmgenet_hfb_init(priv);
INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task);
priv->clk_wol = devm_clk_get_optional(&priv->pdev->dev, "enet-wol");
@@ -4272,10 +4282,7 @@ static int bcmgenet_resume(struct device *d)
bcmgenet_set_hw_addr(priv, dev->dev_addr);
/* Restore hardware filters */
- bcmgenet_hfb_clear(priv);
- list_for_each_entry(rule, &priv->rxnfc_list, list)
- if (rule->state != BCMGENET_RXNFC_STATE_UNUSED)
- bcmgenet_hfb_create_rxnfc_filter(priv, rule);
+ bcmgenet_hfb_restore(priv);
/* Reinitialize TDMA and RDMA and SW housekeeping */
ret = bcmgenet_init_dma(priv, false);
diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c
index 6d9166389988..14ae57fa00cb 100644
--- a/drivers/net/ethernet/cadence/macb_ptp.c
+++ b/drivers/net/ethernet/cadence/macb_ptp.c
@@ -50,7 +50,12 @@ static int gem_tsu_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts,
spin_lock_irqsave(&bp->tsu_clk_lock, flags);
ptp_read_system_prets(sts);
+ /* explicit barriers are needed because gem_readl() is relaxed */
+ if (sts)
+ rmb();
first = gem_readl(bp, TN);
+ if (sts)
+ rmb();
ptp_read_system_postts(sts);
secl = gem_readl(bp, TSL);
sech = gem_readl(bp, TSH);
@@ -62,7 +67,11 @@ static int gem_tsu_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts,
* (assume all done within 1s)
*/
ptp_read_system_prets(sts);
+ if (sts)
+ rmb();
ts->tv_nsec = gem_readl(bp, TN);
+ if (sts)
+ rmb();
ptp_read_system_postts(sts);
secl = gem_readl(bp, TSL);
sech = gem_readl(bp, TSH);
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index f08de623e6f7..2dd2fa801829 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -1798,7 +1798,7 @@ static irqreturn_t gmac_irq(int irq, void *data)
if (val & (GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8))) {
spin_lock(&geth->irq_lock);
- writel(GMAC0_RXDERR_INT_BIT << (netdev->dev_id * 8),
+ writel(GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8),
geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
u64_stats_update_begin(&port->ir_stats_syncp);
++port->stats.rx_fifo_errors;
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index ccc24a1301f2..848ee655c6ea 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -5086,7 +5086,8 @@ static int mvpp2_change_mtu(struct net_device *dev, int mtu)
netdev_warn(dev, "mtu %d too high, switching to shared buffers", mtu);
mvpp2_bm_switch_buffers(priv, false);
}
- } else {
+ } else if (priv->hw_version >= MVPP22 &&
+ mvpp2_get_nrxqs(priv) * 2 <= MVPP2_BM_MAX_POOLS) {
bool jumbo = false;
int i;
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
index 401f8b8ae1ca..e7918d3f6aba 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
@@ -311,6 +311,29 @@ fbnic_rx_csum(u64 rcd, struct sk_buff *skb, struct fbnic_ring *rcq,
}
}
+static void fbnic_tx_doorbell(struct fbnic_ring *ring, __le64 *meta)
+{
+ *meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_COMPLETION);
+ ring->deferred_meta = -1;
+
+ /* Force DMA writes to flush before writing to tail */
+ dma_wmb();
+
+ writel(ring->tail, ring->doorbell);
+}
+
+/* Packets handed to us with xmit_more set are left in the ring without a
+ * doorbell, and without a completion request, in the expectation that the
+ * packet ending the burst will ring for all of them. If that packet gets
+ * dropped instead we have to ring here, otherwise the descriptors sit in
+ * the ring until the next transmit, which may never come.
+ */
+static void fbnic_tx_flush_doorbell(struct fbnic_ring *ring)
+{
+ if (ring->deferred_meta >= 0)
+ fbnic_tx_doorbell(ring, &ring->desc[ring->deferred_meta]);
+}
+
static bool
fbnic_tx_map(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)
{
@@ -378,14 +401,10 @@ fbnic_tx_map(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)
/* Verify there is room for another packet */
fbnic_maybe_stop_tx(skb->dev, ring, FBNIC_MAX_SKB_DESC);
- if (fbnic_tx_sent_queue(skb, ring)) {
- *meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_COMPLETION);
-
- /* Force DMA writes to flush before writing to tail */
- dma_wmb();
-
- writel(tail, ring->doorbell);
- }
+ if (fbnic_tx_sent_queue(skb, ring))
+ fbnic_tx_doorbell(ring, meta);
+ else
+ ring->deferred_meta = meta - ring->desc;
return false;
dma_error:
@@ -425,8 +444,10 @@ fbnic_xmit_frame_ring(struct sk_buff *skb, struct fbnic_ring *ring)
* otherwise try next time
*/
desc_needed = skb_shinfo(skb)->nr_frags + 10;
- if (fbnic_maybe_stop_tx(skb->dev, ring, desc_needed))
+ if (fbnic_maybe_stop_tx(skb->dev, ring, desc_needed)) {
+ fbnic_tx_flush_doorbell(ring);
return NETDEV_TX_BUSY;
+ }
*meta = cpu_to_le64(FBNIC_TWD_FLAG_DEST_MAC);
@@ -447,6 +468,8 @@ fbnic_xmit_frame_ring(struct sk_buff *skb, struct fbnic_ring *ring)
err_free:
dev_kfree_skb_any(skb);
err_count:
+ fbnic_tx_flush_doorbell(ring);
+
u64_stats_update_begin(&ring->stats.syncp);
ring->stats.dropped++;
u64_stats_update_end(&ring->stats.syncp);
@@ -2491,6 +2514,7 @@ static void fbnic_enable_twq0(struct fbnic_ring *twq)
fbnic_ring_wr32(twq, FBNIC_QUEUE_TWQ0_CTL, FBNIC_QUEUE_TWQ_CTL_RESET);
twq->tail = 0;
twq->head = 0;
+ twq->deferred_meta = -1;
/* Store descriptor ring address and size */
fbnic_ring_wr32(twq, FBNIC_QUEUE_TWQ0_BAL, lower_32_bits(twq->dma));
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
index e03c9d2c38dc..f5899446dcc5 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
@@ -128,9 +128,14 @@ struct fbnic_ring {
/* Rx BDQs only */
struct page_pool *page_pool;
- /* Deferred_head is used to cache the head for TWQ1 if
+ /* TWQ0 only, index of the meta descriptor of the last packet
+ * placed in the ring without ringing the doorbell, -1 if the
+ * doorbell is in sync with the tail.
+ */
+ s32 deferred_meta;
+
+ /* TCQ only, used to cache the head for TWQ1 if
* an attempt is made to clean TWQ1 with zero napi_budget.
- * We do not use it for any other ring.
*/
s32 deferred_head;
};
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 24ae56a3c9ed..82d3ec20ba25 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -2604,7 +2604,7 @@ process_extension:
rx->adapter->netdev);
if (rx->adapter->netdev->features & NETIF_F_RXCSUM) {
if (!is_ice && !is_tce && !is_icsm)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ rx->skb_head->ip_summed = CHECKSUM_UNNECESSARY;
}
netdev_dbg(netdev, "sending %d byte frame to OS",
rx->skb_head->len);
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index d14a6584473c..79a0a324c921 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -2149,6 +2149,7 @@ pm_disable:
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
free_ndev:
+ of_node_put(priv->phy_np);
free_netdev(ndev);
dev_err(&pdev->dev, "init failed\n");
@@ -2166,6 +2167,7 @@ static void netsec_remove(struct platform_device *pdev)
netif_napi_del(&priv->napi);
pm_runtime_disable(&pdev->dev);
+ of_node_put(priv->phy_np);
free_netdev(priv->ndev);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 04dafec021b4..9314bcb85c22 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -494,7 +494,7 @@ struct stmmac_ops {
#define stmmac_set_arp_offload(__priv, __args...) \
stmmac_do_void_callback(__priv, mac, set_arp_offload, __args)
#define stmmac_fpe_map_preemption_class(__priv, __args...) \
- stmmac_do_void_callback(__priv, mac, fpe_map_preemption_class, __args)
+ stmmac_do_callback(__priv, mac, fpe_map_preemption_class, __args)
/* PTP and HW Timer helpers */
struct stmmac_hwtimestamp {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 154cc0c7623d..1be5310ca766 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -1016,8 +1016,6 @@ static int stmmac_get_ts_info(struct net_device *dev,
if (priv->ptp_clock)
info->phc_index = ptp_clock_index(priv->ptp_clock);
- else
- info->phc_index = 0;
info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 62c3441911e7..1fb5f804ea23 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -4513,16 +4513,16 @@ static int stmmac_tso_get_num_desc(struct stmmac_tx_queue *tx_q,
*/
static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ unsigned int first_entry, entry, tx_packets, proto_hdr_len;
struct dma_desc *desc, *first, *mss_desc = NULL;
struct stmmac_priv *priv = netdev_priv(dev);
- unsigned int first_entry, entry, tx_packets;
struct stmmac_txq_stats *txq_stats;
int i, first_tx, nfrags, ndesc;
struct stmmac_tx_queue *tx_q;
bool set_ic, is_last_segment;
u32 pay_len, mss, queue;
- u8 proto_hdr_len, hdr;
dma_addr_t des;
+ u8 hdr;
nfrags = skb_shinfo(skb)->nr_frags;
queue = skb_get_queue_mapping(skb);
@@ -4570,7 +4570,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (netif_msg_tx_queued(priv)) {
- pr_info("%s: hdrlen %d, hdr_len %d, pay_len %d, mss %d\n",
+ pr_info("%s: hdrlen %d, hdr_len %u, pay_len %d, mss %d\n",
__func__, hdr, proto_hdr_len, pay_len, mss);
pr_info("\tskb->len %d, skb->data_len %d\n", skb->len,
skb->data_len);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 14cabe76e53e..42a00446e9b4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -970,7 +970,7 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
struct netlink_ext_ack *extack = qopt->mqprio.extack;
struct timespec64 time, current_time, qopt_time;
ktime_t current_time_ns;
- int i, ret = 0;
+ int err, i, ret = 0;
u64 ctr;
if (qopt->base_time < 0)
@@ -1120,9 +1120,9 @@ disable:
mutex_unlock(&priv->est_lock);
}
- stmmac_fpe_map_preemption_class(priv, priv->dev, extack, 0);
+ err = stmmac_fpe_map_preemption_class(priv, priv->dev, extack, 0);
- return ret;
+ return qopt->cmd == TAPRIO_CMD_DESTROY ? err : ret;
}
static void tc_taprio_stats(struct stmmac_priv *priv,
@@ -1237,58 +1237,99 @@ static int tc_query_caps(struct stmmac_priv *priv,
}
}
-static void stmmac_reset_tc_mqprio(struct net_device *ndev,
- struct netlink_ext_ack *extack)
+static int stmmac_set_ndev_tcs(struct net_device *ndev, u8 ntc,
+ struct netdev_tc_txq *tc_to_txq)
+{
+ int i, err;
+
+ netdev_reset_tc(ndev);
+ if (!ntc)
+ return 0;
+
+ err = netdev_set_num_tc(ndev, ntc);
+ if (err)
+ return err;
+
+ for (i = 0; i < ntc; i++) {
+ u16 count, offset;
+
+ count = tc_to_txq[i].count;
+ offset = tc_to_txq[i].offset;
+ netdev_set_tc_queue(ndev, i, count, offset);
+ }
+
+ return 0;
+}
+
+static int stmmac_reset_tc_mqprio(struct net_device *ndev,
+ struct netlink_ext_ack *extack)
{
struct stmmac_priv *priv = netdev_priv(ndev);
netdev_reset_tc(ndev);
netif_set_real_num_tx_queues(ndev, priv->plat->tx_queues_to_use);
- stmmac_fpe_map_preemption_class(priv, ndev, extack, 0);
+
+ return stmmac_fpe_map_preemption_class(priv, ndev, extack, 0);
}
static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,
struct tc_mqprio_qopt_offload *mqprio)
{
+ unsigned int ndev_num_tx_queues, num_tx_queues = 0;
+ struct netdev_tc_txq ndev_tc_to_txq[TC_MAX_QUEUE];
+ struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE] = {};
struct netlink_ext_ack *extack = mqprio->extack;
struct tc_mqprio_qopt *qopt = &mqprio->qopt;
- u32 offset, count, num_stack_tx_queues = 0;
struct net_device *ndev = priv->dev;
- u32 num_tc = qopt->num_tc;
- int err;
-
- if (!num_tc) {
- stmmac_reset_tc_mqprio(ndev, extack);
- return 0;
- }
+ u8 ndev_prio_tc_map[TC_BITMASK + 1];
+ int i, err, ndev_ntc;
- err = netdev_set_num_tc(ndev, num_tc);
- if (err)
- return err;
+ if (!qopt->num_tc)
+ return stmmac_reset_tc_mqprio(ndev, extack);
- for (u32 tc = 0; tc < num_tc; tc++) {
- offset = qopt->offset[tc];
- count = qopt->count[tc];
- num_stack_tx_queues += count;
+ if (qopt->num_tc > ARRAY_SIZE(tc_to_txq))
+ return -EINVAL;
- err = netdev_set_tc_queue(ndev, tc, count, offset);
- if (err)
- goto err_reset_tc;
+ /* save current tc values for reset */
+ ndev_ntc = netdev_get_num_tc(ndev);
+ for (i = 0; i < ARRAY_SIZE(ndev->tc_to_txq); i++)
+ ndev_tc_to_txq[i].combined =
+ READ_ONCE(ndev->tc_to_txq[i].combined);
+ for (i = 0; i < ARRAY_SIZE(ndev_prio_tc_map); i++)
+ ndev_prio_tc_map[i] = READ_ONCE(ndev->prio_tc_map[i]);
+
+ for (i = 0; i < qopt->num_tc; i++) {
+ tc_to_txq[i] = (struct netdev_tc_txq) {
+ .count = qopt->count[i],
+ .offset = qopt->offset[i],
+ };
+ num_tx_queues += qopt->count[i];
}
- err = netif_set_real_num_tx_queues(ndev, num_stack_tx_queues);
+ err = stmmac_set_ndev_tcs(ndev, qopt->num_tc, tc_to_txq);
+ if (err)
+ goto error_reset_tc;
+
+ ndev_num_tx_queues = ndev->real_num_tx_queues;
+ err = netif_set_real_num_tx_queues(ndev, num_tx_queues);
if (err)
- goto err_reset_tc;
+ goto error_reset_tc;
err = stmmac_fpe_map_preemption_class(priv, ndev, extack,
mqprio->preemptible_tcs);
if (err)
- goto err_reset_tc;
+ goto error_reset_num_tx_queues;
return 0;
-err_reset_tc:
- stmmac_reset_tc_mqprio(ndev, extack);
+error_reset_num_tx_queues:
+ if (netif_set_real_num_tx_queues(ndev, ndev_num_tx_queues))
+ netdev_warn(ndev, "Failed to restore %u TX queues\n",
+ ndev_num_tx_queues);
+error_reset_tc:
+ stmmac_set_ndev_tcs(ndev, ndev_ntc, ndev_tc_to_txq);
+ for (i = 0; i < ARRAY_SIZE(ndev_prio_tc_map); i++)
+ netdev_set_prio_tc_map(ndev, i, ndev_prio_tc_map[i]);
return err;
}
diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c
index a273362c9e70..feea7baa4816 100644
--- a/drivers/net/fddi/skfp/skfddi.c
+++ b/drivers/net/fddi/skfp/skfddi.c
@@ -928,7 +928,8 @@ static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr)
dev_addr_set(dev, p_sockaddr->sa_data);
spin_lock_irqsave(&bp->DriverLock, Flags);
- ResetAdapter(smc);
+ if (netif_running(dev))
+ ResetAdapter(smc);
spin_unlock_irqrestore(&bp->DriverLock, Flags);
return 0; /* always return zero */
diff --git a/drivers/net/phy/mediatek/mtk-phy-lib.c b/drivers/net/phy/mediatek/mtk-phy-lib.c
index dfd0f4e439a2..608072fbfde9 100644
--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
@@ -156,20 +156,27 @@ int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
if (!rules)
return 0;
- if (on & on_set)
+ /* TRIGGER_NETDEV_LINK must not be reported together with any of the
+ * per-speed rules, the netdev trigger rejects that combination.
+ * on_set holds every speed this LED can indicate and is what
+ * mtk_phy_led_hw_ctrl_set() programs for TRIGGER_NETDEV_LINK, so
+ * report the speed independent rule only when they are all on.
+ */
+ if ((on & on_set) == on_set) {
*rules |= BIT(TRIGGER_NETDEV_LINK);
+ } else {
+ if (on & MTK_PHY_LED_ON_LINK10)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_10);
- if (on & MTK_PHY_LED_ON_LINK10)
- *rules |= BIT(TRIGGER_NETDEV_LINK_10);
+ if (on & MTK_PHY_LED_ON_LINK100)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_100);
- if (on & MTK_PHY_LED_ON_LINK100)
- *rules |= BIT(TRIGGER_NETDEV_LINK_100);
+ if (on & MTK_PHY_LED_ON_LINK1000)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
- if (on & MTK_PHY_LED_ON_LINK1000)
- *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
-
- if (on & MTK_PHY_LED_ON_LINK2500)
- *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
+ if (on & MTK_PHY_LED_ON_LINK2500)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
+ }
if (on & MTK_PHY_LED_ON_FDX)
*rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 2d55cdc4d165..ae91b57c8422 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -873,6 +873,22 @@ static int ath11k_mac_set_kickout(struct ath11k_vif *arvif)
return 0;
}
+static void ath11k_mac_station_cleanup(struct ieee80211_sta *sta)
+{
+ struct ath11k_sta *arsta;
+
+ if (!sta)
+ return;
+
+ arsta = ath11k_sta_to_arsta(sta);
+
+ kfree(arsta->tx_stats);
+ arsta->tx_stats = NULL;
+
+ kfree(arsta->rx_stats);
+ arsta->rx_stats = NULL;
+}
+
void ath11k_mac_peer_cleanup_all(struct ath11k *ar)
{
struct ath11k_peer *peer, *tmp;
@@ -885,6 +901,7 @@ void ath11k_mac_peer_cleanup_all(struct ath11k *ar)
list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
ath11k_peer_rx_tid_cleanup(ar, peer);
ath11k_peer_rhash_delete(ab, peer);
+ ath11k_mac_station_cleanup(peer->sta);
list_del(&peer->list);
kfree(peer);
}
@@ -9892,7 +9909,6 @@ static int ath11k_mac_station_remove(struct ath11k *ar,
{
struct ath11k_base *ab = ar->ab;
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
- struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
int ret;
if (ab->hw_params.vdev_start_delay &&
@@ -9916,12 +9932,7 @@ static int ath11k_mac_station_remove(struct ath11k *ar,
sta->addr, arvif->vdev_id);
ath11k_mac_dec_num_stations(arvif, sta);
-
- kfree(arsta->tx_stats);
- arsta->tx_stats = NULL;
-
- kfree(arsta->rx_stats);
- arsta->rx_stats = NULL;
+ ath11k_mac_station_cleanup(sta);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/ahb.c b/drivers/net/wireless/ath/ath12k/wifi7/ahb.c
index 98a6606ffd76..6e9e9034cba1 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/ahb.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/ahb.c
@@ -15,21 +15,6 @@
#include "dp.h"
#include "core.h"
-/*
- * Node name to UserPD ID mapping
- *
- * The io_start field is used for additional validation when the reg
- * property is present in the device tree. If io_start is 0, only
- * node_name matching is performed.
- *
- * For platforms where not all WiFi nodes have a 'reg' property, set
- * io_start to 0 for those entries. The driver will match purely by
- * node name in such cases.
- */
-static const struct ath12k_ahb_userpd_map ath12k_wifi7_ahb_userpd_map[] = {
- { .io_start = 0x0c000000, .node_name = "wifi", .upd_id = ATH12K_AHB_USERPD_ID_0 },
-};
-
static const struct ath12k_ahb_desc ath12k_wifi7_ahb_desc[] = {
[ATH12K_HW_IPQ5332_HW10] = {
.hw_rev = ATH12K_HW_IPQ5332_HW10,
@@ -55,40 +40,6 @@ static const struct of_device_id ath12k_wifi7_ahb_of_match[] = {
MODULE_DEVICE_TABLE(of, ath12k_wifi7_ahb_of_match);
-/*
- * ath12k_wifi7_ahb_get_userpd_id - Resolve UserPD ID from DT properties
- * @ab: ath12k base structure
- *
- * Returns: UserPD ID (1-based) on success, 0 on failure
- *
- * Resolution logic:
- * 1. If reg property exist in DT, get userpd_id from io_start
- * 2. If reg property is absent, get userpd_id from DT node name
- * 3. Return 0 if no match found (probe will fail)
- */
-static u32 ath12k_wifi7_ahb_get_userpd_id(struct ath12k_base *ab)
-{
- const struct ath12k_ahb_userpd_map *map;
- struct resource *res;
- size_t i;
-
- res = platform_get_resource(ab->pdev, IORESOURCE_MEM, 0);
-
- for (i = 0; i < ARRAY_SIZE(ath12k_wifi7_ahb_userpd_map); i++) {
- map = &ath12k_wifi7_ahb_userpd_map[i];
-
- if (res) {
- if (map->io_start && map->io_start == res->start)
- return map->upd_id;
- } else if (map->node_name &&
- of_node_name_eq(ab->dev->of_node, map->node_name)) {
- return map->upd_id;
- }
- }
-
- return 0;
-}
-
static int ath12k_wifi7_ahb_probe(struct platform_device *pdev)
{
const struct ath12k_ahb_desc *desc;
@@ -106,7 +57,7 @@ static int ath12k_wifi7_ahb_probe(struct platform_device *pdev)
ab->hw_rev = desc->hw_rev;
ab->hif.ops = desc->ops;
ab_ahb->scm_auth_enabled = desc->auth_enabled;
- ab_ahb->userpd_id = ath12k_wifi7_ahb_get_userpd_id(ab);
+ ab_ahb->userpd_id = ATH12K_AHB_USERPD_ID_0;
if (!ab_ahb->userpd_id)
return -EOPNOTSUPP;
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 44020ec265fb..801f1218ef89 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -1055,7 +1055,7 @@ void wcn36xx_dxe_deinit(struct wcn36xx *wcn)
free_irq(wcn->tx_irq, wcn);
free_irq(wcn->rx_irq, wcn);
- timer_delete(&wcn->tx_ack_timer);
+ timer_shutdown_sync(&wcn->tx_ack_timer);
if (wcn->tx_ack_skb) {
ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index dad6f4563d14..d2ae67985606 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -555,6 +555,8 @@ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
if (type == ETH_P_PAE) {
atomic_dec(&ifp->pend_8021x_cnt);
+ /* Order the decrement before waitqueue_active() */
+ smp_mb__after_atomic();
if (waitqueue_active(&ifp->pend_8021x_wait))
wake_up(&ifp->pend_8021x_wait);
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c
index 545eb9aae966..6d5098f6f00f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c
@@ -198,7 +198,7 @@ brcmf_cyw_external_auth(struct wiphy *wiphy, struct net_device *dev,
{
struct brcmf_if *ifp;
struct brcmf_pub *drvr;
- struct brcmf_auth_req_status_le auth_status;
+ struct brcmf_auth_req_status_le auth_status = {};
int ret = 0;
brcmf_dbg(TRACE, "Enter\n");
@@ -206,6 +206,9 @@ brcmf_cyw_external_auth(struct wiphy *wiphy, struct net_device *dev,
ifp = netdev_priv(dev);
drvr = ifp->drvr;
if (params->status == WLAN_STATUS_SUCCESS) {
+ if (params->pmkid)
+ memcpy(auth_status.pmkid, params->pmkid,
+ WLAN_PMKID_LEN);
auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_SUCCESS);
} else {
bphy_err(drvr, "External authentication failed: status=%d\n",
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
index 6255d673d2d3..c1a2318d7ea6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
@@ -1571,6 +1571,10 @@ void brcms_free_timer(struct brcms_timer *t)
/* delete the timer in case it is active */
brcms_del_timer(t);
+ /* Ensure the callback has finished before freeing the timer
+ * structure, since brcms_del_timer() uses non-synchronous cancel.
+ */
+ cancel_delayed_work_sync(&t->dly_wrk);
if (wl->timers == t) {
wl->timers = wl->timers->next;
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index 2b8a23865bfb..43b4e432956b 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -2712,7 +2712,9 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
break;
}
#endif
- if (stats.len < sizeof(struct libipw_hdr_3addr))
+ if (sq->drv[i].frame_size <
+ sizeof(struct libipw_hdr_3addr) ||
+ sq->drv[i].frame_size > IPW_RX_NIC_BUFFER_LENGTH)
break;
switch (WLAN_FC_GET_TYPE(le16_to_cpu(u->rx_data.header.frame_ctl))) {
case IEEE80211_FTYPE_MGMT:
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index 4bc9bb406e8e..8249d493ee22 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -8322,6 +8322,15 @@ static void ipw_rx(struct ipw_priv *priv)
break;
}
+ if (unlikely(le16_to_cpu(pkt->u.frame.length) >
+ IPW_RX_BUF_SIZE -
+ IPW_RX_FRAME_SIZE)) {
+ IPW_DEBUG_DROP("Received oversized packet. Dropping.\n");
+ priv->net_dev->stats.rx_errors++;
+ priv->wstats.discard.misc++;
+ break;
+ }
+
switch (WLAN_FC_GET_TYPE
(le16_to_cpu(header->frame_ctl))) {
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c
index 24bb28ab7a49..2b0cf0ec496a 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c
@@ -474,14 +474,16 @@ static int libipw_michael_mic_verify(struct sk_buff *skb, int keyidx,
int hdr_len, void *priv)
{
struct libipw_tkip_data *tkey = priv;
- u8 mic[8];
+ u8 mic[MICHAEL_MIC_LEN];
- if (!tkey->key_set)
+ if (!tkey->key_set || skb->len < hdr_len + MICHAEL_MIC_LEN)
return -1;
michael_mic(&tkey->key[24], (struct ieee80211_hdr *)skb->data,
- skb->data + hdr_len, skb->len - 8 - hdr_len, mic);
- if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
+ skb->data + hdr_len,
+ skb->len - MICHAEL_MIC_LEN - hdr_len, mic);
+ if (memcmp(mic, skb->data + skb->len - MICHAEL_MIC_LEN,
+ MICHAEL_MIC_LEN) != 0) {
struct ieee80211_hdr *hdr;
hdr = (struct ieee80211_hdr *)skb->data;
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
@@ -499,7 +501,7 @@ static int libipw_michael_mic_verify(struct sk_buff *skb, int keyidx,
tkey->rx_iv32 = tkey->rx_iv32_new;
tkey->rx_iv16 = tkey->rx_iv16_new;
- skb_trim(skb, skb->len - 8);
+ skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
return 0;
}
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
index c8841f9b9ad9..424349a6935e 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
@@ -1209,6 +1209,9 @@ static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_as
struct libipw_network *network = &network_resp;
struct net_device *dev = ieee->dev;
+ if (stats->len < sizeof(*frame))
+ return 1;
+
network->flags = 0;
network->qos_data.active = 0;
network->qos_data.supported = 0;
@@ -1421,6 +1424,9 @@ static void libipw_process_probe_response(struct libipw_device
#endif
unsigned long flags;
+ if (stats->len < sizeof(*beacon))
+ return;
+
LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
info_element->len, info_element->data,
beacon->header.addr3,
diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c
index 0bb807ff8edf..e5113c6b2d5c 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.c
+++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -2326,7 +2326,7 @@ il_dealloc_bcast_stations(struct il_priv *il)
if (!(il->stations[i].used & IL_STA_BCAST))
continue;
- il->stations[i].used &= ~IL_STA_UCODE_ACTIVE;
+ il->stations[i].used = 0;
il->num_stations--;
if (WARN_ON(il->num_stations < 0))
il->num_stations = 0;
diff --git a/drivers/net/wireless/intersil/p54/eeprom.c b/drivers/net/wireless/intersil/p54/eeprom.c
index 95580921d933..0475222d54fc 100644
--- a/drivers/net/wireless/intersil/p54/eeprom.c
+++ b/drivers/net/wireless/intersil/p54/eeprom.c
@@ -414,17 +414,22 @@ free:
}
static int p54_convert_rev0(struct ieee80211_hw *dev,
- struct pda_pa_curve_data *curve_data)
+ struct pda_pa_curve_data *curve_data, size_t len)
{
struct p54_common *priv = dev->priv;
struct p54_pa_curve_data_sample *dst;
struct pda_pa_curve_data_sample_rev0 *src;
+ size_t needed = curve_data->channels *
+ (sizeof(*src) * curve_data->points_per_channel + 2);
size_t cd_len = sizeof(*curve_data) +
(curve_data->points_per_channel*sizeof(*dst) + 2) *
curve_data->channels;
unsigned int i, j;
void *source, *target;
+ if (len < sizeof(*curve_data) + needed)
+ return -EINVAL;
+
priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len,
GFP_KERNEL);
if (!priv->curve_data)
@@ -466,17 +471,22 @@ static int p54_convert_rev0(struct ieee80211_hw *dev,
}
static int p54_convert_rev1(struct ieee80211_hw *dev,
- struct pda_pa_curve_data *curve_data)
+ struct pda_pa_curve_data *curve_data, size_t len)
{
struct p54_common *priv = dev->priv;
struct p54_pa_curve_data_sample *dst;
struct pda_pa_curve_data_sample_rev1 *src;
+ size_t needed = curve_data->channels *
+ (sizeof(*src) * curve_data->points_per_channel + 3);
size_t cd_len = sizeof(*curve_data) +
(curve_data->points_per_channel*sizeof(*dst) + 2) *
curve_data->channels;
unsigned int i, j;
void *source, *target;
+ if (len < sizeof(*curve_data) + needed)
+ return -EINVAL;
+
priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data),
GFP_KERNEL);
if (!priv->curve_data)
@@ -763,6 +773,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
case PDR_PRISM_PA_CAL_CURVE_DATA: {
struct pda_pa_curve_data *curve_data =
(struct pda_pa_curve_data *)entry->data;
+
if (data_len < sizeof(*curve_data)) {
err = -EINVAL;
goto err;
@@ -770,10 +781,10 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
switch (curve_data->cal_method_rev) {
case 0:
- err = p54_convert_rev0(dev, curve_data);
+ err = p54_convert_rev0(dev, curve_data, data_len);
break;
case 1:
- err = p54_convert_rev1(dev, curve_data);
+ err = p54_convert_rev1(dev, curve_data, data_len);
break;
default:
wiphy_err(dev->wiphy,
@@ -801,7 +812,8 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
break;
case PDR_INTERFACE_LIST:
tmp = entry->data;
- while ((u8 *)tmp < entry->data + data_len) {
+ while ((u8 *)tmp + sizeof(struct exp_if) <=
+ entry->data + data_len) {
struct exp_if *exp_if = tmp;
if (exp_if->if_id == cpu_to_le16(IF_ID_ISL39000))
synth = le16_to_cpu(exp_if->variant);
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
index 42be6fa22f9c..411f075b6186 100644
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -173,8 +173,8 @@ static int lbtf_init_adapter(struct lbtf_private *priv)
static void lbtf_free_adapter(struct lbtf_private *priv)
{
lbtf_deb_enter(LBTF_DEB_MAIN);
- lbtf_free_cmd_buffer(priv);
timer_delete_sync(&priv->command_timer);
+ lbtf_free_cmd_buffer(priv);
lbtf_deb_leave(LBTF_DEB_MAIN);
}
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 7a1ba32f1fb3..936939ea9c47 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -4277,6 +4277,7 @@ mwifiex_cfg80211_authenticate(struct wiphy *wiphy,
struct mwifiex_adapter *adapter = priv->adapter;
struct sk_buff *skb;
u16 pkt_len, auth_alg;
+ size_t frame_len;
int ret;
struct mwifiex_ieee80211_mgmt *mgmt;
struct mwifiex_txinfo *tx_info;
@@ -4349,10 +4350,17 @@ mwifiex_cfg80211_authenticate(struct wiphy *wiphy,
mwifiex_cancel_scan(adapter);
- pkt_len = (u16)req->ie_len + req->auth_data_len +
+ frame_len = req->ie_len + req->auth_data_len +
MWIFIEX_MGMT_HEADER_LEN + MWIFIEX_AUTH_BODY_LEN;
if (req->auth_data_len >= 4)
- pkt_len -= 4;
+ frame_len -= 4;
+
+ if (frame_len > U16_MAX) {
+ mwifiex_dbg(priv->adapter, ERROR,
+ "auth frame too long: %zu bytes\n", frame_len);
+ return -EINVAL;
+ }
+ pkt_len = frame_len;
skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +
MWIFIEX_MGMT_FRAME_HEADER_SIZE +
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index a760de191fce..a9425e9a94f4 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -3068,7 +3068,7 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
ret);
for (j = 0; j < i; j++)
free_irq(card->msix_entries[j].vector,
- &card->msix_ctx[i]);
+ &card->msix_ctx[j]);
pci_disable_msix(pdev);
} else {
mwifiex_dbg(adapter, MSG, "MSIx enabled!");
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index 97c0ec3b822e..bdd4b8465863 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -104,12 +104,24 @@ has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key)
* a given oui in PTK.
*/
static u8
-mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
+mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui, int ie_len)
{
+ const size_t ptk_body_offset = offsetof(struct ie_body, ptk_body);
u8 count;
+ /* ie_len is the number of bytes available at iebody. Keep it signed
+ * and reject a negative (underflowed) length before the unsigned
+ * comparisons below, so a small or zero IE length cannot wrap.
+ */
+ if (ie_len < 0 || (size_t)ie_len < ptk_body_offset)
+ return MWIFIEX_OUI_NOT_PRESENT;
+
count = iebody->ptk_cnt[0];
+ /* Reject an OUI count whose list would run past the element. */
+ if (ptk_body_offset + count * sizeof(iebody->ptk_body) > (size_t)ie_len)
+ return MWIFIEX_OUI_NOT_PRESENT;
+
/* There could be multiple OUIs for PTK hence
1) Take the length.
2) Check all the OUIs for AES.
@@ -143,11 +155,14 @@ mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
u8 ret = MWIFIEX_OUI_NOT_PRESENT;
if (has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
+ int ie_len = (int)bss_desc->bcn_rsn_ie->ieee_hdr.len -
+ RSN_GTK_OUI_OFFSET;
+
iebody = (struct ie_body *)
(((u8 *) bss_desc->bcn_rsn_ie->data) +
RSN_GTK_OUI_OFFSET);
oui = &mwifiex_rsn_oui[cipher][0];
- ret = mwifiex_search_oui_in_ie(iebody, oui);
+ ret = mwifiex_search_oui_in_ie(iebody, oui, ie_len);
if (ret)
return ret;
}
@@ -169,10 +184,14 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
u8 ret = MWIFIEX_OUI_NOT_PRESENT;
if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) {
+ int ie_len = (int)bss_desc->bcn_wpa_ie->vend_hdr.len -
+ (int)sizeof(bss_desc->bcn_wpa_ie->vend_hdr.oui) -
+ WPA_GTK_OUI_OFFSET;
+
iebody = (struct ie_body *)((u8 *)bss_desc->bcn_wpa_ie->data +
WPA_GTK_OUI_OFFSET);
oui = &mwifiex_wpa_oui[cipher][0];
- ret = mwifiex_search_oui_in_ie(iebody, oui);
+ ret = mwifiex_search_oui_in_ie(iebody, oui, ie_len);
if (ret)
return ret;
}
@@ -2096,6 +2115,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
u32 bytes_left;
u32 idx;
u32 tlv_buf_size;
+ size_t fixed_size;
struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
struct chan_band_param_set *chan_band;
u8 is_bgscan_resp;
@@ -2111,6 +2131,14 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
else
scan_rsp = &resp->params.scan_resp;
+ scan_resp_size = le16_to_cpu(resp->size);
+ fixed_size = scan_rsp->bss_desc_and_tlv_buffer - (u8 *)resp;
+ if (scan_resp_size < fixed_size) {
+ mwifiex_dbg(adapter, ERROR,
+ "SCAN_RESP: response is too short\n");
+ ret = -1;
+ goto check_next_scan;
+ }
if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
mwifiex_dbg(adapter, ERROR,
@@ -2128,8 +2156,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
"info: SCAN_RESP: bss_descript_size %d\n",
bytes_left);
- scan_resp_size = le16_to_cpu(resp->size);
-
mwifiex_dbg(adapter, INFO,
"info: SCAN_RESP: returned %d APs before parsing\n",
scan_rsp->number_of_sets);
@@ -2137,15 +2163,17 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
bss_info = scan_rsp->bss_desc_and_tlv_buffer;
/*
- * The size of the TLV buffer is equal to the entire command response
- * size (scan_resp_size) minus the fixed fields (sizeof()'s), the
- * BSS Descriptions (bss_descript_size as bytesLef) and the command
- * response header (S_DS_GEN)
+ * The TLV buffer follows the command-specific fixed fields and the BSS
+ * descriptions. Background-scan responses have an additional fixed
+ * field before scan_rsp, which is included in fixed_size.
*/
- tlv_buf_size = scan_resp_size - (bytes_left
- + sizeof(scan_rsp->bss_descript_size)
- + sizeof(scan_rsp->number_of_sets)
- + S_DS_GEN);
+ if (bytes_left > scan_resp_size - fixed_size) {
+ mwifiex_dbg(adapter, ERROR,
+ "SCAN_RESP: BSS data exceeds response\n");
+ ret = -1;
+ goto check_next_scan;
+ }
+ tlv_buf_size = scan_resp_size - fixed_size - bytes_left;
tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
bss_desc_and_tlv_buffer +
diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c
index 7d3631d21223..71305efb77ac 100644
--- a/drivers/net/wireless/marvell/mwifiex/util.c
+++ b/drivers/net/wireless/marvell/mwifiex/util.c
@@ -317,10 +317,16 @@ mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
switch (stype) {
case IEEE80211_STYPE_ACTION:
- category = *(payload + sizeof(struct ieee80211_hdr));
+ if (len < sizeof(*ieee_hdr) + 1)
+ return -1;
+
+ category = *(payload + sizeof(*ieee_hdr));
switch (category) {
case WLAN_CATEGORY_PUBLIC:
- action_code = *(payload + sizeof(struct ieee80211_hdr)
+ if (len < sizeof(*ieee_hdr) + 2)
+ return -1;
+
+ action_code = *(payload + sizeof(*ieee_hdr)
+ 1);
if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
addr2 = ieee_hdr->addr2;
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
index bb2748a19329..9ad21d41e999 100644
--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
@@ -1058,6 +1058,13 @@ void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)
if (!ieee80211_is_public_action((struct ieee80211_hdr *)buff, size))
goto out_rx_mgmt;
+ /* ieee80211_is_public_action() only validates up to the category
+ * byte, so reject frames too short for the P2P public action header
+ * before dereferencing it or computing size - ie_offset.
+ */
+ if (size < ie_offset)
+ goto out_rx_mgmt;
+
d = (struct wilc_p2p_pub_act_frame *)(&mgmt->u.action);
if (d->oui_subtype != GO_NEG_REQ && d->oui_subtype != GO_NEG_RSP &&
d->oui_subtype != P2P_INV_REQ && d->oui_subtype != P2P_INV_RSP)
@@ -1200,6 +1207,13 @@ static int mgmt_tx(struct wiphy *wiphy,
goto out_set_timeout;
}
+ /* ieee80211_is_public_action() only validates up to the category
+ * byte, so reject frames too short for the P2P public action header
+ * before dereferencing it or computing len - ie_offset.
+ */
+ if (len < ie_offset)
+ goto out_set_timeout;
+
d = (struct wilc_p2p_pub_act_frame *)(&mgmt->u.action);
if (d->oui_type != WLAN_OUI_TYPE_WFA_P2P ||
d->oui_subtype != GO_NEG_CONF) {
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
index 4b116fe6f9ea..55a77a2e3288 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.c
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
@@ -1197,6 +1197,15 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
if (size <= 0)
return;
+ /* A size exceeding the RX buffer is bogus; drop the transfer
+ * instead of overflowing the buffer.
+ */
+ if (size > WILC_RX_BUFF_SIZE) {
+ wilc->hif_func->hif_clear_int_ext(wilc,
+ DATA_INT_CLR | ENABLE_RX_VMM);
+ return;
+ }
+
if (WILC_RX_BUFF_SIZE - offset < size)
offset = 0;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index bb167f03367b..d9dcbb255317 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -852,8 +852,6 @@ int rsi_hal_load_key(struct rsi_common *common,
memcpy(set_key->tx_mic_key, &data[16], 8);
memcpy(set_key->rx_mic_key, &data[24], 8);
}
- } else {
- memset(&set_key[FRAME_DESC_SZ], 0, frame_len - FRAME_DESC_SZ);
}
skb_put(skb, frame_len);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 5595f7a1fc0c..edf6ca23c6c3 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -3724,10 +3724,8 @@ void wlcore_regdomain_config(struct wl1271 *wl)
goto out;
ret = wlcore_cmd_regdomain_config_locked(wl);
- if (ret < 0) {
+ if (ret < 0)
wl12xx_queue_recovery_work(wl);
- goto out;
- }
pm_runtime_put_autosuspend(wl->dev);
out:
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_main.c b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
index 02b6d81cccd1..b9446577ff49 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_main.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
@@ -2327,7 +2327,12 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw, bool suspend)
struct sk_buff *skb;
int i;
- data->started = false;
+ /*
+ * Serialise against wmediumd userspace, so no more frames
+ * can be handed to mac80211 after this returns.
+ */
+ scoped_guard(mutex, &data->mutex)
+ data->started = false;
for (i = 0; i < ARRAY_SIZE(data->link_data); i++)
hrtimer_cancel(&data->link_data[i].beacon_timer);
@@ -6505,12 +6510,12 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
if (frame_data_len < sizeof(struct ieee80211_hdr_3addr) ||
frame_data_len > IEEE80211_MAX_DATA_LEN)
- goto err;
+ goto out;
/* Allocate new skb here */
skb = alloc_skb(frame_data_len, GFP_KERNEL);
if (skb == NULL)
- goto err;
+ goto out;
/* Copy the data */
skb_put_data(skb, frame_data, frame_data_len);
@@ -6535,10 +6540,17 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
goto out;
}
+ /*
+ * Serialise against mac80211_hwsim_stop() - mac80211 doesn't allow
+ * frames reported while the HW is down, hence the ->started check
+ * must be under mutex.
+ */
+ mutex_lock(&data2->mutex);
+
/* check if radio is configured properly */
if ((data2->idle && !data2->tmp_chan) || !data2->started)
- goto out;
+ goto out_unlock;
/* A frame is received from user space */
memset(&rx_status, 0, sizeof(rx_status));
@@ -6557,22 +6569,18 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
iter_data.channel = ieee80211_get_channel(data2->hw->wiphy,
rx_status.freq);
if (!iter_data.channel)
- goto out;
+ goto out_unlock;
rx_status.band = iter_data.channel->band;
- mutex_lock(&data2->mutex);
if (!hwsim_chans_compat(iter_data.channel, channel)) {
ieee80211_iterate_active_interfaces_atomic(
data2->hw, IEEE80211_IFACE_ITER_NORMAL,
mac80211_hwsim_tx_iter, &iter_data);
- if (!iter_data.receive) {
- mutex_unlock(&data2->mutex);
- goto out;
- }
+ if (!iter_data.receive)
+ goto out_unlock;
}
- mutex_unlock(&data2->mutex);
} else if (!channel) {
- goto out;
+ goto out_unlock;
} else {
rx_status.freq = channel->center_freq;
rx_status.band = channel->band;
@@ -6580,7 +6588,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates)
- goto out;
+ goto out_unlock;
rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
hdr = (void *)skb->data;
@@ -6590,10 +6598,11 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
rx_status.boottime_ns = ktime_get_boottime_ns();
mac80211_hwsim_rx(data2, &rx_status, skb);
+ mutex_unlock(&data2->mutex);
return 0;
-err:
- pr_debug("mac80211_hwsim: error occurred in %s\n", __func__);
+out_unlock:
+ mutex_unlock(&data2->mutex);
out:
dev_kfree_skb(skb);
return -EINVAL;
diff --git a/drivers/net/wireless/virtual/virt_wifi.c b/drivers/net/wireless/virtual/virt_wifi.c
index 2335e45db8b8..48afc2432f93 100644
--- a/drivers/net/wireless/virtual/virt_wifi.c
+++ b/drivers/net/wireless/virtual/virt_wifi.c
@@ -434,6 +434,7 @@ static netdev_tx_t virt_wifi_start_xmit(struct sk_buff *skb,
priv->tx_packets++;
if (!priv->is_connected) {
priv->tx_failed++;
+ dev_kfree_skb_any(skb);
return NET_XMIT_DROP;
}
@@ -557,7 +558,6 @@ static int virt_wifi_newlink(struct net_device *dev,
}
eth_hw_addr_inherit(dev, priv->lowerdev);
- netif_stacked_transfer_operstate(priv->lowerdev, dev);
dev->ieee80211_ptr = kzalloc_obj(*dev->ieee80211_ptr);
@@ -583,6 +583,8 @@ static int virt_wifi_newlink(struct net_device *dev,
goto unregister_netdev;
}
+ netif_stacked_transfer_operstate(priv->lowerdev, dev);
+
dev->priv_destructor = virt_wifi_net_device_destructor;
priv->being_deleted = false;
priv->is_connected = false;
diff --git a/drivers/net/wwan/mhi_wwan_mbim.c b/drivers/net/wwan/mhi_wwan_mbim.c
index a94998712597..336f89756f10 100644
--- a/drivers/net/wwan/mhi_wwan_mbim.c
+++ b/drivers/net/wwan/mhi_wwan_mbim.c
@@ -251,6 +251,14 @@ static int mbim_rx_verify_ndp16(struct sk_buff *skb, struct usb_cdc_ncm_ndp16 *n
return ret;
}
+static void mhi_mbim_rx_drop(struct mhi_mbim_link *link, struct sk_buff *skb)
+{
+ dev_kfree_skb_any(skb);
+ u64_stats_update_begin(&link->rx_syncp);
+ u64_stats_inc(&link->rx_errors);
+ u64_stats_update_end(&link->rx_syncp);
+}
+
static void mhi_mbim_rx(struct mhi_mbim_context *mbim, struct sk_buff *skb)
{
int ndpoffset;
@@ -320,7 +328,10 @@ static void mhi_mbim_rx(struct mhi_mbim_context *mbim, struct sk_buff *skb)
continue;
skb_put(skbn, dgram_len);
- skb_copy_bits(skb, dgram_offset, skbn->data, dgram_len);
+ if (skb_copy_bits(skb, dgram_offset, skbn->data, dgram_len)) {
+ mhi_mbim_rx_drop(link, skbn);
+ continue;
+ }
switch (skbn->data[0] & 0xf0) {
case 0x40:
@@ -332,10 +343,7 @@ static void mhi_mbim_rx(struct mhi_mbim_context *mbim, struct sk_buff *skb)
default:
net_err_ratelimited("%s: unknown protocol\n",
link->ndev->name);
- dev_kfree_skb_any(skbn);
- u64_stats_update_begin(&link->rx_syncp);
- u64_stats_inc(&link->rx_errors);
- u64_stats_update_end(&link->rx_syncp);
+ mhi_mbim_rx_drop(link, skbn);
continue;
}
@@ -349,9 +357,13 @@ static void mhi_mbim_rx(struct mhi_mbim_context *mbim, struct sk_buff *skb)
unlock:
rcu_read_unlock();
next_ndp:
- /* Other NDP to process? */
- ndpoffset = (int)le16_to_cpu(ndp16.wNextNdpIndex);
- if (!ndpoffset)
+ /* Other NDP to process? The offsets must advance, or a
+ * self-referencing NDP keeps the loop spinning forever.
+ */
+ n = (int)le16_to_cpu(ndp16.wNextNdpIndex);
+ if (n > ndpoffset)
+ ndpoffset = n;
+ else
break;
}
diff --git a/drivers/net/wwan/t7xx/t7xx_netdev.c b/drivers/net/wwan/t7xx/t7xx_netdev.c
index fc0a7cb181df..8f32c2d26931 100644
--- a/drivers/net/wwan/t7xx/t7xx_netdev.c
+++ b/drivers/net/wwan/t7xx/t7xx_netdev.c
@@ -420,6 +420,10 @@ static void t7xx_ccmni_recv_skb(struct t7xx_ccmni_ctrl *ccmni_ctlb, struct sk_bu
skb_cb = T7XX_SKB_CB(skb);
netif_id = skb_cb->netif_idx;
+ if (netif_id >= NIC_DEV_MAX) {
+ dev_kfree_skb(skb);
+ return;
+ }
ccmni = READ_ONCE(ccmni_ctlb->ccmni_inst[netif_id]);
if (!ccmni) {
dev_kfree_skb(skb);
diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
index 1c5f5820f5b7..226c62704d9b 100644
--- a/drivers/power/sequencing/Kconfig
+++ b/drivers/power/sequencing/Kconfig
@@ -29,7 +29,8 @@ config POWER_SEQUENCING_QCOM_WCN
config POWER_SEQUENCING_TH1520_GPU
tristate "T-HEAD TH1520 GPU power sequencing driver"
- depends on (ARCH_THEAD && AUXILIARY_BUS) || COMPILE_TEST
+ depends on ARCH_THEAD || COMPILE_TEST
+ select AUXILIARY_BUS
help
Say Y here to enable the power sequencing driver for the TH1520 SoC
GPU. This driver handles the complex clock and reset sequence
diff --git a/drivers/power/sequencing/core.c b/drivers/power/sequencing/core.c
index 0cb71efbb268..3076b3879af9 100644
--- a/drivers/power/sequencing/core.c
+++ b/drivers/power/sequencing/core.c
@@ -101,6 +101,7 @@ static struct pwrseq_unit *pwrseq_unit_new(const struct pwrseq_unit_data *data)
}
kref_init(&unit->ref);
+ INIT_LIST_HEAD(&unit->list);
INIT_LIST_HEAD(&unit->deps);
unit->enable = data->enable;
unit->disable = data->disable;
@@ -504,10 +505,6 @@ pwrseq_device_register(const struct pwrseq_config *config)
*/
device_initialize(&pwrseq->dev);
- ret = dev_set_name(&pwrseq->dev, "pwrseq.%d", pwrseq->id);
- if (ret)
- goto err_put_pwrseq;
-
pwrseq->owner = config->owner ?: THIS_MODULE;
pwrseq->match = config->match;
@@ -516,6 +513,10 @@ pwrseq_device_register(const struct pwrseq_config *config)
INIT_LIST_HEAD(&pwrseq->targets);
INIT_LIST_HEAD(&pwrseq->units);
+ ret = dev_set_name(&pwrseq->dev, "pwrseq.%d", pwrseq->id);
+ if (ret)
+ goto err_put_pwrseq;
+
ret = pwrseq_setup_targets(config->targets, pwrseq);
if (ret)
goto err_put_pwrseq;
@@ -912,6 +913,8 @@ int pwrseq_enable(struct pwrseq_desc *desc)
if (!ret)
desc->powered_on = true;
}
+ if (ret)
+ return ret;
if (target->post_enable) {
ret = target->post_enable(pwrseq);