diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-27 13:53:43 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-27 13:53:43 -0700 |
| commit | 1b78070aaef63512688aebfbc82365ef9d6660f1 (patch) | |
| tree | 691c0aeaa3d92278ceeb6ace56bc8cd56a7f2ae8 /drivers | |
| parent | 3ba13f5e7180c034b0a1ef7e052fb780856b134e (diff) | |
| parent | 4a9d62a8774f130a5b8de26ca9f415e6050a9d51 (diff) | |
| download | linux-next-stable.tar.gz linux-next-stable.zip | |
Merge tag 'net-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/netstable
Pull networking fixes from Jakub Kicinski:
"Including fixes from Bluetooth, IPSec and Netfilter.
Current release - fix to a fix:
- netfilter: ipset: remove need to allocate memory on delete operations
Current release - regressions:
- macb: drop CONFIG_OF #if block, fix build
Previous releases - always broken:
- stream of fixes for SCTP continues
- inet: frags: strip GSO state from fragments before reassembly
- virtio-net: ensure that TCP packets don't overflow gso_segs
- tcp-ao: fix use-after-free of current_key on reconnect to another
peer
- page_pool: remove zone/policy GFP flags when allocating XArray
entries
- Bluetooth: L2CAP: reject accept queue add unless BT_LISTEN
- tls: device: fix out-of-bounds write in tls_append_frag()
- eth: bnxt:
- ring the doorbell when SW USO exits early, avoid packets stuck
in Tx
- gate TPH enablement behind BNXT_SUPPORTS_QUEUE_API check, avoid
users of older NICs seeing non-actionable warning messages
- eth: qede: fix NULL pointer dereference in TPA fragment processing"
* tag 'net-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (216 commits)
inet: frags: strip GSO state from fragments before reassembly
net/sched: sch_htb: limit htb_classify inner-class filter hops
selftests/net: packetdrill: add tcp_urg_ptr_retransmit
tcp: fix corruption of urgent data on multi-segment retransmit
usb: atm: usbatm: fix invalid ci_range initialization
net: fec: only stop PTP if it was initialized
slip: remove slip_hangup() to fix use-after-free in slip_receive_buf()
net: bridge: mcast: fix use-after-free of a master VLAN's multicast context
net/sched: bound qdisc_pkt_len to prevent qdisc soft lockup
net: dsa: mxl862xx: enable assisted learning on CPU port
net: stmmac: restore NET_IP_ALIGN in the RX DMA offset
net: stmmac: drop gso_enabled_types and rely on netdev features
net: stmmac: selftests: Don't test flow control for small rx fifos
net: stmmac: selftests: Account for the UC filter list for filtering tests
net: stmmac: dwxgmac: Account for the primary MAC address for UC filtering
net: stmmac: dwmac4: Account for the primary MAC address for UC filtering
net: stmmac: dwmac1000: Account for the primary MAC address for UC filtering
net: stmmac: selftests: Check multiple MMC counters
selftests: net: Fix slow configurations in big_tcp_tunnels.sh
selftests: net: Lower threshold with csum offload off in big_tcp_tunnels.sh
...
Diffstat (limited to 'drivers')
81 files changed, 886 insertions, 504 deletions
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c index 66b346761043..c0ed51567ed4 100644 --- a/drivers/bluetooth/btmtk.c +++ b/drivers/bluetooth/btmtk.c @@ -860,6 +860,7 @@ static u32 btmtk_usb_reset_done(struct hci_dev *hdev) int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id) { + int reset_err = 0; u32 val; int err; @@ -958,8 +959,10 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id) err = readx_poll_timeout(btmtk_usb_reset_done, hdev, val, val & MTK_BT_RST_DONE, 20000, 1000000); - if (err < 0) + if (err < 0) { bt_dev_err(hdev, "Reset timeout"); + reset_err = err; + } if (dev_id == 0x7922) { err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT, 0x000000FF); @@ -968,10 +971,12 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id) } err = btmtk_usb_id_get(hdev, 0x70010200, &val); - if (err || (!val && dev_id != 0x6639)) + if (err || (!val && dev_id != 0x6639)) { bt_dev_err(hdev, "Can't get device id, subsys reset fail."); + return err ? err : -ENODEV; + } - return err; + return reset_err; } EXPORT_SYMBOL_GPL(btmtk_usb_subsys_reset); diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 4e1012e90979..94aa60d9cc20 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -272,12 +272,24 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev, struct sk_buff *skb) { struct mtkbtsdio_hdr *sdio_hdr; + unsigned int len, pad_len; int err; - /* Make sure that there are enough rooms for SDIO header */ - if (unlikely(skb_headroom(skb) < sizeof(*sdio_hdr))) { - err = pskb_expand_head(skb, sizeof(*sdio_hdr), 0, - GFP_ATOMIC); + /* Make sure that the data buffer is not shared with anyone else and + * that there is enough room for the SDIO header + */ + err = skb_cow_head(skb, sizeof(*sdio_hdr)); + if (err < 0) + return err; + + /* The transfer is rounded up to the SDIO block size, so the buffer + * has to provide tailroom for the padding as well + */ + len = skb->len + sizeof(*sdio_hdr); + pad_len = round_up(len, MTK_SDIO_BLOCK_SIZE) - len; + + if (unlikely(skb_tailroom(skb) < pad_len)) { + err = pskb_expand_head(skb, 0, pad_len, GFP_ATOMIC); if (err < 0) return err; } @@ -290,19 +302,22 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev, sdio_hdr->reserved = cpu_to_le16(0); sdio_hdr->bt_type = hci_skb_pkt_type(skb); + /* Zero the padding so that no uninitialised memory is sent out */ + skb_put_zero(skb, pad_len); + clear_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state); - err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data, - round_up(skb->len, MTK_SDIO_BLOCK_SIZE)); + err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data, skb->len); if (err < 0) - goto err_skb_pull; + goto err_skb_restore; - bdev->hdev->stat.byte_tx += skb->len; + bdev->hdev->stat.byte_tx += len; kfree_skb(skb); return 0; -err_skb_pull: +err_skb_restore: + skb_trim(skb, len); skb_pull(skb, sizeof(*sdio_hdr)); return err; diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c index 9afe3f73c22b..25e7b41b349f 100644 --- a/drivers/bluetooth/btnxpuart.c +++ b/drivers/bluetooth/btnxpuart.c @@ -1359,12 +1359,21 @@ static int nxp_process_fw_dump(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_acl_hdr *acl_hdr = (struct hci_acl_hdr *)skb_pull_data(skb, sizeof(*acl_hdr)); - struct nxp_fw_dump_hdr *fw_dump_hdr = (struct nxp_fw_dump_hdr *)skb->data; + struct nxp_fw_dump_hdr *fw_dump_hdr; struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); - __u16 seq_num = __le16_to_cpu(fw_dump_hdr->seq_num); - __u16 buf_len = __le16_to_cpu(fw_dump_hdr->buf_len); + __u16 seq_num; + __u16 buf_len; int err; + fw_dump_hdr = skb_pull_data(skb, sizeof(*fw_dump_hdr)); + if (!fw_dump_hdr) { + bt_dev_warn(hdev, "FW dump: invalid or corrupt fw dump chunk"); + goto free_skb; + } + + seq_num = __le16_to_cpu(fw_dump_hdr->seq_num); + buf_len = __le16_to_cpu(fw_dump_hdr->buf_len); + if (seq_num == 0x0001) { if (test_and_set_bit(BTNXPUART_FW_DUMP_IN_PROGRESS, &nxpdev->tx_state)) { bt_dev_err(hdev, "FW dump already in progress"); @@ -1809,6 +1818,28 @@ static void nxp_coredump_notify(struct hci_dev *hdev, int state) kobject_uevent_env(&serdev->dev.kobj, KOBJ_CHANGE, envp); } +/* + * Check if the remote M.2 connector device linked via OF graph is present + * and available. This is used to determine whether the pwrseq path should + * be taken. When the remote connector node is disabled (e.g., by a DT + * overlay switching from PCIe WiFi to SDIO WiFi), the pwrseq path is + * skipped, allowing the BT driver to use a direct bluetooth child node + * instead. + */ +static bool nxp_m2_connector_is_available(struct device *dev) +{ + struct device_node *ep __free(device_node) = + of_graph_get_next_endpoint(dev_of_node(dev), NULL); + + if (!ep) + return false; + + struct device_node *remote __free(device_node) = + of_graph_get_remote_port_parent(ep); + + return remote && of_device_is_available(remote); +} + static int nxp_serdev_probe(struct serdev_device *serdev) { struct hci_dev *hdev; @@ -1863,7 +1894,7 @@ static int nxp_serdev_probe(struct serdev_device *serdev) return err; } - if (of_graph_is_present(dev_of_node(&serdev->ctrl->dev))) { + if (nxp_m2_connector_is_available(&serdev->ctrl->dev)) { struct pwrseq_desc *pwrseq; pwrseq = pwrseq_get(&serdev->ctrl->dev, "uart"); diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 7f54d2d2d13a..03fa9409e3ee 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -1343,19 +1343,6 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) if (!btrtl_dev->ic_info) return; - switch (btrtl_dev->project_id) { - case CHIP_ID_8761B: - /* RTL8761B/BU reports HCI version 5.1 but does not support - * the LE Extended Scan commands (Opcode 0x2042), causing - * repeated -EBUSY failures when BlueZ attempts extended - * scanning while a connection is active. - */ - hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN); - break; - default: - break; - } - switch (btrtl_dev->ic_info->lmp_subver) { case RTL_ROM_LMP_8703B: /* 8723CS reports two pages for local ext features, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index be82bbbc1b5c..d70a3e7a13f5 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -67,6 +67,7 @@ static struct usb_driver btusb_driver; #define BTUSB_INTEL_NO_WBS_SUPPORT BIT(26) #define BTUSB_ACTIONS_SEMI BIT(27) #define BTUSB_BARROT BIT(28) +#define BTUSB_BROKEN_EXT_SCAN BIT(29) static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -617,6 +618,10 @@ static const struct usb_device_id quirks_table[] = { { USB_DEVICE(0x0489, 0xe130), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + /* Realtek 8761BU Bluetooth devices */ + { USB_DEVICE(0x0bda, 0xa728), .driver_info = BTUSB_REALTEK | + BTUSB_BROKEN_EXT_SCAN }, + /* Realtek Bluetooth devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), .driver_info = BTUSB_REALTEK }, @@ -4401,6 +4406,9 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_INVALID_LE_STATES) hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES); + if (id->driver_info & BTUSB_BROKEN_EXT_SCAN) + hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN); + if (id->driver_info & BTUSB_DIGIANSWER) { data->cmdreq_type = USB_TYPE_VENDOR; hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 01da3fecb536..9a103db7e355 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -547,6 +547,7 @@ static int bcm_close(struct hci_uart *hu) if (IS_ENABLED(CONFIG_PM) && bdev->irq_acquired) { devm_free_irq(bdev->dev, bdev->irq, bdev); device_init_wakeup(bdev->dev, false); + pm_runtime_dont_use_autosuspend(bdev->dev); pm_runtime_disable(bdev->dev); } diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c index 925d0a635945..66d49b471544 100644 --- a/drivers/bluetooth/hci_bcm4377.c +++ b/drivers/bluetooth/hci_bcm4377.c @@ -2490,6 +2490,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = { .has_bar0_core2_window2 = true, .broken_mws_transport_config = true, .broken_le_coded = true, + .broken_le_ext_adv_report_phy = true, .send_calibration = bcm4378_send_calibration, .send_ptb = bcm4378_send_ptb, }, diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index 60b90f1e11fc..b1999e14aade 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -1023,8 +1023,10 @@ static void h5_btrtl_open(struct h5 *h5) static void h5_btrtl_close(struct h5 *h5) { - if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags)) + if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags)) { + pm_runtime_dont_use_autosuspend(&h5->hu->serdev->dev); pm_runtime_disable(&h5->hu->serdev->dev); + } gpiod_set_value_cansleep(h5->device_wake_gpio, 0); gpiod_set_value_cansleep(h5->enable_gpio, 0); diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index ecf597f3e201..d10ce7a0ba3e 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -345,6 +345,7 @@ static int intel_set_power(struct hci_uart *hu, bool powered) devm_free_irq(&idev->pdev->dev, idev->irq, idev); device_wakeup_disable(&idev->pdev->dev); + pm_runtime_dont_use_autosuspend(&idev->pdev->dev); pm_runtime_disable(&idev->pdev->dev); } } diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 58f5504a336e..697e32122cc8 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -457,7 +457,7 @@ static int hci_uart_setup(struct hci_dev *hdev) if (IS_ERR(skb)) { BT_ERR("%s: Reading local version information failed (%ld)", hdev->name, PTR_ERR(skb)); - return 0; + return PTR_ERR(skb); } if (skb->len != sizeof(*ver)) { diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 593d9cefbbf9..d2eaf2f12aa2 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -221,7 +221,7 @@ static int hci_uart_setup(struct hci_dev *hdev) if (IS_ERR(skb)) { bt_dev_err(hdev, "Reading local version info failed (%ld)", PTR_ERR(skb)); - return 0; + return PTR_ERR(skb); } if (skb->len != sizeof(*ver)) diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index a7bcc33587cc..373ee1f42d4a 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -1630,14 +1630,15 @@ static int mlx5_ib_query_port_speed_from_vport(struct mlx5_core_dev *mdev, u32 port_num) { u32 max_tx_speed; + u8 vport_state; int err; err = mlx5_query_vport_max_tx_speed(mdev, op_mod, vport, other_vport, - &max_tx_speed); + &max_tx_speed, &vport_state); if (err) return err; - if (max_tx_speed == 0) + if (vport_state == VPORT_STATE_DOWN || max_tx_speed == 0) /* Value 0 indicates field not supported, fallback */ return mlx5_ib_query_port_speed_from_port(dev, port_num, speed); diff --git a/drivers/net/dsa/mxl862xx/mxl862xx.c b/drivers/net/dsa/mxl862xx/mxl862xx.c index 45d237b3a40f..cfa7e3e269a2 100644 --- a/drivers/net/dsa/mxl862xx/mxl862xx.c +++ b/drivers/net/dsa/mxl862xx/mxl862xx.c @@ -2111,6 +2111,7 @@ static int mxl862xx_probe(struct mdio_device *mdiodev) ds->ops = &mxl862xx_switch_ops; ds->phylink_mac_ops = &mxl862xx_phylink_mac_ops; ds->num_ports = MXL862XX_MAX_PORTS; + ds->assisted_learning_on_cpu_port = true; ds->fdb_isolation = true; ds->max_num_bridges = MXL862XX_MAX_BRIDGES; diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c index de75376db194..5bb4817a898d 100644 --- a/drivers/net/ethernet/airoha/airoha_npu.c +++ b/drivers/net/ethernet/airoha/airoha_npu.c @@ -768,7 +768,7 @@ static int airoha_npu_probe(struct platform_device *pdev) npu->irqs[i] = irq; } - err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (err) return err; diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 42174249ef61..942454e29488 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -996,9 +996,9 @@ static int emac_probe(struct platform_device *pdev) /* fill in parameters for net-dev structure */ ndev->base_addr = (unsigned long)db->membase; ndev->irq = irq_of_parse_and_map(np, 0); - if (ndev->irq == -ENXIO) { + if (!ndev->irq) { netdev_err(ndev, "No irq resource\n"); - ret = ndev->irq; + ret = -ENXIO; goto out_iounmap; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 208a894d6190..39eb6ab5f805 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -13473,10 +13473,13 @@ static int bnx2x_init_firmware(struct bnx2x *bp) iro_alloc_err: kfree(bp->init_ops_offsets); + bp->init_ops_offsets = NULL; init_offsets_alloc_err: kfree(bp->init_ops); + bp->init_ops = NULL; init_ops_alloc_err: kfree(bp->init_data); + bp->init_data = NULL; request_firmware_exit: release_firmware(bp->firmware); bp->firmware = NULL; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 9377bf675981..d59bcca73a2b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -485,6 +485,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) struct bnxt_sw_tx_bd *tx_buf; __le32 lflags = 0; skb_frag_t *frag; + netdev_tx_t ret; i = skb_get_queue_mapping(skb); if (unlikely(i >= bp->tx_nr_rings)) { @@ -501,17 +502,19 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) if (skb_shinfo(skb)->nr_frags > TX_MAX_FRAGS) { netdev_warn_once(dev, "SKB has too many (%d) fragments, max supported is %d. SKB will be linearized.\n", skb_shinfo(skb)->nr_frags, TX_MAX_FRAGS); - if (skb_linearize(skb)) { - dev_kfree_skb_any(skb); - dev_core_stats_tx_dropped_inc(dev); - return NETDEV_TX_OK; - } + if (skb_linearize(skb)) + goto tx_free; } #endif if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) && - !(bp->flags & BNXT_FLAG_UDP_GSO_CAP)) - return bnxt_sw_udp_gso_xmit(bp, txr, txq, skb); + !(bp->flags & BNXT_FLAG_UDP_GSO_CAP)) { + ret = bnxt_sw_udp_gso_xmit(bp, txr, txq, skb); + if (txr->kick_pending) + bnxt_txr_db_kick(bp, txr, txr->tx_prod); + + return ret; + } free_size = bnxt_tx_avail(bp, txr); if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) { @@ -11946,9 +11949,11 @@ static int bnxt_request_irq(struct bnxt *bp) #endif /* Enable TPH support as part of IRQ request */ - rc = pcie_enable_tph(bp->pdev, PCI_TPH_ST_IV_MODE); - if (!rc) - bp->tph_mode = PCI_TPH_ST_IV_MODE; + if (BNXT_SUPPORTS_QUEUE_API(bp)) { + rc = pcie_enable_tph(bp->pdev, PCI_TPH_ST_IV_MODE); + if (!rc) + bp->tph_mode = PCI_TPH_ST_IV_MODE; + } for (i = 0, j = 0; i < bp->cp_nr_rings; i++) { struct cpumask *cpu_mask = bp->ring_cpu_mask[i]; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c index f317f60414e8..f7e18bea0fb8 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c @@ -223,9 +223,7 @@ netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp, netdev_tx_sent_queue(txq, skb->len); WRITE_ONCE(txr->tx_prod, prod); - /* Sync BDs before doorbell */ - wmb(); - bnxt_db_write(bp, &txr->tx_db, prod); + txr->kick_pending = 1; if (unlikely(bnxt_tx_avail(bp, txr) <= bp->tx_wake_thresh)) netif_txq_try_stop(txq, bnxt_tx_avail(bp, txr), diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c index de3427c6c6aa..faed0cf726e1 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwmon.c @@ -40,7 +40,7 @@ void bnxt_hwmon_notify_event(struct bnxt *bp) return; } - hwmon_notify_event(&bp->pdev->dev, hwmon_temp, attr, 0); + hwmon_notify_event(bp->hwmon_dev, hwmon_temp, attr, 0); } static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 1476bce77f34..76ee4f506033 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -4926,7 +4926,6 @@ static const struct macb_usrio_config at91_default_usrio = { .clken = MACB_BIT(CLKEN), }; -#if defined(CONFIG_OF) /* 1518 rounded up */ #define AT91ETHER_MAX_RBUFF_SZ 0x600 /* max number of receive buffers */ @@ -5754,7 +5753,6 @@ static const struct of_device_id macb_dt_ids[] = { { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, macb_dt_ids); -#endif /* CONFIG_OF */ static const struct macb_config default_gem_config = { .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | @@ -6267,7 +6265,7 @@ static struct platform_driver macb_driver = { .remove = macb_remove, .driver = { .name = "macb", - .of_match_table = of_match_ptr(macb_dt_ids), + .of_match_table = macb_dt_ids, .pm = &macb_pm_ops, }, .shutdown = macb_shutdown, diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 8e3f345dd9aa..80f0082f6c63 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -81,6 +81,33 @@ void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter) } EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter); +void enetc_set_congestion_mode(struct enetc_ndev_priv *priv, bool enable) +{ + struct enetc_si *si = priv->si; + struct enetc_hw *hw = &si->hw; + + spin_lock(&si->gen_lock); + + if (enable) + set_bit(ENETC_RXBDR_CM, &priv->flags); + else + clear_bit(ENETC_RXBDR_CM, &priv->flags); + + for (int i = 0; i < priv->num_rx_rings; i++) { + u32 old_rbmr = enetc_rxbdr_rd(hw, i, ENETC_RBMR); + u32 rbmr; + + rbmr = u32_replace_bits(old_rbmr, enable, ENETC_RBMR_CM); + if (rbmr == old_rbmr) + continue; + + enetc_rxbdr_wr(hw, i, ENETC_RBMR, rbmr); + } + + spin_unlock(&si->gen_lock); +} +EXPORT_SYMBOL_GPL(enetc_set_congestion_mode); + static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv) { int num_tx_rings = priv->num_tx_rings; @@ -2632,7 +2659,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring, bool extended) { int idx = rx_ring->index; - u32 rbmr = 0; enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0, lower_32_bits(rx_ring->bd_dma_base)); @@ -2660,12 +2686,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring, enetc_rxbdr_wr(hw, idx, ENETC_RBICR0, ENETC_RBICR0_ICEN | 0x1); rx_ring->ext_en = extended; - if (rx_ring->ext_en) - rbmr |= ENETC_RBMR_BDS; - - if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX) - rbmr |= ENETC_RBMR_VTE; - rx_ring->rcir = hw->reg + ENETC_BDR(RX, idx, ENETC_RBCIR); rx_ring->idr = hw->reg + ENETC_SIRXIDR; @@ -2676,8 +2696,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring, enetc_lock_mdio(); enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring)); enetc_unlock_mdio(); - - enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr); } static void enetc_setup_bdrs(struct enetc_ndev_priv *priv, bool extended) @@ -2704,21 +2722,34 @@ static void enetc_enable_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) static void enetc_enable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring) { + struct enetc_ndev_priv *priv = netdev_priv(rx_ring->ndev); int idx = rx_ring->index; - u32 rbmr; + u32 rbmr = ENETC_RBMR_EN; + + if (rx_ring->ext_en) + rbmr |= ENETC_RBMR_BDS; + + if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX) + rbmr |= ENETC_RBMR_VTE; + + if (test_bit(ENETC_RXBDR_CM, &priv->flags)) + rbmr |= ENETC_RBMR_CM; - rbmr = enetc_rxbdr_rd(hw, idx, ENETC_RBMR); - rbmr |= ENETC_RBMR_EN; enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr); } static void enetc_enable_rx_bdrs(struct enetc_ndev_priv *priv) { - struct enetc_hw *hw = &priv->si->hw; + struct enetc_si *si = priv->si; + struct enetc_hw *hw = &si->hw; int i; + spin_lock(&si->gen_lock); + for (i = 0; i < priv->num_rx_rings; i++) enetc_enable_rxbdr(hw, priv->rx_ring[i]); + + spin_unlock(&si->gen_lock); } static void enetc_enable_tx_bdrs(struct enetc_ndev_priv *priv) @@ -2748,11 +2779,16 @@ static void enetc_disable_txbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring) static void enetc_disable_rx_bdrs(struct enetc_ndev_priv *priv) { - struct enetc_hw *hw = &priv->si->hw; + struct enetc_si *si = priv->si; + struct enetc_hw *hw = &si->hw; int i; + spin_lock(&si->gen_lock); + for (i = 0; i < priv->num_rx_rings; i++) enetc_disable_rxbdr(hw, priv->rx_ring[i]); + + spin_unlock(&si->gen_lock); } static void enetc_disable_tx_bdrs(struct enetc_ndev_priv *priv) @@ -3344,11 +3380,16 @@ EXPORT_SYMBOL_GPL(enetc_get_stats); static void enetc_enable_rxvlan(struct net_device *ndev, bool en) { struct enetc_ndev_priv *priv = netdev_priv(ndev); - struct enetc_hw *hw = &priv->si->hw; + struct enetc_si *si = priv->si; + struct enetc_hw *hw = &si->hw; int i; + spin_lock(&si->gen_lock); + for (i = 0; i < priv->num_rx_rings; i++) enetc_bdr_enable_rxvlan(hw, i, en); + + spin_unlock(&si->gen_lock); } static void enetc_enable_txvlan(struct net_device *ndev, bool en) @@ -3679,6 +3720,7 @@ int enetc_pci_probe(struct pci_dev *pdev, const char *name, int sizeof_priv) si = PTR_ALIGN(p, ENETC_SI_ALIGN); si->pad = (char *)si - (char *)p; + spin_lock_init(&si->gen_lock); pci_set_drvdata(pdev, si); si->pdev = pdev; diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h index 8839cfb49bcf..d1e9d9130057 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.h +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -309,6 +309,13 @@ struct enetc_si { struct net_device *ndev; /* back ref. */ + /* General-purpose lock serializing updates that must not race, + * e.g. read-modify-write of shared hardware registers and of + * selected priv->flags bits between the phylink link callbacks + * and the ring (re)configuration path. + */ + spinlock_t gen_lock; + union { struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */ struct ntmp_user ntmp_user; /* ENETC 4.1 and later */ @@ -417,6 +424,7 @@ enum enetc_active_offloads { enum enetc_flags_bit { ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS = 0, ENETC_TX_DOWN, + ENETC_RXBDR_CM, }; /* interrupt coalescing modes */ @@ -505,6 +513,7 @@ int enetc_get_driver_data(struct enetc_si *si); void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter, const unsigned char *addr); void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter); +void enetc_set_congestion_mode(struct enetc_ndev_priv *priv, bool enable); int enetc_open(struct net_device *ndev); int enetc_close(struct net_device *ndev); diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c index fcfbabb29d22..9bb1004548ab 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c @@ -718,22 +718,14 @@ static void enetc4_set_rx_pause(struct enetc_pf *pf, bool rx_pause) enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val); } -static void enetc4_set_tx_pause(struct enetc_pf *pf, int num_rxbdr, bool tx_pause) +static void enetc4_set_tx_pause(struct enetc_pf *pf, bool tx_pause) { + struct enetc_ndev_priv *priv = netdev_priv(pf->si->ndev); u32 pause_off_thresh = 0, pause_on_thresh = 0; u32 init_quanta = 0, refresh_quanta = 0; struct enetc_hw *hw = &pf->si->hw; - u32 rbmr, old_rbmr; - int i; - for (i = 0; i < num_rxbdr; i++) { - old_rbmr = enetc_rxbdr_rd(hw, i, ENETC_RBMR); - rbmr = u32_replace_bits(old_rbmr, tx_pause ? 1 : 0, ENETC_RBMR_CM); - if (rbmr == old_rbmr) - continue; - - enetc_rxbdr_wr(hw, i, ENETC_RBMR, rbmr); - } + enetc_set_congestion_mode(priv, tx_pause); if (tx_pause) { /* When the port first enters congestion, send a PAUSE request @@ -898,7 +890,7 @@ static void enetc4_pl_mac_link_up(struct phylink_config *config, tx_pause = false; } - enetc4_set_tx_pause(pf, priv->num_rx_rings, tx_pause); + enetc4_set_tx_pause(pf, tx_pause); enetc4_set_rx_pause(pf, rx_pause); enetc4_mac_tx_enable(pf); enetc4_mac_rx_enable(pf); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index a509929f89f2..55c07c528f22 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -556,8 +556,7 @@ static void enetc_pl_mac_link_up(struct phylink_config *config, struct enetc_hw *hw = &pf->si->hw; struct enetc_si *si = pf->si; struct enetc_ndev_priv *priv; - u32 rbmr, cmd_cfg; - int idx; + u32 cmd_cfg; priv = netdev_priv(pf->si->ndev); @@ -569,16 +568,7 @@ static void enetc_pl_mac_link_up(struct phylink_config *config, enetc_force_rgmii_mac(si, speed, duplex); /* Flow control */ - for (idx = 0; idx < priv->num_rx_rings; idx++) { - rbmr = enetc_rxbdr_rd(hw, idx, ENETC_RBMR); - - if (tx_pause) - rbmr |= ENETC_RBMR_CM; - else - rbmr &= ~ENETC_RBMR_CM; - - enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr); - } + enetc_set_congestion_mode(priv, tx_pause); if (tx_pause) { /* When the port first enters congestion, send a PAUSE request diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index ced4dbf8cd90..794ec427b0ee 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -5457,7 +5457,8 @@ failed_mii_init: failed_irq: fec_enet_deinit(ndev); failed_init: - fec_ptp_stop(pdev); + if (fep->bufdesc_ex) + fec_ptp_stop(pdev); failed_reset: pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -5499,7 +5500,8 @@ fec_drv_remove(struct platform_device *pdev) ERR_PTR(ret)); cancel_work_sync(&fep->tx_timeout_work); - fec_ptp_stop(pdev); + if (fep->bufdesc_ex) + fec_ptp_stop(pdev); unregister_netdev(ndev); fec_enet_mii_remove(fep); if (fep->reg_phy) diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c index 4382af937e2e..207ada721dd9 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c @@ -554,7 +554,7 @@ static int hbg_ring_page_pool_init(struct hbg_priv *priv, struct hbg_ring *ring) .nid = dev_to_node(&priv->pdev->dev), .dev = &priv->pdev->dev, .napi = &ring->napi, - .dma_dir = DMA_FROM_DEVICE, + .dma_dir = DMA_BIDIRECTIONAL, .offset = 0, .max_len = hbg_get_page_size(ring), }; diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 8b9ce7cbfff9..1fb5f3cbe93c 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -3071,7 +3071,8 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) olinfo_status = xdp_desc.len << IGC_ADVTXD_PAYLEN_SHIFT; dma = xsk_buff_raw_get_dma(pool, xdp_desc.addr); - meta = xsk_buff_get_metadata(pool, xdp_desc.addr); + meta = xsk_buff_get_metadata(pool, xdp_desc.addr, + xdp_desc.options); xsk_buff_raw_dma_sync_for_device(pool, dma, xdp_desc.len); bi = &ring->tx_buffer_info[ntu]; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/api.h b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/api.h index 4285b5d6a6a2..f36a1d5f236f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/api.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/api.h @@ -21,6 +21,7 @@ int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int num); int cn20k_rvu_get_mbox_regions(struct rvu *rvu, void **mbox_addr, int num, int type, unsigned long *pf_bmap); void cn20k_free_mbox_memory(struct rvu *rvu); +void cn20k_free_mbox_memory_type(struct rvu *rvu, int type); int cn20k_register_afpf_mbox_intr(struct rvu *rvu); int cn20k_register_afvf_mbox_intr(struct rvu *rvu, int pf_vec_start); void cn20k_rvu_enable_mbox_intr(struct rvu *rvu); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/mbox_init.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/mbox_init.c index 71401dec0d77..01f32adac599 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/mbox_init.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/mbox_init.c @@ -335,13 +335,30 @@ int cn20k_rvu_mbox_init(struct rvu *rvu, int type, int ndevs) return rvu_alloc_mbox_memory(rvu, type, ndevs, MBOX_SIZE); } +void cn20k_free_mbox_memory_type(struct rvu *rvu, int type) +{ + if (!is_cn20k(rvu->pdev) || !rvu->ng_rvu) + return; + + switch (type) { + case TYPE_AFPF: + qmem_free(rvu->dev, rvu->ng_rvu->pf_mbox_addr); + rvu->ng_rvu->pf_mbox_addr = NULL; + break; + case TYPE_AFVF: + qmem_free(rvu->dev, rvu->ng_rvu->vf_mbox_addr); + rvu->ng_rvu->vf_mbox_addr = NULL; + break; + } +} + void cn20k_free_mbox_memory(struct rvu *rvu) { if (!is_cn20k(rvu->pdev)) return; - qmem_free(rvu->dev, rvu->ng_rvu->pf_mbox_addr); - qmem_free(rvu->dev, rvu->ng_rvu->vf_mbox_addr); + cn20k_free_mbox_memory_type(rvu, TYPE_AFPF); + cn20k_free_mbox_memory_type(rvu, TYPE_AFVF); } void cn20k_rvu_disable_afvf_intr(struct rvu *rvu, int vfs) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index ffba56ee8a60..74c041ab5280 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -2585,12 +2585,6 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw, if (!pf_bmap) return -ENOMEM; - ng_rvu_mbox = kzalloc_obj(*ng_rvu_mbox); - if (!ng_rvu_mbox) { - err = -ENOMEM; - goto free_bitmap; - } - /* RVU VFs */ if (type == TYPE_AFVF) bitmap_set(pf_bmap, 0, num); @@ -2604,15 +2598,22 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw, } } - rvu->ng_rvu = ng_rvu_mbox; + if (!rvu->ng_rvu) { + ng_rvu_mbox = devm_kzalloc(rvu->dev, sizeof(*ng_rvu_mbox), GFP_KERNEL); + if (!ng_rvu_mbox) { + err = -ENOMEM; + goto free_bitmap; + } + + rvu->ng_rvu = ng_rvu_mbox; - rvu->ng_rvu->rvu_mbox_ops = &rvu_mbox_ops; + rvu->ng_rvu->rvu_mbox_ops = &rvu_mbox_ops; + mutex_init(&rvu->mbox_lock); + } err = cn20k_rvu_mbox_init(rvu, type, num); if (err) - goto free_mem; - - mutex_init(&rvu->mbox_lock); + goto free_bitmap; mbox_regions = kcalloc(num, sizeof(void __iomem *), GFP_KERNEL); if (!mbox_regions) { @@ -2702,14 +2703,18 @@ unmap_regions: free_regions: kfree(mbox_regions); free_qmem: - cn20k_free_mbox_memory(rvu); -free_mem: - kfree(rvu->ng_rvu); + cn20k_free_mbox_memory_type(rvu, type); free_bitmap: bitmap_free(pf_bmap); return err; } +static void rvu_free_cn20k_mbox_memory(struct rvu *rvu) +{ + if (is_cn20k(rvu->pdev)) + cn20k_free_mbox_memory(rvu); +} + static void rvu_mbox_destroy(struct mbox_wq_info *mw) { struct otx2_mbox *mbox = &mw->mbox; @@ -3331,8 +3336,8 @@ static int rvu_register_interrupts(struct rvu *rvu) goto fail; for (i = 0; i < rvu->num_vec; i++) { - if (strstr(&rvu->irq_name[i * NAME_SIZE], "Mbox") || - strstr(&rvu->irq_name[i * NAME_SIZE], "FLR")) + if (strnstr(&rvu->irq_name[i * NAME_SIZE], "Mbox", NAME_SIZE) || + strnstr(&rvu->irq_name[i * NAME_SIZE], "FLR", NAME_SIZE)) irq_set_affinity(pci_irq_vector(rvu->pdev, i), cpumask_of(0)); } @@ -3519,6 +3524,7 @@ static int rvu_enable_sriov(struct rvu *rvu) if (err) { rvu_disable_afvf_intr(rvu); rvu_mbox_destroy(&rvu->afvf_wq_info); + cn20k_free_mbox_memory_type(rvu, TYPE_AFVF); return err; } @@ -3681,6 +3687,7 @@ err_flr: err_mbox: rvu_mbox_destroy(&rvu->afpf_wq_info); err_hwsetup: + rvu_free_cn20k_mbox_memory(rvu); rvu_cgx_exit(rvu); rvu_fwdata_exit(rvu); rvu_mcs_exit(rvu); @@ -3723,9 +3730,7 @@ static void rvu_remove(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); devm_kfree(&pdev->dev, rvu->hw); - if (is_cn20k(rvu->pdev)) - cn20k_free_mbox_memory(rvu); - kfree(rvu->ng_rvu); + rvu_free_cn20k_mbox_memory(rvu); devm_kfree(&pdev->dev, rvu); atomic_set(&device_bound, 0); } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index 3456313d3b3c..22ee99676879 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -1697,6 +1697,12 @@ static int rvu_dbg_nix_tm_tree_display(struct seq_file *m, void *unused) return -EINVAL; pfvf = rvu_get_pfvf(rvu, pcifunc); + + if (!pfvf->sq_ctx) { + seq_printf(m, "SQ context is not initialized for pcifunc 0x%x\n", pcifunc); + return -EINVAL; + } + max_id = pfvf->sq_ctx->qsize; memset(&aq_req, 0, sizeof(struct nix_aq_enq_req)); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index b81c47ea023b..153eb57bad06 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -2491,8 +2491,8 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, int pf = rvu_get_pf(rvu->pdev, pcifunc); u8 cgx_id = 0, lmac_id = 0; u16 tl2_tl3_link_schq; - u8 link, link_level; u64 cfg, bmap = 0; + u8 link_level; if (!is_rvu_otx2(rvu)) { /* Skip SMQ flush if pkt count is zero */ @@ -2524,7 +2524,6 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, link_level = rvu_read64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL) & 0x01 ? NIX_TXSCH_LVL_TL3 : NIX_TXSCH_LVL_TL2; tl2_tl3_link_schq = smq_flush_ctx->smq_tree_ctx[link_level].schq; - link = smq_flush_ctx->smq_tree_ctx[NIX_TXSCH_LVL_TL1].schq; /* SMQ set enqueue xoff */ cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq)); @@ -2534,13 +2533,13 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, /* Clear all NIX_AF_TL3_TL2_LINK_CFG[ENA] for the TL3/TL2 queue */ for (i = 0; i < (rvu->hw->cgx_links + rvu->hw->lbk_links); i++) { cfg = rvu_read64(rvu, blkaddr, - NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link)); + NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, i)); if (!(cfg & BIT_ULL(12))) continue; bmap |= BIT_ULL(i); cfg &= ~BIT_ULL(12); rvu_write64(rvu, blkaddr, - NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link), cfg); + NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, i), cfg); } /* Do SMQ flush and set enqueue xoff */ @@ -2561,10 +2560,10 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, if (!(bmap & BIT_ULL(i))) continue; cfg = rvu_read64(rvu, blkaddr, - NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link)); + NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, i)); cfg |= BIT_ULL(12); rvu_write64(rvu, blkaddr, - NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, link), cfg); + NIX_AF_TL3_TL2X_LINKX_CFG(tl2_tl3_link_schq, i), cfg); } /* clear XOFF on TL2s */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index ca73a94db794..175992188c18 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -333,7 +333,8 @@ int otx2_set_rss_table(struct otx2_nic *pfvf, int ctx_id, const u32 *ind_tbl) /* Get memory to put this msg */ for (idx = 0; idx < rss->rss_size; idx++) { /* Ignore the queue if AF_XDP zero copy is enabled */ - if (test_bit(ind_tbl[idx], pfvf->af_xdp_zc_qidx)) + if (pfvf->af_xdp_zc_qidx && + test_bit(ind_tbl[idx], pfvf->af_xdp_zc_qidx)) continue; aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox); @@ -1509,7 +1510,8 @@ int otx2_pool_aq_init(struct otx2_nic *pfvf, u16 pool_id, if (type != AURA_NIX_RQ) return 0; - if (!test_bit(pool_id, pfvf->af_xdp_zc_qidx)) { + if (!pfvf->af_xdp_zc_qidx || + !test_bit(pool_id, pfvf->af_xdp_zc_qidx)) { pp_params.order = get_order(buf_size); pp_params.flags = PP_FLAG_DMA_MAP; pp_params.pool_size = min(OTX2_PAGE_POOL_SZ, numptrs); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c index a0340f3422bf..9bee1b91eeaa 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c @@ -939,7 +939,8 @@ static int otx2_get_rxfh(struct net_device *dev, for (idx = 0; idx < rss->rss_size; idx++) { /* Ignore if the rx queue is AF_XDP zero copy enabled */ - if (test_bit(rss->ind_tbl[idx], pfvf->af_xdp_zc_qidx)) + if (pfvf->af_xdp_zc_qidx && + test_bit(rss->ind_tbl[idx], pfvf->af_xdp_zc_qidx)) continue; indir[idx] = rss->ind_tbl[idx]; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c index b022f52c6845..fcdf891f90b5 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c @@ -737,16 +737,16 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (err) goto err_ptp_destroy; + err = otx2_vf_wq_init(vf); + if (err) + goto err_ipsec_clean; + err = register_netdev(netdev); if (err) { dev_err(dev, "Failed to register netdevice\n"); - goto err_ipsec_clean; + goto err_wq_destroy; } - err = otx2_vf_wq_init(vf); - if (err) - goto err_unreg_netdev; - otx2vf_set_ethtool_ops(netdev); err = otx2vf_mcam_flow_init(vf); @@ -789,6 +789,10 @@ err_shutdown_tc: otx2_shutdown_tc(vf); err_unreg_netdev: unregister_netdev(netdev); +err_wq_destroy: + cancel_work_sync(&vf->reset_task); + cancel_work_sync(&vf->rx_mode_work); + destroy_workqueue(vf->otx2_wq); err_ipsec_clean: cn10k_ipsec_clean(vf); err_ptp_destroy: @@ -836,11 +840,13 @@ static void otx2vf_remove(struct pci_dev *pdev) } #endif - cancel_work_sync(&vf->reset_task); otx2_unregister_dl(vf); unregister_netdev(netdev); - if (vf->otx2_wq) + if (vf->otx2_wq) { + cancel_work_sync(&vf->reset_task); + cancel_work_sync(&vf->rx_mode_work); destroy_workqueue(vf->otx2_wq); + } cn10k_ipsec_clean(vf); otx2_ptp_destroy(vf); otx2_mcam_flow_del(vf); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_xsk.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_xsk.c index 7d67b4cbaf71..0e8a6a6486c4 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_xsk.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_xsk.c @@ -193,7 +193,8 @@ int otx2_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags) void otx2_attach_xsk_buff(struct otx2_nic *pfvf, struct otx2_snd_queue *sq, int qidx) { - if (test_bit(qidx, pfvf->af_xdp_zc_qidx)) + if (pfvf->af_xdp_zc_qidx && + test_bit(qidx, pfvf->af_xdp_zc_qidx)) sq->xsk_pool = xsk_get_pool_from_qid(pfvf->netdev, qidx); } diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c index 10d9beaae372..53d3b7e00e1c 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c @@ -2071,6 +2071,11 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev) wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); } + if (mtk_wed_is_v2(dev->hw)) + wdma_m32(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RESV_BUFF, + FIELD_PREP(MTK_WDMA_GLO_CFG_RESV_BUFF, 0x80)); + wed_set(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_TX_DMA_EN | MTK_WED_GLO_CFG_RX_DMA_EN); diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h index c71190924816..e5f83100ded5 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h +++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h @@ -433,6 +433,7 @@ struct mtk_wdma_desc { #define MTK_WDMA_GLO_CFG_TX_DMA_BUSY BIT(1) #define MTK_WDMA_GLO_CFG_RX_DMA_EN BIT(2) #define MTK_WDMA_GLO_CFG_RX_DMA_BUSY BIT(3) +#define MTK_WDMA_GLO_CFG_RESV_BUFF GENMASK(23, 16) #define MTK_WDMA_GLO_CFG_RX_INFO3_PRERES BIT(26) #define MTK_WDMA_GLO_CFG_RX_INFO2_PRERES BIT(27) #define MTK_WDMA_GLO_CFG_RX_INFO1_PRERES BIT(28) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c index 3d19dad8f868..d194eeddd7b5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c @@ -99,7 +99,7 @@ bool mlx5e_xsk_tx(struct mlx5e_xdpsq *sq, unsigned int budget) xdptxd.dma_addr = xsk_buff_raw_get_dma(pool, desc.addr); xdptxd.data = xsk_buff_raw_get_data(pool, desc.addr); xdptxd.len = desc.len; - meta = xsk_buff_get_metadata(pool, desc.addr); + meta = xsk_buff_get_metadata(pool, desc.addr, desc.options); xsk_buff_raw_dma_sync_for_device(pool, xdptxd.dma_addr, xdptxd.len); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 603051ab1eaa..ce765692fd19 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -689,11 +689,13 @@ static int mlx5e_rep_open(struct net_device *dev) if (err) goto unlock; + mutex_lock(&rep->esw->state_lock); if (!mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, rep->vport, 1, MLX5_VPORT_ADMIN_STATE_UP)) netif_carrier_on(dev); + mutex_unlock(&rep->esw->state_lock); unlock: mutex_unlock(&priv->state_lock); @@ -708,10 +710,12 @@ static int mlx5e_rep_close(struct net_device *dev) int ret; mutex_lock(&priv->state_lock); + mutex_lock(&rep->esw->state_lock); mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, rep->vport, 1, MLX5_VPORT_ADMIN_STATE_DOWN); + mutex_unlock(&rep->esw->state_lock); ret = mlx5e_close_locked(dev); mutex_unlock(&priv->state_lock); return ret; @@ -783,22 +787,25 @@ static int mlx5e_rep_change_carrier(struct net_device *dev, bool new_carrier) struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5_eswitch_rep *rep = rpriv->rep; - int err; + int err = 0; + mutex_lock(&rep->esw->state_lock); if (new_carrier) { err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, rep->vport, 1, MLX5_VPORT_ADMIN_STATE_UP); if (err) - return err; + goto unlock; netif_carrier_on(dev); } else { err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, rep->vport, 1, MLX5_VPORT_ADMIN_STATE_DOWN); if (err) - return err; + goto unlock; netif_carrier_off(dev); } - return 0; +unlock: + mutex_unlock(&rep->esw->state_lock); + return err; } static const struct net_device_ops mlx5e_netdev_ops_rep = { @@ -1339,9 +1346,12 @@ static int mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) mlx5e_rep_tc_enable(priv); - if (MLX5_CAP_GEN(mdev, uplink_follow)) + if (MLX5_CAP_GEN(mdev, uplink_follow)) { + mutex_lock(&mdev->priv.eswitch->state_lock); mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK, 0, 0, MLX5_VPORT_ADMIN_STATE_AUTO); + mutex_unlock(&mdev->priv.eswitch->state_lock); + } mlx5_lag_add_netdev(mdev, netdev); priv->events_nb.notifier_call = uplink_rep_async_event; mlx5_notifier_register(mdev, &priv->events_nb); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c index ca249b50f830..7950b82d8b8a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c @@ -9,6 +9,28 @@ int mlx5_esw_adj_vport_modify(struct mlx5_core_dev *dev, u16 vport, { u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {}; + lockdep_assert_held(&dev->priv.eswitch->state_lock); + + if (MLX5_CAP_ESW(dev, esw_vport_state_max_tx_speed)) { + u8 op_mod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT; + struct mlx5_vport *esw_vport; + u32 speed = 0; + int err; + + err = mlx5_query_vport_max_tx_speed(dev, op_mod, vport, + true, &speed, NULL); + if (err) { + esw_vport = mlx5_eswitch_get_vport(dev->priv.eswitch, + vport); + speed = IS_ERR(esw_vport) ? 0 : + esw_vport->agg_max_tx_speed; + mlx5_core_dbg(dev, + "Failed to query vport %d max tx speed, err=%d, using cached %u\n", + vport, err, speed); + } + MLX5_SET(modify_vport_state_in, in, max_tx_speed, speed); + } + MLX5_SET(modify_vport_state_in, in, opcode, MLX5_CMD_OP_MODIFY_VPORT_STATE); MLX5_SET(modify_vport_state_in, in, op_mod, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 247e5d85ec36..d603e294ee0e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2567,6 +2567,7 @@ static void mlx5_esw_fdb_active(struct mlx5_eswitch *esw) mlx5_esw_fdb_drop_destroy(esw); mlx5_mpfs_enable(esw->dev); + mutex_lock(&esw->state_lock); mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) { if (!vport->adjacent) continue; @@ -2574,6 +2575,7 @@ static void mlx5_esw_fdb_active(struct mlx5_eswitch *esw) vport->vport); mlx5_esw_adj_vport_modify(esw->dev, vport->vport, true); } + mutex_unlock(&esw->state_lock); esw->offloads_inactive = false; esw_warn(esw->dev, "MPFS/FDB active\n"); @@ -2587,6 +2589,7 @@ static void mlx5_esw_fdb_inactive(struct mlx5_eswitch *esw) mlx5_mpfs_disable(esw->dev); mlx5_esw_fdb_drop_create(esw); + mutex_lock(&esw->state_lock); mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) { if (!vport->adjacent) continue; @@ -2595,6 +2598,7 @@ static void mlx5_esw_fdb_inactive(struct mlx5_eswitch *esw) mlx5_esw_adj_vport_modify(esw->dev, vport->vport, false); } + mutex_unlock(&esw->state_lock); esw->offloads_inactive = true; esw_warn(esw->dev, "MPFS/FDB inactive\n"); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index 28d16fdc3f06..2285c889c215 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -1471,6 +1471,7 @@ static void mlx5_lag_modify_device_vports_speed(struct mlx5_core_dev *mdev, if (!MLX5_CAP_ESW(mdev, esw_vport_state_max_tx_speed)) return; + mutex_lock(&esw->state_lock); mlx5_esw_for_each_vport(esw, i, vport) { if (!vport) continue; @@ -1490,6 +1491,7 @@ static void mlx5_lag_modify_device_vports_speed(struct mlx5_core_dev *mdev, "Failed to set vport %d speed %d, err=%d\n", vport->vport, speed, ret); } + mutex_unlock(&esw->state_lock); } void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index 3d86510af615..5774ec117428 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -89,6 +89,34 @@ int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, { u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {}; +#ifdef CONFIG_MLX5_ESWITCH + lockdep_assert_held(&mdev->priv.eswitch->state_lock); +#endif + + if (MLX5_CAP_ESW(mdev, esw_vport_state_max_tx_speed) && + opmod == MLX5_VPORT_STATE_OP_MOD_ESW_VPORT && + vport != MLX5_VPORT_UPLINK) { + u32 speed = 0; + int err; + + err = mlx5_query_vport_max_tx_speed(mdev, opmod, vport, + other_vport, &speed, NULL); + if (err) { +#ifdef CONFIG_MLX5_ESWITCH + struct mlx5_vport *esw_vport; + + esw_vport = mlx5_eswitch_get_vport(mdev->priv.eswitch, + vport); + speed = IS_ERR(esw_vport) ? 0 : + esw_vport->agg_max_tx_speed; +#endif + mlx5_core_dbg(mdev, + "Failed to query vport %d max tx speed, err=%d, using cached %u\n", + vport, err, speed); + } + MLX5_SET(modify_vport_state_in, in, max_tx_speed, speed); + } + MLX5_SET(modify_vport_state_in, in, opcode, MLX5_CMD_OP_MODIFY_VPORT_STATE); MLX5_SET(modify_vport_state_in, in, op_mod, opmod); @@ -106,6 +134,10 @@ int mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 opmod, u8 admin_state; int err; +#ifdef CONFIG_MLX5_ESWITCH + lockdep_assert_held(&mdev->priv.eswitch->state_lock); +#endif + err = mlx5_query_vport_admin_state(mdev, opmod, vport, other_vport, &admin_state); if (err) @@ -123,11 +155,11 @@ int mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 opmod, } int mlx5_query_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 op_mod, - u16 vport, u8 other_vport, u32 *max_tx_speed) + u16 vport, u8 other_vport, + u32 *max_tx_speed, u8 *state) { u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] = {}; u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] = {}; - u32 state; int err; MLX5_SET(query_vport_state_in, in, opcode, @@ -140,13 +172,9 @@ int mlx5_query_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 op_mod, if (err) return err; - state = MLX5_GET(query_vport_state_out, out, state); - if (state == VPORT_STATE_DOWN) { - *max_tx_speed = 0; - return 0; - } - *max_tx_speed = MLX5_GET(query_vport_state_out, out, max_tx_speed); + if (state) + *state = MLX5_GET(query_vport_state_out, out, state); return 0; } EXPORT_SYMBOL_GPL(mlx5_query_vport_max_tx_speed); diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c index 1d34af78166a..4dedf5d92641 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c @@ -162,13 +162,18 @@ static int sparx5_port_stop(struct net_device *ndev) return 0; } -static void sparx5_set_rx_mode(struct net_device *dev) +static int sparx5_set_rx_mode(struct net_device *dev, + struct netdev_hw_addr_list *uc, + struct netdev_hw_addr_list *mc) { struct sparx5_port *port = netdev_priv(dev); struct sparx5 *sparx5 = port->sparx5; if (!test_bit(port->portno, sparx5->bridge_mask)) - __dev_mc_sync(dev, sparx5_mc_sync, sparx5_mc_unsync); + return __hw_addr_sync_dev(mc, dev, sparx5_mc_sync, + sparx5_mc_unsync); + + return 0; } static int sparx5_port_get_phys_port_name(struct net_device *dev, @@ -249,7 +254,7 @@ static const struct net_device_ops sparx5_port_netdev_ops = { .ndo_open = sparx5_port_open, .ndo_stop = sparx5_port_stop, .ndo_start_xmit = sparx5_port_xmit_impl, - .ndo_set_rx_mode = sparx5_set_rx_mode, + .ndo_set_rx_mode_async = sparx5_set_rx_mode, .ndo_get_phys_port_name = sparx5_port_get_phys_port_name, .ndo_set_mac_address = sparx5_set_mac_address, .ndo_validate_addr = eth_validate_addr, diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c index cf332de6bf73..2dee2ce19fce 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c @@ -2077,8 +2077,9 @@ int sparx5_vcap_init(struct sparx5 *sparx5) dir = vcap_debugfs(sparx5->dev, sparx5->debugfs_root, ctrl); for (idx = 0; idx < consts->n_ports; ++idx) if (sparx5->ports[idx]) - vcap_port_debugfs(sparx5->dev, dir, ctrl, - sparx5->ports[idx]->ndev); + vcap_port_debugfs_portno(sparx5->dev, dir, ctrl, + sparx5->ports[idx]->ndev, + sparx5->ports[idx]->portno); return err; } diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c index e0c65c7ab23e..476f7496a9d4 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c @@ -400,6 +400,27 @@ void vcap_port_debugfs(struct device *dev, struct dentry *parent, } EXPORT_SYMBOL_GPL(vcap_port_debugfs); +void vcap_port_debugfs_portno(struct device *dev, + struct dentry *parent, + struct vcap_control *vctrl, + struct net_device *ndev, + unsigned int portno) +{ + struct vcap_port_debugfs_info *info; + char name[16]; + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return; + + info->vctrl = vctrl; + info->ndev = ndev; + + snprintf(name, sizeof(name), "p%u", portno); + debugfs_create_file(name, 0444, parent, info, &vcap_port_debugfs_fops); +} +EXPORT_SYMBOL_GPL(vcap_port_debugfs_portno); + /* Show the full VCAP instance data (rules with all fields) */ static int vcap_debugfs_show(struct seq_file *m, void *unused) { diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.h b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.h index 9f2c59b5f6f5..7dc6e3411a4d 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.h +++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.h @@ -18,6 +18,12 @@ void vcap_port_debugfs(struct device *dev, struct dentry *parent, struct vcap_control *vctrl, struct net_device *ndev); +void vcap_port_debugfs_portno(struct device *dev, + struct dentry *parent, + struct vcap_control *vctrl, + struct net_device *ndev, + unsigned int portno); + /* Create a debugFS entry for a vcap instance */ struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent, struct vcap_control *vctrl); @@ -30,6 +36,14 @@ static inline void vcap_port_debugfs(struct device *dev, struct dentry *parent, { } +static inline void vcap_port_debugfs_portno(struct device *dev, + struct dentry *parent, + struct vcap_control *vctrl, + struct net_device *ndev, + unsigned int portno) +{ +} + static inline struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent, struct vcap_control *vctrl) diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c index ed9af314e4ed..f92b2d0bf926 100644 --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c @@ -182,6 +182,7 @@ static int mana_gd_query_max_resources(struct pci_dev *pdev) struct gdma_query_max_resources_resp resp = {}; struct gdma_general_req req = {}; unsigned int max_num_queues; + unsigned int msix_vec_count; u8 bm_hostmode; u16 num_ports; int err; @@ -218,6 +219,24 @@ static int mana_gd_query_max_resources(struct pci_dev *pdev) gc->num_msix_usable = min(resp.max_msix, num_online_cpus() + 1); } + /* MSI-X vectors are allocated by index into the device MSI-X table, so + * never ask for more than the table holds. It can be smaller than both + * resp.max_msix and the CPU count. + */ + err = pci_msix_vec_count(pdev); + if (err <= 0) { + dev_err(gc->dev, "Failed to query MSI-X table size: %d\n", err); + return err < 0 ? err : -ENOSPC; + } + msix_vec_count = err; + + if (gc->num_msix_usable > msix_vec_count) { + dev_info(gc->dev, + "Limiting MSI-X vectors from %u to table size %u\n", + gc->num_msix_usable, msix_vec_count); + gc->num_msix_usable = msix_vec_count; + } + if (gc->num_msix_usable <= 1) return -ENOSPC; diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 58d3e55def48..f0218a0eab5c 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -2740,7 +2740,7 @@ static void nv_tx_timeout(struct net_device *dev, unsigned int txqueue) netdev_info(dev, "Ring at %lx\n", (unsigned long)np->ring_addr); netdev_info(dev, "Dumping tx registers\n"); - for (i = 0; i <= np->register_size; i += 32) { + for (i = 0; i + 32 <= np->register_size; i += 32) { netdev_info(dev, "%3x: %08x %08x %08x %08x " "%08x %08x %08x %08x\n", @@ -6221,7 +6221,7 @@ static int nv_suspend(struct device *device) netif_device_detach(dev); /* save non-pci configuration space */ - for (i = 0; i <= np->register_size/sizeof(u32); i++) + for (i = 0; i < np->register_size/sizeof(u32); i++) np->saved_config_space[i] = readl(base + i*sizeof(u32)); return 0; @@ -6236,7 +6236,7 @@ static int nv_resume(struct device *device) int i, rc = 0; /* restore non-pci configuration space */ - for (i = 0; i <= np->register_size/sizeof(u32); i++) + for (i = 0; i < np->register_size/sizeof(u32); i++) writel(np->saved_config_space[i], base+i*sizeof(u32)); if (np->driver_data & DEV_NEED_MSI_FIX) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_if.h b/drivers/net/ethernet/pensando/ionic/ionic_if.h index 6afc1fc3c7ed..15f2bc3f4043 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_if.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_if.h @@ -555,6 +555,8 @@ enum ionic_lif_rdma_cap_stats { * @rdma.eq_qtype: RDMA Event Qtype * @rdma.stats_type: Supported statistics type * (enum ionic_lif_rdma_cap_stats) + * @rdma.rsvd: Reserved byte + * @rdma.rcq_sign_bit: RCQ sign bit * @rdma.rsvd1: Reserved byte(s) * @words: word access to struct contents */ @@ -600,7 +602,9 @@ union ionic_lif_identity { struct ionic_lif_logical_qtype cq_qtype; struct ionic_lif_logical_qtype eq_qtype; __le16 stats_type; - u8 rsvd1[162]; + u8 rsvd; + u8 rcq_sign_bit; + u8 rsvd1[160]; } __packed rdma; } __packed; __le32 words[478]; diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 042a75f34060..0e7a0c2c1765 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -303,10 +303,10 @@ enum qede_agg_state { }; struct qede_agg_info { - /* rx_buf is a data buffer that can be placed / consumed from rx bd - * chain. It has two purposes: We will preallocate the data buffer - * for each aggregation when we open the interface and will place this - * buffer on the rx-bd-ring when we receive TPA_START. We don't want + /* buffer is used to retain the Rx consumer descriptor when a TPA + * session starts. If the SKB allocation fails during TPA_START, + * we use this saved buffer to safely recycle the physical page + * back into the rx-bd-ring via qede_reuse_page(). We don't want * to be in a state where allocation fails, as we can't reuse the * consumer buffer in the rx-chain since FW may still be writing to it * (since header needs to be modified for TPA). diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c index c11e0d8f98aa..a02624f6d6d5 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_fp.c +++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c @@ -850,6 +850,7 @@ static void qede_tpa_start(struct qede_dev *edev, pad, false); tpa_info->buffer.page_offset = sw_rx_data_cons->page_offset; tpa_info->buffer.mapping = sw_rx_data_cons->mapping; + tpa_info->buffer.data = sw_rx_data_cons->data; if (unlikely(!tpa_info->skb)) { DP_NOTICE(edev, "Failed to allocate SKB for gro\n"); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index 9192c5ad5a16..c6bdf1b6ac9d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c @@ -6,6 +6,7 @@ #include "qlcnic.h" #include "qlcnic_hw.h" +#include <linux/unaligned.h> struct crb_addr_pair { u32 addr; @@ -740,159 +741,212 @@ qlcnic_has_mn(struct qlcnic_adapter *adapter) return 0; } -static -struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section) -{ - u32 i, entries; - struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; - entries = le32_to_cpu(directory->num_entries); - - for (i = 0; i < entries; i++) { +#define FILEHEADER_SIZE (14 * 4) +#define QLCNIC_UNI_DIR_TYPE_OFF (8 * sizeof(__le32)) +#define QLCNIC_UNI_DIR_ENTRY_MIN_SIZE (9 * sizeof(__le32)) +#define QLCNIC_UNI_PRODUCT_ENTRY_MIN_SIZE \ + ((QLCNIC_UNI_FIRMWARE_IDX_OFF + 1) * sizeof(__le32)) +#define QLCNIC_UNI_VERSION_TAIL_SIZE 17 +#define QLCNIC_UNI_BOOTLD_SIZE \ + (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) + +struct qlcnic_uni_data { + u32 offset; + u32 size; +}; - u32 offs = le32_to_cpu(directory->findex) + - i * le32_to_cpu(directory->entry_size); - u32 tab_type = le32_to_cpu(*((__le32 *)&unirom[offs] + 8)); +static bool qlcnic_rom_range_valid(size_t size, size_t offset, size_t len) +{ + return offset <= size && len <= size - offset; +} - if (tab_type == section) - return (struct uni_table_desc *) &unirom[offs]; - } +static bool qlcnic_rom_table_valid(size_t size, u32 offset, u32 entries, + u32 entry_size, u32 min_entry_size) +{ + if (entry_size < min_entry_size || offset > size) + return false; - return NULL; + return entries <= (size - offset) / entry_size; } -#define FILEHEADER_SIZE (14 * 4) - -static int -qlcnic_validate_header(struct qlcnic_adapter *adapter) +static int qlcnic_get_directory(struct qlcnic_adapter *adapter, + size_t *offset, u32 *entries, u32 *entry_size) { - const u8 *unirom = adapter->fw->data; - struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; - u32 entries, entry_size, tab_size, fw_file_size; - - fw_file_size = adapter->fw->size; + const struct firmware *fw = adapter->fw; + const u8 *directory = fw->data; - if (fw_file_size < FILEHEADER_SIZE) + if (fw->size < FILEHEADER_SIZE) return -EINVAL; - entries = le32_to_cpu(directory->num_entries); - entry_size = le32_to_cpu(directory->entry_size); - tab_size = le32_to_cpu(directory->findex) + (entries * entry_size); + *offset = get_unaligned_le32(directory + + offsetof(struct uni_table_desc, findex)); + *entries = get_unaligned_le32(directory + + offsetof(struct uni_table_desc, num_entries)); + *entry_size = get_unaligned_le32(directory + + offsetof(struct uni_table_desc, entry_size)); - if (fw_file_size < tab_size) + if (!qlcnic_rom_table_valid(fw->size, *offset, *entries, *entry_size, + QLCNIC_UNI_DIR_ENTRY_MIN_SIZE)) return -EINVAL; return 0; } -static int -qlcnic_validate_bootld(struct qlcnic_adapter *adapter) +static int qlcnic_get_table_desc(struct qlcnic_adapter *adapter, int section, + size_t *desc_offset) { - struct uni_table_desc *tab_desc; - struct uni_data_desc *descr; - u32 offs, tab_size, data_size, idx; const u8 *unirom = adapter->fw->data; - __le32 temp; - - temp = *((__le32 *)&unirom[adapter->file_prd_off] + - QLCNIC_UNI_BOOTLD_IDX_OFF); - idx = le32_to_cpu(temp); - tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD); - - if (!tab_desc) - return -EINVAL; - - tab_size = le32_to_cpu(tab_desc->findex) + - le32_to_cpu(tab_desc->entry_size) * (idx + 1); - - if (adapter->fw->size < tab_size) - return -EINVAL; + size_t directory_offset; + u32 entries, entry_size; + size_t i; + int ret; - offs = le32_to_cpu(tab_desc->findex) + - le32_to_cpu(tab_desc->entry_size) * idx; - descr = (struct uni_data_desc *)&unirom[offs]; + ret = qlcnic_get_directory(adapter, &directory_offset, &entries, + &entry_size); + if (ret) + return ret; - data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size); + for (i = 0; i < entries; i++) { + size_t offset = directory_offset + i * entry_size; + u32 table_type; - if (adapter->fw->size < data_size) - return -EINVAL; + table_type = get_unaligned_le32(unirom + offset + + QLCNIC_UNI_DIR_TYPE_OFF); + if (table_type == section) { + *desc_offset = offset; + return 0; + } + } - return 0; + return -ENOENT; } static int -qlcnic_validate_fw(struct qlcnic_adapter *adapter) +qlcnic_validate_header(struct qlcnic_adapter *adapter) { - struct uni_table_desc *tab_desc; - struct uni_data_desc *descr; - const u8 *unirom = adapter->fw->data; - u32 offs, tab_size, data_size, idx; - __le32 temp; + u32 entries, entry_size; + size_t offset; + + return qlcnic_get_directory(adapter, &offset, &entries, &entry_size); +} - temp = *((__le32 *)&unirom[adapter->file_prd_off] + - QLCNIC_UNI_FIRMWARE_IDX_OFF); - idx = le32_to_cpu(temp); - tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW); +static int qlcnic_get_data_desc(struct qlcnic_adapter *adapter, u32 section, + u32 index_offset, struct qlcnic_uni_data *data) +{ + size_t table_desc_offset, table_offset, desc_offset; + const struct firmware *fw = adapter->fw; + const u8 *unirom = fw->data; + size_t product_index_offset; + u32 entries, entry_size, idx; + int ret; - if (!tab_desc) + product_index_offset = adapter->file_prd_off + + (size_t)index_offset * sizeof(__le32); + if (!qlcnic_rom_range_valid(fw->size, product_index_offset, + sizeof(__le32))) return -EINVAL; - tab_size = le32_to_cpu(tab_desc->findex) + - le32_to_cpu(tab_desc->entry_size) * (idx + 1); + idx = get_unaligned_le32(unirom + product_index_offset); + ret = qlcnic_get_table_desc(adapter, section, &table_desc_offset); + if (ret) + return ret; - if (adapter->fw->size < tab_size) + table_offset = get_unaligned_le32(unirom + table_desc_offset + + offsetof(struct uni_table_desc, findex)); + entries = get_unaligned_le32(unirom + table_desc_offset + + offsetof(struct uni_table_desc, num_entries)); + entry_size = get_unaligned_le32(unirom + table_desc_offset + + offsetof(struct uni_table_desc, entry_size)); + if (!qlcnic_rom_table_valid(fw->size, table_offset, entries, + entry_size, sizeof(struct uni_data_desc)) || + idx >= entries) return -EINVAL; - offs = le32_to_cpu(tab_desc->findex) + - le32_to_cpu(tab_desc->entry_size) * idx; - descr = (struct uni_data_desc *)&unirom[offs]; - data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size); + desc_offset = table_offset + (size_t)idx * entry_size; + data->offset = get_unaligned_le32(unirom + desc_offset + + offsetof(struct uni_data_desc, findex)); + data->size = get_unaligned_le32(unirom + desc_offset + + offsetof(struct uni_data_desc, size)); - if (adapter->fw->size < data_size) + if (!qlcnic_rom_range_valid(fw->size, data->offset, data->size)) return -EINVAL; return 0; } +static int qlcnic_validate_bootld(struct qlcnic_adapter *adapter) +{ + struct qlcnic_uni_data data; + int ret; + + ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD, + QLCNIC_UNI_BOOTLD_IDX_OFF, &data); + if (ret) + return ret; + + return data.size < QLCNIC_UNI_BOOTLD_SIZE ? -EINVAL : 0; +} + +static int qlcnic_validate_fw(struct qlcnic_adapter *adapter) +{ + struct qlcnic_uni_data data; + int ret; + + ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, + QLCNIC_UNI_FIRMWARE_IDX_OFF, &data); + if (ret) + return ret; + + return data.size < QLCNIC_UNI_VERSION_TAIL_SIZE ? -EINVAL : 0; +} + static int qlcnic_validate_product_offs(struct qlcnic_adapter *adapter) { - struct uni_table_desc *ptab_descr; + size_t table_desc_offset, table_offset; const u8 *unirom = adapter->fw->data; int mn_present = qlcnic_has_mn(adapter); - u32 entries, entry_size, tab_size, i; - __le32 temp; - - ptab_descr = qlcnic_get_table_desc(unirom, - QLCNIC_UNI_DIR_SECT_PRODUCT_TBL); - if (!ptab_descr) - return -EINVAL; + u32 entries, entry_size; + size_t i; + int ret; - entries = le32_to_cpu(ptab_descr->num_entries); - entry_size = le32_to_cpu(ptab_descr->entry_size); - tab_size = le32_to_cpu(ptab_descr->findex) + (entries * entry_size); + ret = qlcnic_get_table_desc(adapter, QLCNIC_UNI_DIR_SECT_PRODUCT_TBL, + &table_desc_offset); + if (ret) + return ret; - if (adapter->fw->size < tab_size) + table_offset = get_unaligned_le32(unirom + table_desc_offset + + offsetof(struct uni_table_desc, findex)); + entries = get_unaligned_le32(unirom + table_desc_offset + + offsetof(struct uni_table_desc, num_entries)); + entry_size = get_unaligned_le32(unirom + table_desc_offset + + offsetof(struct uni_table_desc, entry_size)); + if (!qlcnic_rom_table_valid(adapter->fw->size, table_offset, entries, + entry_size, + QLCNIC_UNI_PRODUCT_ENTRY_MIN_SIZE)) return -EINVAL; nomn: for (i = 0; i < entries; i++) { - - u32 flags, file_chiprev, offs; + size_t offset = table_offset + i * entry_size; u8 chiprev = adapter->ahw->revision_id; + u32 flags, file_chiprev; u32 flagbit; - offs = le32_to_cpu(ptab_descr->findex) + - i * le32_to_cpu(ptab_descr->entry_size); - temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_FLAGS_OFF); - flags = le32_to_cpu(temp); - temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_CHIP_REV_OFF); - file_chiprev = le32_to_cpu(temp); + flags = get_unaligned_le32(unirom + offset + + QLCNIC_UNI_FLAGS_OFF * sizeof(__le32)); + file_chiprev = get_unaligned_le32(unirom + offset + + QLCNIC_UNI_CHIP_REV_OFF * + sizeof(__le32)); flagbit = mn_present ? 1 : 2; if ((chiprev == file_chiprev) && ((1ULL << flagbit) & flags)) { - adapter->file_prd_off = offs; + if (offset > U32_MAX) + return -EINVAL; + + adapter->file_prd_off = offset; return 0; } } @@ -933,93 +987,81 @@ qlcnic_validate_unified_romimage(struct qlcnic_adapter *adapter) return 0; } -static -struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter, - u32 section, u32 idx_offset) -{ - const u8 *unirom = adapter->fw->data; - struct uni_table_desc *tab_desc; - u32 offs, idx; - __le32 temp; - - temp = *((__le32 *)&unirom[adapter->file_prd_off] + idx_offset); - idx = le32_to_cpu(temp); - - tab_desc = qlcnic_get_table_desc(unirom, section); - - if (tab_desc == NULL) - return NULL; - - offs = le32_to_cpu(tab_desc->findex) + - le32_to_cpu(tab_desc->entry_size) * idx; - - return (struct uni_data_desc *)&unirom[offs]; -} - -static u8 * -qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter) +static int qlcnic_get_bootld_data(struct qlcnic_adapter *adapter, + const u8 **bootld) { u32 offs = QLCNIC_BOOTLD_START; - struct uni_data_desc *data_desc; - - data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD, - QLCNIC_UNI_BOOTLD_IDX_OFF); + struct qlcnic_uni_data data; + int ret; - if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) - offs = le32_to_cpu(data_desc->findex); + if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) { + ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD, + QLCNIC_UNI_BOOTLD_IDX_OFF, &data); + if (ret || data.size < QLCNIC_UNI_BOOTLD_SIZE) + return -EINVAL; + offs = data.offset; + } else if (!qlcnic_rom_range_valid(adapter->fw->size, offs, + QLCNIC_UNI_BOOTLD_SIZE)) { + return -EINVAL; + } - return (u8 *)&adapter->fw->data[offs]; + *bootld = adapter->fw->data + offs; + return 0; } -static u8 * -qlcnic_get_fw_offs(struct qlcnic_adapter *adapter) +static int qlcnic_get_fw_data(struct qlcnic_adapter *adapter, + const u8 **image, u32 *image_size) { u32 offs = QLCNIC_IMAGE_START; - struct uni_data_desc *data_desc; - - data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, - QLCNIC_UNI_FIRMWARE_IDX_OFF); - if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) - offs = le32_to_cpu(data_desc->findex); - - return (u8 *)&adapter->fw->data[offs]; -} + struct qlcnic_uni_data data; + int ret; -static u32 qlcnic_get_fw_size(struct qlcnic_adapter *adapter) -{ - struct uni_data_desc *data_desc; - const u8 *unirom = adapter->fw->data; + if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) { + ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, + QLCNIC_UNI_FIRMWARE_IDX_OFF, &data); + if (ret) + return ret; + offs = data.offset; + *image_size = data.size; + } else { + if (!qlcnic_rom_range_valid(adapter->fw->size, + QLCNIC_FW_SIZE_OFFSET, + sizeof(__le32))) + return -EINVAL; + *image_size = get_unaligned_le32(adapter->fw->data + + QLCNIC_FW_SIZE_OFFSET); + } - data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, - QLCNIC_UNI_FIRMWARE_IDX_OFF); + if (!qlcnic_rom_range_valid(adapter->fw->size, offs, *image_size)) + return -EINVAL; - if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) - return le32_to_cpu(data_desc->size); - else - return le32_to_cpu(*(__le32 *)&unirom[QLCNIC_FW_SIZE_OFFSET]); + *image = adapter->fw->data + offs; + return 0; } static u32 qlcnic_get_fw_version(struct qlcnic_adapter *adapter) { - struct uni_data_desc *fw_data_desc; + char ver_str[QLCNIC_UNI_VERSION_TAIL_SIZE + 1]; const struct firmware *fw = adapter->fw; + struct qlcnic_uni_data data; u32 major, minor, sub; - __le32 version_offset; - const u8 *ver_str; int i, ret; - if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) { - version_offset = *(__le32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]; - return le32_to_cpu(version_offset); - } + if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) + return get_unaligned_le32(fw->data + QLCNIC_FW_VERSION_OFFSET); + + ret = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, + QLCNIC_UNI_FIRMWARE_IDX_OFF, &data); + if (ret || data.size < QLCNIC_UNI_VERSION_TAIL_SIZE) + return 0; - fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, - QLCNIC_UNI_FIRMWARE_IDX_OFF); - ver_str = fw->data + le32_to_cpu(fw_data_desc->findex) + - le32_to_cpu(fw_data_desc->size) - 17; + memcpy(ver_str, fw->data + data.offset + data.size - + QLCNIC_UNI_VERSION_TAIL_SIZE, + QLCNIC_UNI_VERSION_TAIL_SIZE); + ver_str[QLCNIC_UNI_VERSION_TAIL_SIZE] = '\0'; for (i = 0; i < 12; i++) { - if (!strncmp(&ver_str[i], "REV=", 4)) { + if (!strncmp(ver_str + i, "REV=", 4)) { ret = sscanf(&ver_str[i+4], "%u.%u.%u ", &major, &minor, &sub); if (ret != 3) @@ -1034,18 +1076,15 @@ static u32 qlcnic_get_fw_version(struct qlcnic_adapter *adapter) static u32 qlcnic_get_bios_version(struct qlcnic_adapter *adapter) { - const struct firmware *fw = adapter->fw; u32 bios_ver, prd_off = adapter->file_prd_off; - u8 *version_offset; - __le32 temp; + const struct firmware *fw = adapter->fw; - if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) { - version_offset = (u8 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]; - return le32_to_cpu(*(__le32 *)version_offset); - } + if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) + return get_unaligned_le32(fw->data + QLCNIC_BIOS_VERSION_OFFSET); - temp = *((__le32 *)(&fw->data[prd_off]) + QLCNIC_UNI_BIOS_VERSION_OFF); - bios_ver = le32_to_cpu(temp); + bios_ver = get_unaligned_le32(fw->data + prd_off + + QLCNIC_UNI_BIOS_VERSION_OFF * + sizeof(__le32)); return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); } @@ -1106,24 +1145,26 @@ static const char *fw_name[] = { int qlcnic_load_firmware(struct qlcnic_adapter *adapter) { - __le64 *ptr64; - u32 i, flashaddr, size; const struct firmware *fw = adapter->fw; struct pci_dev *pdev = adapter->pdev; + const u8 *bootld, *image; + u32 i, flashaddr, image_size; + int ret; dev_info(&pdev->dev, "loading firmware from %s\n", fw_name[adapter->ahw->fw_type]); if (fw) { + u32 words, remainder; u64 data; - size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8; - - ptr64 = (__le64 *)qlcnic_get_bootld_offs(adapter); + ret = qlcnic_get_bootld_data(adapter, &bootld); + if (ret) + return ret; flashaddr = QLCNIC_BOOTLD_START; - for (i = 0; i < size; i++) { - data = le64_to_cpu(ptr64[i]); + for (i = 0; i < QLCNIC_UNI_BOOTLD_SIZE / sizeof(u64); i++) { + data = get_unaligned_le64(bootld + i * sizeof(u64)); if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data)) return -EIO; @@ -1131,13 +1172,15 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter) flashaddr += 8; } - size = qlcnic_get_fw_size(adapter) / 8; - - ptr64 = (__le64 *)qlcnic_get_fw_offs(adapter); + ret = qlcnic_get_fw_data(adapter, &image, &image_size); + if (ret) + return ret; + words = image_size / sizeof(u64); + remainder = image_size % sizeof(u64); flashaddr = QLCNIC_IMAGE_START; - for (i = 0; i < size; i++) { - data = le64_to_cpu(ptr64[i]); + for (i = 0; i < words; i++) { + data = get_unaligned_le64(image + i * sizeof(u64)); if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data)) @@ -1146,9 +1189,11 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter) flashaddr += 8; } - size = qlcnic_get_fw_size(adapter) % 8; - if (size) { - data = le64_to_cpu(ptr64[i]); + if (remainder) { + __le64 tail = 0; + + memcpy(&tail, image + words * sizeof(u64), remainder); + data = le64_to_cpu(tail); if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data)) @@ -1156,10 +1201,9 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter) } } else { - u64 data; - u32 hi, lo; - int ret; struct qlcnic_flt_entry bootld_entry; + u32 hi, lo, size; + u64 data; ret = qlcnic_get_flt_entry(adapter, QLCNIC_BOOTLD_REGION, &bootld_entry); @@ -1200,26 +1244,33 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter) static int qlcnic_validate_firmware(struct qlcnic_adapter *adapter) { - u32 val; - u32 ver, bios, min_size; - struct pci_dev *pdev = adapter->pdev; const struct firmware *fw = adapter->fw; + struct pci_dev *pdev = adapter->pdev; u8 fw_type = adapter->ahw->fw_type; + u32 ver, bios, min_size; + const u8 *data; + u32 data_size; + u32 val; + + if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) + min_size = QLCNIC_UNI_FW_MIN_SIZE; + else + min_size = QLCNIC_FW_MIN_SIZE; + + if (fw->size < min_size) + return -EINVAL; if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) { if (qlcnic_validate_unified_romimage(adapter)) return -EINVAL; - - min_size = QLCNIC_UNI_FW_MIN_SIZE; } else { - val = le32_to_cpu(*(__le32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]); + val = get_unaligned_le32(fw->data + QLCNIC_FW_MAGIC_OFFSET); if (val != QLCNIC_BDINFO_MAGIC) return -EINVAL; - - min_size = QLCNIC_FW_MIN_SIZE; } - if (fw->size < min_size) + if (qlcnic_get_bootld_data(adapter, &data) || + qlcnic_get_fw_data(adapter, &data, &data_size)) return -EINVAL; val = qlcnic_get_fw_version(adapter); diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c index 305ae15ae8f3..e6f48dc9fe64 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c @@ -394,6 +394,7 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb, if (!skbn) return NULL; + skbn->dev = skb->dev; skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM); skb_put(skbn, packet_len); memcpy(skbn->data, skb->data, packet_len); diff --git a/drivers/net/ethernet/renesas/rswitch_main.c b/drivers/net/ethernet/renesas/rswitch_main.c index 6fe964816322..755232994fcc 100644 --- a/drivers/net/ethernet/renesas/rswitch_main.c +++ b/drivers/net/ethernet/renesas/rswitch_main.c @@ -1303,7 +1303,8 @@ static int rswitch_etha_mii_write_c22(struct mii_bus *bus, int phyad, /* Call of_node_put(port) after done */ static struct device_node *rswitch_get_port_node(struct rswitch_device *rdev) { - struct device_node *ports, *port; + struct device_node *port = NULL; + struct device_node *ports; int err = 0; u32 index; @@ -1312,17 +1313,16 @@ static struct device_node *rswitch_get_port_node(struct rswitch_device *rdev) if (!ports) return NULL; - for_each_available_child_of_node(ports, port) { - err = of_property_read_u32(port, "reg", &index); - if (err < 0) { - port = NULL; - goto out; - } - if (index == rdev->etha->index) + for_each_available_child_of_node_scoped(ports, child) { + err = of_property_read_u32(child, "reg", &index); + if (err < 0) break; + if (index == rdev->etha->index) { + port = of_node_get(child); + break; + } } -out: of_node_put(ports); return port; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index caac85fc08f1..d4ace3924891 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -194,7 +194,7 @@ static void dwmac1000_set_filter(struct mac_device_info *hw, dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2); /* Handle multiple unicast addresses (perfect filtering) */ - if (netdev_uc_count(dev) > perfect_addr_number) + if (netdev_uc_count(dev) + 1 > perfect_addr_number) /* Switch to promiscuous mode if more than unicast * addresses are requested than supported by hardware. */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index c6fcfae27c3d..18b357b257cc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -521,7 +521,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw, value |= GMAC_PACKET_FILTER_HPF; /* Handle multiple unicast addresses */ - if (netdev_uc_count(dev) > hw->unicast_filter_entries) { + if (netdev_uc_count(dev) + 1 > hw->unicast_filter_entries) { /* Switch to promiscuous mode if more than 128 addrs * are required */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 52054f31376d..fc6ddb51c682 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -532,7 +532,7 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw, dwxgmac2_set_mchash(ioaddr, mc_filter, mcbitslog2); /* Handle multiple unicast addresses */ - if (netdev_uc_count(dev) > hw->unicast_filter_entries) { + if (netdev_uc_count(dev) + 1 > hw->unicast_filter_entries) { value |= XGMAC_FILTER_PR; } else { struct netdev_hw_addr *ha; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 8ba8f03e1ce0..7582fca63741 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -265,8 +265,6 @@ struct stmmac_priv { u32 rx_coal_frames[MTL_MAX_RX_QUEUES]; int hwts_tx_en; - /* skb_shinfo(skb)->gso_type types that we handle */ - unsigned int gso_enabled_types; bool tx_path_in_lpi_mode; bool sph_active; bool sph_capable; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index b2b7d0242dd3..f2fc89176654 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1531,9 +1531,9 @@ static void stmmac_display_rings(struct stmmac_priv *priv, static unsigned int stmmac_rx_offset(struct stmmac_priv *priv) { if (stmmac_xdp_is_enabled(priv)) - return XDP_PACKET_HEADROOM; + return XDP_PACKET_HEADROOM + NET_IP_ALIGN; - return NET_SKB_PAD; + return NET_SKB_PAD + NET_IP_ALIGN; } static int stmmac_set_bfsize(int mtu) @@ -2723,7 +2723,8 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) tx_desc = stmmac_get_tx_desc(priv, tx_q, entry); dma_addr = xsk_buff_raw_get_dma(pool, xdp_desc.addr); - meta = xsk_buff_get_metadata(pool, xdp_desc.addr); + meta = xsk_buff_get_metadata(pool, xdp_desc.addr, + xdp_desc.options); xsk_buff_raw_dma_sync_for_device(pool, dma_addr, xdp_desc.len); /* To return XDP buffer to XSK pool, we simple call @@ -4375,18 +4376,6 @@ static void stmmac_flush_tx_descriptors(struct stmmac_priv *priv, int queue) stmmac_set_queue_tx_tail_ptr(priv, tx_q, queue, tx_q->cur_tx); } -static void stmmac_set_gso_types(struct stmmac_priv *priv, bool tso) -{ - if (!tso) { - priv->gso_enabled_types = 0; - } else { - /* Manage oversized TCP frames for GMAC4 device */ - priv->gso_enabled_types = SKB_GSO_TCPV4 | SKB_GSO_TCPV6; - if (priv->plat->core_type == DWMAC_CORE_GMAC4) - priv->gso_enabled_types |= SKB_GSO_UDP_L4; - } -} - static void stmmac_set_gso_features(struct net_device *ndev) { struct stmmac_priv *priv = netdev_priv(ndev); @@ -4420,8 +4409,6 @@ static void stmmac_set_gso_features(struct net_device *ndev) if (priv->plat->core_type == DWMAC_CORE_GMAC4) ndev->hw_features |= NETIF_F_GSO_UDP_L4; - stmmac_set_gso_types(priv, true); - dev_info(priv->device, "TSO feature enabled\n"); } @@ -4771,8 +4758,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) if (priv->tx_path_in_lpi_mode && priv->eee_sw_timer_en) stmmac_stop_sw_lpi(priv); - if (skb_is_gso(skb) && - skb_shinfo(skb)->gso_type & priv->gso_enabled_types) + if (skb_is_gso(skb)) return stmmac_tso_xmit(skb, dev); if (priv->est && priv->est->enable && @@ -6206,8 +6192,6 @@ static int stmmac_set_features(struct net_device *netdev, stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan); } - stmmac_set_gso_types(priv, features & NETIF_F_TSO); - if (features & NETIF_F_HW_VLAN_CTAG_RX) priv->hw->hw_vlan_en = true; else diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index dc5f951a311d..6128ed1bd521 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -130,7 +130,6 @@ static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev) static int stmmac_mtl_setup(struct platform_device *pdev, struct plat_stmmacenet_data *plat) { - struct device_node *q_node; struct device_node *rx_node; struct device_node *tx_node; u8 queue = 0; @@ -169,7 +168,7 @@ static int stmmac_mtl_setup(struct platform_device *pdev, plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP; /* Processing individual RX queue config */ - for_each_child_of_node(rx_node, q_node) { + for_each_child_of_node_scoped(rx_node, q_node) { if (queue >= plat->rx_queues_to_use) break; @@ -227,7 +226,7 @@ static int stmmac_mtl_setup(struct platform_device *pdev, queue = 0; /* Processing individual TX queue config */ - for_each_child_of_node(tx_node, q_node) { + for_each_child_of_node_scoped(tx_node, q_node) { if (queue >= plat->tx_queues_to_use) break; @@ -276,7 +275,6 @@ static int stmmac_mtl_setup(struct platform_device *pdev, out: of_node_put(rx_node); of_node_put(tx_node); - of_node_put(q_node); return ret; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index 1df26c217f9a..6372ec7c3f31 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -395,11 +395,17 @@ static int stmmac_test_mmc(struct stmmac_priv *priv) stmmac_mmc_read(priv, priv->mmcaddr, &final); /* - * The number of MMC counters available depends on HW configuration - * so we just use this one to validate the feature. I hope there is - * not a version without this counter. + * The number of MMC counters available depends on HW configuration, + * and there doesn't seem to be a way to enumerate the implemented + * counters. + * + * Let's check a hand-picked set of counters, knowing that : + * - Starfive JH7110 doesn't implement mmc_tx_framecount_g + * - Amlogic SM1 doesn't implement any mmc_tx_* + * */ - if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g) + if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g && + final.mmc_rx_framecount_gb <= initial.mmc_rx_framecount_gb) return -EINVAL; return 0; @@ -473,6 +479,21 @@ static int stmmac_filter_check(struct stmmac_priv *priv) return -EOPNOTSUPP; } +static int stmmac_uc_filter_check(struct stmmac_priv *priv) +{ + /* For tests involving the UC filter, we need at least one empty + * slot in the UC filter. The UC filters contains netdev_uc_count() + 1 + * entries: The dev->uc list + one entry for the HW address. + * + * Having an empty slot therefore means netdev_uc_count() + 2 entries + * can fit in the filter + */ + if (netdev_uc_count(priv->dev) + 2 > priv->hw->unicast_filter_entries) + return -EOPNOTSUPP; + + return 0; +} + static bool stmmac_hash_check(struct stmmac_priv *priv, unsigned char *addr) { int mc_offset = 32 - priv->hw->mcast_bits_log2; @@ -564,7 +585,7 @@ static int stmmac_test_pfilt(struct stmmac_priv *priv) if (stmmac_filter_check(priv)) return -EOPNOTSUPP; - if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries) + if (stmmac_uc_filter_check(priv)) return -EOPNOTSUPP; while (--tries) { @@ -608,7 +629,7 @@ static int stmmac_test_mcfilt(struct stmmac_priv *priv) if (stmmac_filter_check(priv)) return -EOPNOTSUPP; - if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries) + if (stmmac_uc_filter_check(priv)) return -EOPNOTSUPP; if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins) return -EOPNOTSUPP; @@ -654,7 +675,7 @@ static int stmmac_test_ucfilt(struct stmmac_priv *priv) if (stmmac_filter_check(priv)) return -EOPNOTSUPP; - if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries) + if (stmmac_uc_filter_check(priv)) return -EOPNOTSUPP; if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins) return -EOPNOTSUPP; @@ -718,12 +739,24 @@ static int stmmac_test_flowctrl(struct stmmac_priv *priv) u32 rx_cnt = priv->plat->rx_queues_to_use; struct mac_device_info *mac = priv->hw; struct stmmac_test_priv *tpriv; + unsigned int rx_fifo_size; unsigned int pkt_count; int i, ret = 0; if (!(mac->link.caps & MAC_SYM_PAUSE)) return -EOPNOTSUPP; + rx_fifo_size = priv->plat->rx_fifo_size; + if (!rx_fifo_size) + rx_fifo_size = priv->dma_cap.rx_fifo_size; + + /* No pause frame is emitted if we don't have at least 4096 bytes per + * queue, except on dwmac100. + */ + if (priv->plat->core_type != DWMAC_CORE_MAC100 && + rx_fifo_size / priv->plat->rx_queues_to_use < 4096) + return -EOPNOTSUPP; + tpriv = kzalloc_obj(*tpriv); if (!tpriv) return -ENOMEM; @@ -737,9 +770,7 @@ static int stmmac_test_flowctrl(struct stmmac_priv *priv) dev_add_pack(&tpriv->pt); /* Compute minimum number of packets to make FIFO full */ - pkt_count = priv->plat->rx_fifo_size; - if (!pkt_count) - pkt_count = priv->dma_cap.rx_fifo_size; + pkt_count = rx_fifo_size; pkt_count /= 1400; pkt_count *= 2; @@ -1432,11 +1463,11 @@ static int __stmmac_test_l4filt(struct stmmac_priv *priv, u32 dst, u32 src, struct { struct flow_dissector_key_basic bkey; struct flow_dissector_key_ports key; - } __aligned(BITS_PER_LONG / 8) keys; + } __aligned(BITS_PER_LONG / 8) keys = { }; struct { struct flow_dissector_key_basic bmask; struct flow_dissector_key_ports mask; - } __aligned(BITS_PER_LONG / 8) masks; + } __aligned(BITS_PER_LONG / 8) masks = { }; unsigned long dummy_cookie = 0xdeadbeef; struct stmmac_packet_attrs attr = { }; struct flow_dissector *dissector; @@ -1489,6 +1520,8 @@ static int __stmmac_test_l4filt(struct stmmac_priv *priv, u32 dst, u32 src, keys.bkey.ip_proto = udp ? IPPROTO_UDP : IPPROTO_TCP; keys.key.src = htons(src); keys.key.dst = htons(dst); + /* Match the full IP proto field */ + masks.bmask.ip_proto = 0xff; masks.mask.src = src_mask; masks.mask.dst = dst_mask; diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ptp.c b/drivers/net/ethernet/wangxun/libwx/wx_ptp.c index 3eea647c4742..4708e7f3958f 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_ptp.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_ptp.c @@ -558,13 +558,11 @@ static int wx_ptp_set_timestamp_mode(struct wx *wx, { u32 tsync_tx_ctl = WX_TSC_1588_CTL_ENABLED; u32 tsync_rx_ctl = WX_PSR_1588_CTL_ENABLED; - DECLARE_BITMAP(flags, WX_PF_FLAGS_NBITS); u32 tsync_rx_mtrl = PTP_EV_PORT << 16; + bool rx_tstamp = false; bool is_l2 = false; u32 regval; - memcpy(flags, wx->flags, sizeof(wx->flags)); - switch (config->tx_type) { case HWTSTAMP_TX_OFF: tsync_tx_ctl = 0; @@ -579,20 +577,16 @@ static int wx_ptp_set_timestamp_mode(struct wx *wx, case HWTSTAMP_FILTER_NONE: tsync_rx_ctl = 0; tsync_rx_mtrl = 0; - clear_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, flags); - clear_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, flags); break; case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: tsync_rx_ctl |= WX_PSR_1588_CTL_TYPE_L4_V1; tsync_rx_mtrl |= WX_PSR_1588_MSG_V1_SYNC; - set_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, flags); - set_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, flags); + rx_tstamp = true; break; case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: tsync_rx_ctl |= WX_PSR_1588_CTL_TYPE_L4_V1; tsync_rx_mtrl |= WX_PSR_1588_MSG_V1_DELAY_REQ; - set_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, flags); - set_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, flags); + rx_tstamp = true; break; case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: @@ -605,9 +599,8 @@ static int wx_ptp_set_timestamp_mode(struct wx *wx, case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: tsync_rx_ctl |= WX_PSR_1588_CTL_TYPE_EVENT_V2; is_l2 = true; + rx_tstamp = true; config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; - set_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, flags); - set_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, flags); break; default: /* register PSR_1588_MSG must be set in order to do V1 packets, @@ -646,7 +639,8 @@ static int wx_ptp_set_timestamp_mode(struct wx *wx, WX_WRITE_FLUSH(wx); /* configure adapter flags only when HW is actually configured */ - memcpy(wx->flags, flags, sizeof(wx->flags)); + assign_bit(WX_FLAG_RX_HWTSTAMP_ENABLED, wx->flags, rx_tstamp); + assign_bit(WX_FLAG_RX_HWTSTAMP_IN_REGISTER, wx->flags, rx_tstamp); /* clear TX/RX timestamp state, just to be sure */ wx_ptp_clear_tx_timestamp(wx); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 2eba5ab59925..9454e90258d8 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -1446,7 +1446,7 @@ struct wx { }; #define WX_INTR_ALL (~0ULL) -#define WX_INTR_Q(i) BIT((i)) +#define WX_INTR_Q(i) BIT_ULL((i)) /* register operations */ #define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg))) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c index 8746318ad3bc..5ad1ff7c3ce9 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c @@ -164,6 +164,7 @@ static irqreturn_t txgbe_misc_irq_thread_fn(int irq, void *data) struct wx *wx = txgbe->wx; unsigned int nhandled = 0; unsigned int sub_irq; + u64 misc_mask; u32 eicr; eicr = txgbe->eicr; @@ -183,7 +184,9 @@ static irqreturn_t txgbe_misc_irq_thread_fn(int irq, void *data) nhandled++; } - wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); + misc_mask = wx->pdev->msix_enabled ? TXGBE_INTR_MISC(wx) : BIT(0); + if (!test_bit(WX_STATE_DOWN, wx->state)) + wx_intr_enable(wx, misc_mask); return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); } diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 3e93a3f309c1..757d1ce8d3ad 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -303,7 +303,7 @@ struct txgbe_fdir_filter { #define TXGBE_DEFAULT_RX_WORK 128 #endif -#define TXGBE_INTR_MISC(A) BIT((A)->num_q_vectors) +#define TXGBE_INTR_MISC(A) BIT_ULL((A)->num_q_vectors) #define TXGBE_INTR_QALL(A) (TXGBE_INTR_MISC(A) - 1) #define TXGBE_MAX_EITR GENMASK(11, 3) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 9a12cc53da00..298efc76a56b 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -12,6 +12,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> +#include <linux/mutex.h> #include <linux/skbuff.h> #include <linux/udp.h> #include <linux/rculist.h> @@ -108,6 +109,7 @@ struct gtp_net { }; static u32 gtp_h_initval; +static DEFINE_MUTEX(gtp_pdp_lock); static struct genl_family gtp_genl_family; @@ -151,7 +153,8 @@ static struct pdp_ctx *gtp0_pdp_find(struct gtp_dev *gtp, u64 tid, u16 family) head = >p->tid_hash[gtp0_hashfn(tid) % gtp->hash_size]; - hlist_for_each_entry_rcu(pdp, head, hlist_tid) { + hlist_for_each_entry_rcu(pdp, head, hlist_tid, + lockdep_is_held(>p_pdp_lock)) { if (pdp->af == family && pdp->gtp_version == GTP_V0 && pdp->u.v0.tid == tid) @@ -168,7 +171,8 @@ static struct pdp_ctx *gtp1_pdp_find(struct gtp_dev *gtp, u32 tid, u16 family) head = >p->tid_hash[gtp1u_hashfn(tid) % gtp->hash_size]; - hlist_for_each_entry_rcu(pdp, head, hlist_tid) { + hlist_for_each_entry_rcu(pdp, head, hlist_tid, + lockdep_is_held(>p_pdp_lock)) { if (pdp->af == family && pdp->gtp_version == GTP_V1 && pdp->u.v1.i_tei == tid) @@ -185,7 +189,8 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr) head = >p->addr_hash[ipv4_hashfn(ms_addr) % gtp->hash_size]; - hlist_for_each_entry_rcu(pdp, head, hlist_addr) { + hlist_for_each_entry_rcu(pdp, head, hlist_addr, + lockdep_is_held(>p_pdp_lock)) { if (pdp->af == AF_INET && pdp->ms.addr.s_addr == ms_addr) return pdp; @@ -220,7 +225,8 @@ static struct pdp_ctx *ipv6_pdp_find(struct gtp_dev *gtp, head = >p->addr_hash[ipv6_hashfn(ms_addr) % gtp->hash_size]; - hlist_for_each_entry_rcu(pdp, head, hlist_addr) { + hlist_for_each_entry_rcu(pdp, head, hlist_addr, + lockdep_is_held(>p_pdp_lock)) { if (pdp->af == AF_INET6 && ipv6_pdp_addr_equal(&pdp->ms.addr6, ms_addr)) return pdp; @@ -1543,6 +1549,8 @@ static int gtp_newlink(struct net_device *dev, out_encap: gtp_encap_disable(gtp); out_hashtable: + /* Wait for RCU readers that may still reference this gtp_dev. */ + synchronize_net(); kfree(gtp->addr_hash); kfree(gtp->tid_hash); return err; @@ -1555,9 +1563,11 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head) struct pdp_ctx *pctx; int i; + mutex_lock(>p_pdp_lock); for (i = 0; i < gtp->hash_size; i++) hlist_for_each_entry_safe(pctx, next, >p->tid_hash[i], hlist_tid) pdp_context_delete(pctx); + mutex_unlock(>p_pdp_lock); list_del(>p->list); unregister_netdevice_queue(dev, head); @@ -2053,6 +2063,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) goto out_unlock; } + mutex_lock(>p_pdp_lock); pctx = gtp_pdp_add(gtp, sk, info); if (IS_ERR(pctx)) { err = PTR_ERR(pctx); @@ -2060,6 +2071,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) gtp_tunnel_notify(pctx, GTP_CMD_NEWPDP, GFP_KERNEL); err = 0; } + mutex_unlock(>p_pdp_lock); out_unlock: rtnl_unlock(); @@ -2134,6 +2146,8 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[GTPA_VERSION]) return -EINVAL; + mutex_lock(>p_pdp_lock); + rcu_read_lock(); pctx = gtp_find_pdp(sock_net(skb->sk), info->attrs); @@ -2154,6 +2168,7 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info) out_unlock: rcu_read_unlock(); + mutex_unlock(>p_pdp_lock); return err; } diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index 3cd9e44680e9..14ac2d2faf7c 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -972,12 +972,12 @@ static void ipa_remove(struct platform_device *pdev) } if (ret) { /* - * Not cleaning up here properly might also yield a - * crash later on. As the device is still unregistered - * in this case, this might even yield a crash later on. + * Continuing teardown after failing to stop the modem + * could crash, so leave the remaining resources allocated. */ dev_err(dev, "Failed to stop modem (%pe), leaking resources\n", ERR_PTR(ret)); + pm_runtime_put_noidle(dev); return; } diff --git a/drivers/net/ipa/ipa_modem.c b/drivers/net/ipa/ipa_modem.c index 9b136f6b8b4a..d84c1dbd3b1a 100644 --- a/drivers/net/ipa/ipa_modem.c +++ b/drivers/net/ipa/ipa_modem.c @@ -266,13 +266,29 @@ void ipa_modem_suspend(struct net_device *netdev) * the modem. We can't enable the queue directly in ipa_modem_resume() * because transmits restart the instant the queue is awakened; but the * device power state won't be ACTIVE until *after* ipa_modem_resume() - * returns. + * returns. A transmit restarted before that would stop the queue + * again and get -EINPROGRESS from pm_runtime_get(), and with this + * work having already run, nothing would ever wake the queue again. + * So wait for the resume to complete before waking the queue. */ static void ipa_modem_wake_queue_work(struct work_struct *work) { struct ipa_priv *priv = container_of(work, struct ipa_priv, work); + struct device *dev = priv->ipa->dev; + int ret; + + ret = pm_runtime_get_sync(dev); + /* Wake the queue even if the device could not be resumed, so + * that pending packets are dropped by the transmit path rather + * than stranded behind a stopped queue. + */ netif_wake_queue(priv->tx->netdev); + + if (ret < 0) + pm_runtime_put_noidle(dev); + else + (void)pm_runtime_put_autosuspend(dev); } /** ipa_modem_resume() - resume callback for runtime_pm diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 4e9d7e10b527..b4a99f3ceac6 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -529,6 +529,7 @@ static void nsim_del_napi(struct netdevsim *ns) for (i = 0; i < dev->num_rx_queues; i++) { struct nsim_rq *rq = ns->rq[i]; + netif_queue_set_napi(dev, i, NETDEV_QUEUE_TYPE_RX, NULL); napi_disable_locked(&rq->napi); __netif_napi_del_locked(&rq->napi); } @@ -826,6 +827,7 @@ nsim_queue_start(struct net_device *dev, struct netdev_queue_config *qcfg, } ns->rq[idx] = qmem->rq; + netif_queue_set_napi(dev, idx, NETDEV_QUEUE_TYPE_RX, &ns->rq[idx]->napi); napi_enable_locked(&ns->rq[idx]->napi); return 0; diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index 029a4a532a10..9c171697e762 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -144,6 +144,9 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data, goto enqueue_again; } + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += len; + new_skb = netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN); if (!new_skb) { ndev->stats.rx_dropped++; @@ -155,13 +158,7 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data, skb->ip_summed = CHECKSUM_NONE; skb_record_rx_queue(skb, q->qid); - if (netif_rx(skb) == NET_RX_DROP) { - ndev->stats.rx_errors++; - ndev->stats.rx_dropped++; - } else { - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += len; - } + netif_rx(skb); skb = new_skb; @@ -199,8 +196,10 @@ static int __ntb_netdev_maybe_stop_tx(struct net_device *netdev, static int ntb_netdev_maybe_stop_tx(struct net_device *ndev, struct ntb_netdev_queue *q, int size) { - if (__netif_subqueue_stopped(ndev, q->qid) || - (ntb_transport_tx_free_entry(q->qp) >= size)) + if (__netif_subqueue_stopped(ndev, q->qid)) + return -EBUSY; + + if (ntb_transport_tx_free_entry(q->qp) >= size) return 0; return __ntb_netdev_maybe_stop_tx(ndev, q, size); @@ -256,21 +255,30 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb, q = &dev->queues[qid]; - ntb_netdev_maybe_stop_tx(ndev, q, tx_stop); + if (unlikely(ntb_netdev_maybe_stop_tx(ndev, q, tx_stop))) + return NETDEV_TX_BUSY; rc = ntb_transport_tx_enqueue(q->qp, skb, skb->data, skb->len); - if (rc) - goto err; + if (rc) { + if (rc == -EAGAIN || rc == -EBUSY) { + netif_stop_subqueue(ndev, q->qid); + mod_timer(&q->tx_timer, + jiffies + usecs_to_jiffies(tx_time)); + return NETDEV_TX_BUSY; + } + + goto drop; + } /* check for next submit */ ntb_netdev_maybe_stop_tx(ndev, q, tx_stop); return NETDEV_TX_OK; -err: +drop: + dev_kfree_skb_any(skb); ndev->stats.tx_dropped++; - ndev->stats.tx_errors++; - return NETDEV_TX_BUSY; + return NETDEV_TX_OK; } static void ntb_netdev_tx_timer(struct timer_list *t) diff --git a/drivers/net/phy/air_en8811h.c b/drivers/net/phy/air_en8811h.c index edd49c193e47..0eeb7b9a4e26 100644 --- a/drivers/net/phy/air_en8811h.c +++ b/drivers/net/phy/air_en8811h.c @@ -1173,13 +1173,6 @@ static int en8811h_probe(struct phy_device *phydev) if (ret) return ret; - /* Configure led gpio pins as output */ - ret = air_phy_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT, - EN8811H_GPIO_OUTPUT_345, - EN8811H_GPIO_OUTPUT_345); - if (ret < 0) - return ret; - return 0; } @@ -1324,6 +1317,17 @@ static int en8811h_config_init(struct phy_device *phydev) return ret; } + /* Configure led gpio pins as output. Must be redone on every + * .config_init(), not just once in .probe(): en8811h_restart_mcu() + * resets buckpbus-mapped MCU state (incl. this register) on every + * call after the first, e.g. on link renegotiation or ifup/ifdown. + */ + ret = air_phy_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT, + EN8811H_GPIO_OUTPUT_345, + EN8811H_GPIO_OUTPUT_345); + if (ret < 0) + return ret; + return 0; } diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 5b8e956902fb..3ec3bb439109 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -964,7 +964,7 @@ static unsigned int phylink_inband_caps(struct phylink *pl, return 0; pcs = pl->mac_ops->mac_select_pcs(pl->config, interface); - if (!pcs) + if (IS_ERR_OR_NULL(pcs)) return 0; return phylink_pcs_inband_caps(pcs, interface); diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index faae711cf793..fdd6f63fb849 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -628,9 +628,15 @@ static void sl_uninit(struct net_device *dev) struct slip *sl = netdev_priv(dev); sl_free_bufs(sl); + /* Drop the slip_devs[] entry here rather than from the destructor: + * ndo_uninit runs under RTNL, so it cannot race sl_sync(). + */ + slip_devs[dev->base_addr] = NULL; } -/* Hook the destructor so we can free slip devices at the right point in time */ +/* Only for the slip_open() error path: register_netdevice() can fail before + * ndo_init, and then ndo_uninit is not called either. + */ static void sl_free_netdev(struct net_device *dev) { int i = dev->base_addr; @@ -657,7 +663,6 @@ static void sl_setup(struct net_device *dev) { dev->netdev_ops = &sl_netdev_ops; dev->needs_free_netdev = true; - dev->priv_destructor = sl_free_netdev; dev->hard_header_len = 0; dev->addr_len = 0; @@ -881,8 +886,6 @@ err_exit: * Close down a SLIP channel. * This means flushing out any pending queues, and then returning. This * call is serialized against other ldisc functions. - * - * We also use this method fo a hangup event */ static void slip_close(struct tty_struct *tty) @@ -908,12 +911,7 @@ static void slip_close(struct tty_struct *tty) #endif /* Flush network side */ unregister_netdev(sl->dev); - /* This will complete via sl_free_netdev */ -} - -static void slip_hangup(struct tty_struct *tty) -{ - slip_close(tty); + /* sl_uninit() has dropped the slip_devs[] entry by now */ } /************************************************************************ * STANDARD SLIP ENCAPSULATION * @@ -1275,7 +1273,6 @@ static struct tty_ldisc_ops sl_ldisc = { .name = "slip", .open = slip_open, .close = slip_close, - .hangup = slip_hangup, .ioctl = slip_ioctl, .receive_buf = slip_receive_buf, .write_wakeup = slip_write_wakeup, diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c index 71c1aafca4d3..d9fb587a62c5 100644 --- a/drivers/net/thunderbolt/main.c +++ b/drivers/net/thunderbolt/main.c @@ -904,9 +904,11 @@ static int tbnet_poll(struct napi_struct *napi, int budget) le32_to_cpu(net->rx_hdr.frame_count) - 1; rx_packets++; - net->stats.rx_bytes += frame_size; if (last) { + /* Before eth_type_trans() pulls the Ethernet header. */ + net->stats.rx_packets++; + net->stats.rx_bytes += skb->len; skb->protocol = eth_type_trans(skb, net->dev); trace_tbnet_rx_skb(skb); napi_gro_receive(&net->napi, skb); @@ -914,8 +916,6 @@ static int tbnet_poll(struct napi_struct *napi, int budget) } } - net->stats.rx_packets += rx_packets; - if (cleaned_count) tbnet_alloc_rx_buffers(net, cleaned_count); diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 0223a172851e..35db38cb3e4a 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -2013,6 +2013,12 @@ static const struct usb_device_id cdc_devs[] = { }, /* Mac */ + { USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x1902, 0), + .driver_info = (unsigned long)&apple_private_interface_info, + }, + { USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x1902, 2), + .driver_info = (unsigned long)&apple_private_interface_info, + }, { USB_DEVICE_INTERFACE_NUMBER(0x05ac, 0x1905, 0), .driver_info = (unsigned long)&apple_private_interface_info, }, diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index ac88d1c85bea..459f19f7071e 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -1881,6 +1881,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) if (n) { struct vxlan_rdst *rdst = NULL; + u8 ha[ETH_ALEN] __aligned(2); struct vxlan_fdb *f; struct sk_buff *reply; @@ -1889,8 +1890,10 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) goto out; } + neigh_ha_snapshot(ha, n, n->dev); + rcu_read_lock(); - f = vxlan_find_mac_tx(vxlan, n->ha, vni); + f = vxlan_find_mac_tx(vxlan, ha, vni); if (f) rdst = first_remote_rcu(f); if (rdst && vxlan_addr_any(&rdst->remote_ip)) { @@ -1902,7 +1905,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) rcu_read_unlock(); reply = arp_create(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, - n->ha, sha); + ha, sha); neigh_release(n); @@ -1935,7 +1938,8 @@ out: #if IS_ENABLED(CONFIG_IPV6) static struct sk_buff *vxlan_na_create(struct sk_buff *request, - struct neighbour *n, bool isrouter) + struct neighbour *n, u8 *ha, + bool isrouter) { struct net_device *dev = request->dev; struct sk_buff *reply; @@ -1981,7 +1985,7 @@ static struct sk_buff *vxlan_na_create(struct sk_buff *request, /* Ethernet header */ ether_addr_copy(eth_hdr(reply)->h_dest, daddr); - ether_addr_copy(eth_hdr(reply)->h_source, n->ha); + ether_addr_copy(eth_hdr(reply)->h_source, ha); eth_hdr(reply)->h_proto = htons(ETH_P_IPV6); reply->protocol = htons(ETH_P_IPV6); @@ -2010,7 +2014,7 @@ static struct sk_buff *vxlan_na_create(struct sk_buff *request, na->icmph.icmp6_override = 1; na->icmph.icmp6_solicited = 1; na->target = ns->target; - ether_addr_copy(&na->opt[2], n->ha); + ether_addr_copy(&na->opt[2], ha); na->opt[0] = ND_OPT_TARGET_LL_ADDR; na->opt[1] = na_olen >> 3; @@ -2051,6 +2055,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) if (n) { struct vxlan_rdst *rdst = NULL; + u8 ha[ETH_ALEN] __aligned(2); struct vxlan_fdb *f; struct sk_buff *reply; @@ -2059,7 +2064,8 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) goto out; } - f = vxlan_find_mac_tx(vxlan, n->ha, vni); + neigh_ha_snapshot(ha, n, n->dev); + f = vxlan_find_mac_tx(vxlan, ha, vni); if (f) rdst = first_remote_rcu(f); if (rdst && vxlan_addr_any(&rdst->remote_ip)) { @@ -2068,7 +2074,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) goto out; } - reply = vxlan_na_create(skb, n, + reply = vxlan_na_create(skb, n, ha, !!(f ? f->flags & NTF_ROUTER : 0)); neigh_release(n); diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index f59f926d4bfa..f9caa1a653c5 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -1719,9 +1719,16 @@ static void ntb_transport_rxc_db(unsigned long data) static void ntb_tx_copy_callback(void *data, const struct dmaengine_result *res) { + struct ntb_payload_header __iomem *hdr; struct ntb_queue_entry *entry = data; - struct ntb_transport_qp *qp = entry->qp; - struct ntb_payload_header __iomem *hdr = entry->tx_hdr; + struct ntb_transport_qp *qp; + unsigned int len; + void *cb_data; + + qp = entry->qp; + hdr = entry->tx_hdr; + cb_data = entry->cb_data; + len = entry->len; /* we need to check DMA results if we are using DMA */ if (res) { @@ -1768,15 +1775,13 @@ static void ntb_tx_copy_callback(void *data, * "link down" or similar. Since no payload is being sent in these * cases, there is nothing to add to the completion queue. */ - if (entry->len > 0) { - qp->tx_bytes += entry->len; - - if (qp->tx_handler) - qp->tx_handler(qp, qp->cb_data, entry->cb_data, - entry->len); - } + if (len > 0) + qp->tx_bytes += len; ntb_list_add(&qp->ntb_tx_free_q_lock, &entry->entry, &qp->tx_free_q); + + if (len > 0 && qp->tx_handler) + qp->tx_handler(qp, qp->cb_data, cb_data, len); } static void ntb_memcpy_tx_on_stack(struct ntb_queue_entry *entry, void __iomem *offset) @@ -1950,15 +1955,6 @@ static int ntb_process_tx(struct ntb_transport_qp *qp, return -EAGAIN; } - if (entry->len > qp->tx_max_frame - sizeof(struct ntb_payload_header)) { - if (qp->tx_handler) - qp->tx_handler(qp, qp->cb_data, NULL, -EIO); - - ntb_list_add(&qp->ntb_tx_free_q_lock, &entry->entry, - &qp->tx_free_q); - return 0; - } - ntb_async_tx(qp, entry); qp->tx_pkts++; @@ -2348,9 +2344,11 @@ int ntb_transport_tx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data, if (!qp || !len) return -EINVAL; - /* If the qp link is down already, just ignore. */ if (!qp->link_is_up) - return 0; + return -ENOLINK; + + if (len > qp->tx_max_frame - sizeof(struct ntb_payload_header)) + return -EMSGSIZE; entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q); if (!entry) { diff --git a/drivers/ptp/ptp_netc.c b/drivers/ptp/ptp_netc.c index 59db08e189e6..19ca99d80e95 100644 --- a/drivers/ptp/ptp_netc.c +++ b/drivers/ptp/ptp_netc.c @@ -440,7 +440,7 @@ static int net_timer_enable_perout(struct netc_timer *priv, } if (on) { - u64 period_ns, gclk_period, max_period, min_period; + u64 period_ns, gclk_period, min_period; struct timespec64 period, stime; u32 integral_period; int alarm_id; @@ -450,12 +450,12 @@ static int net_timer_enable_perout(struct netc_timer *priv, period_ns = timespec64_to_ns(&period); integral_period = netc_timer_get_integral_period(priv); - max_period = (u64)NETC_TMR_DEFAULT_FIPER + integral_period; gclk_period = netc_timer_get_gclk_period(priv); min_period = gclk_period * 4 + integral_period; - if (period_ns > max_period || period_ns < min_period) { - dev_err(dev, "The period range is %llu ~ %llu\n", - min_period, max_period); + if (period_ns > NETC_TMR_DEFAULT_FIPER || + period_ns < min_period) { + dev_err(dev, "The period range is %llu ~ %lu\n", + min_period, NETC_TMR_DEFAULT_FIPER); err = -EINVAL; goto unlock_spinlock; } diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 9600e1ec0993..7b0c791399ea 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -917,8 +917,8 @@ static int usbatm_atm_init(struct usbatm_data *instance) instance->atm_dev = atm_dev; - atm_dev->ci_range.vpi_bits = ATM_CI_MAX; - atm_dev->ci_range.vci_bits = ATM_CI_MAX; + atm_dev->ci_range.vpi_bits = 8; + atm_dev->ci_range.vci_bits = 16; atm_dev->signal = ATM_PHY_SIG_UNKNOWN; /* temp init ATM device, set to 128kbit */ |
