diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-12-12 20:37:22 +0300 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-12-12 20:37:22 +0300 |
| commit | afab69dcd2367d658853a3520fb06d356ccabb7f (patch) | |
| tree | eadb66b0176308a9e57480f0675d81ef05b5d776 /drivers/net | |
| parent | 9319aefb0f8805af379d375403b5ba48a0d3ef1b (diff) | |
| parent | 53d3c6ddbb9749ebc06956a13ed6eead31402a7d (diff) | |
| download | linux-rolling-lts.tar.xz | |
Merge v6.12.62linux-rolling-lts
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/net')
30 files changed, 381 insertions, 175 deletions
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index 24dd15c91722..ba662bef155c 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -681,26 +681,6 @@ static void rcar_canfd_tx_failure_cleanup(struct net_device *ndev) can_free_echo_skb(ndev, i, NULL); } -static void rcar_canfd_set_mode(struct rcar_canfd_global *gpriv) -{ - if (is_gen4(gpriv)) { - u32 ch, val = gpriv->fdmode ? RCANFD_GEN4_FDCFG_FDOE - : RCANFD_GEN4_FDCFG_CLOE; - - for_each_set_bit(ch, &gpriv->channels_mask, - gpriv->info->max_channels) - rcar_canfd_set_bit(gpriv->base, RCANFD_GEN4_FDCFG(ch), - val); - } else { - if (gpriv->fdmode) - rcar_canfd_set_bit(gpriv->base, RCANFD_GRMCFG, - RCANFD_GRMCFG_RCMC); - else - rcar_canfd_clear_bit(gpriv->base, RCANFD_GRMCFG, - RCANFD_GRMCFG_RCMC); - } -} - static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) { u32 sts, ch; @@ -732,6 +712,16 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) /* Reset Global error flags */ rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0); + /* Set the controller into appropriate mode */ + if (!is_gen4(gpriv)) { + if (gpriv->fdmode) + rcar_canfd_set_bit(gpriv->base, RCANFD_GRMCFG, + RCANFD_GRMCFG_RCMC); + else + rcar_canfd_clear_bit(gpriv->base, RCANFD_GRMCFG, + RCANFD_GRMCFG_RCMC); + } + /* Transition all Channels to reset mode */ for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) { rcar_canfd_clear_bit(gpriv->base, @@ -750,10 +740,27 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) "channel %u reset failed\n", ch); return err; } - } - /* Set the controller into appropriate mode */ - rcar_canfd_set_mode(gpriv); + /* Set the controller into appropriate mode */ + if (is_gen4(gpriv)) { + /* Do not set CLOE and FDOE simultaneously */ + if (!gpriv->fdmode) { + rcar_canfd_clear_bit(gpriv->base, + RCANFD_GEN4_FDCFG(ch), + RCANFD_GEN4_FDCFG_FDOE); + rcar_canfd_set_bit(gpriv->base, + RCANFD_GEN4_FDCFG(ch), + RCANFD_GEN4_FDCFG_CLOE); + } else { + rcar_canfd_clear_bit(gpriv->base, + RCANFD_GEN4_FDCFG(ch), + RCANFD_GEN4_FDCFG_FDOE); + rcar_canfd_clear_bit(gpriv->base, + RCANFD_GEN4_FDCFG(ch), + RCANFD_GEN4_FDCFG_CLOE); + } + } + } return 0; } diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 4d245857ef1c..83476af8adb5 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -548,8 +548,8 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF) goto out; - while ((isrc = priv->read_reg(priv, SJA1000_IR)) && - (n < SJA1000_MAX_IRQ)) { + while ((n < SJA1000_MAX_IRQ) && + (isrc = priv->read_reg(priv, SJA1000_IR))) { status = priv->read_reg(priv, SJA1000_SR); /* check for absent controller due to hw unplug */ diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 30b30fdbcae9..212de6d67322 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -657,8 +657,8 @@ static irqreturn_t sun4i_can_interrupt(int irq, void *dev_id) u8 isrc, status; int n = 0; - while ((isrc = readl(priv->base + SUN4I_REG_INT_ADDR)) && - (n < SUN4I_CAN_MAX_IRQ)) { + while ((n < SUN4I_CAN_MAX_IRQ) && + (isrc = readl(priv->base + SUN4I_REG_INT_ADDR))) { n++; status = readl(priv->base + SUN4I_REG_STA_ADDR); diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index fb904dc28b8e..36540a254458 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -258,14 +258,21 @@ struct canfd_quirk { u8 quirk; } __packed; +/* struct gs_host_frame::echo_id == GS_HOST_FRAME_ECHO_ID_RX indicates + * a regular RX'ed CAN frame + */ +#define GS_HOST_FRAME_ECHO_ID_RX 0xffffffff + struct gs_host_frame { - u32 echo_id; - __le32 can_id; + struct_group(header, + u32 echo_id; + __le32 can_id; - u8 can_dlc; - u8 channel; - u8 flags; - u8 reserved; + u8 can_dlc; + u8 channel; + u8 flags; + u8 reserved; + ); union { DECLARE_FLEX_ARRAY(struct classic_can, classic_can); @@ -565,6 +572,37 @@ gs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb, return len; } +static unsigned int +gs_usb_get_minimum_rx_length(const struct gs_can *dev, const struct gs_host_frame *hf, + unsigned int *data_length_p) +{ + unsigned int minimum_length, data_length = 0; + + if (hf->flags & GS_CAN_FLAG_FD) { + if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) + data_length = can_fd_dlc2len(hf->can_dlc); + + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + /* timestamp follows data field of max size */ + minimum_length = struct_size(hf, canfd_ts, 1); + else + minimum_length = sizeof(hf->header) + data_length; + } else { + if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX && + !(hf->can_id & cpu_to_le32(CAN_RTR_FLAG))) + data_length = can_cc_dlc2len(hf->can_dlc); + + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + /* timestamp follows data field of max size */ + minimum_length = struct_size(hf, classic_can_ts, 1); + else + minimum_length = sizeof(hf->header) + data_length; + } + + *data_length_p = data_length; + return minimum_length; +} + static void gs_usb_receive_bulk_callback(struct urb *urb) { struct gs_usb *parent = urb->context; @@ -573,6 +611,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) int rc; struct net_device_stats *stats; struct gs_host_frame *hf = urb->transfer_buffer; + unsigned int minimum_length, data_length; struct gs_tx_context *txc; struct can_frame *cf; struct canfd_frame *cfd; @@ -591,6 +630,15 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) return; } + minimum_length = sizeof(hf->header); + if (urb->actual_length < minimum_length) { + dev_err_ratelimited(&parent->udev->dev, + "short read (actual_length=%u, minimum_length=%u)\n", + urb->actual_length, minimum_length); + + goto resubmit_urb; + } + /* device reports out of range channel id */ if (hf->channel >= parent->channel_cnt) goto device_detach; @@ -606,20 +654,33 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) if (!netif_running(netdev)) goto resubmit_urb; - if (hf->echo_id == -1) { /* normal rx */ + minimum_length = gs_usb_get_minimum_rx_length(dev, hf, &data_length); + if (urb->actual_length < minimum_length) { + stats->rx_errors++; + stats->rx_length_errors++; + + if (net_ratelimit()) + netdev_err(netdev, + "short read (actual_length=%u, minimum_length=%u)\n", + urb->actual_length, minimum_length); + + goto resubmit_urb; + } + + if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) { /* normal rx */ if (hf->flags & GS_CAN_FLAG_FD) { skb = alloc_canfd_skb(netdev, &cfd); if (!skb) return; cfd->can_id = le32_to_cpu(hf->can_id); - cfd->len = can_fd_dlc2len(hf->can_dlc); + cfd->len = data_length; if (hf->flags & GS_CAN_FLAG_BRS) cfd->flags |= CANFD_BRS; if (hf->flags & GS_CAN_FLAG_ESI) cfd->flags |= CANFD_ESI; - memcpy(cfd->data, hf->canfd->data, cfd->len); + memcpy(cfd->data, hf->canfd->data, data_length); } else { skb = alloc_can_skb(netdev, &cf); if (!skb) @@ -628,7 +689,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) cf->can_id = le32_to_cpu(hf->can_id); can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); - memcpy(cf->data, hf->classic_can->data, 8); + memcpy(cf->data, hf->classic_can->data, data_length); /* ERROR frames tell us information about the controller */ if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) @@ -684,7 +745,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) resubmit_urb: usb_fill_bulk_urb(urb, parent->udev, parent->pipe_in, - hf, dev->parent->hf_size_rx, + hf, parent->hf_size_rx, gs_usb_receive_bulk_callback, parent); rc = usb_submit_urb(urb, GFP_ATOMIC); @@ -747,8 +808,21 @@ static void gs_usb_xmit_callback(struct urb *urb) struct gs_can *dev = txc->dev; struct net_device *netdev = dev->netdev; - if (urb->status) - netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id); + if (!urb->status) + return; + + if (urb->status != -ESHUTDOWN && net_ratelimit()) + netdev_info(netdev, "failed to xmit URB %u: %pe\n", + txc->echo_id, ERR_PTR(urb->status)); + + netdev->stats.tx_dropped++; + netdev->stats.tx_errors++; + + can_free_echo_skb(netdev, txc->echo_id, NULL); + gs_free_tx_context(txc); + atomic_dec(&dev->active_tx_urbs); + + netif_wake_queue(netdev); } static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index 6b9122ab1464..b7f6935686c9 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -662,7 +662,7 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, * for further details. */ if (tmp->len == 0) { - pos = round_up(pos, + pos = round_up(pos + 1, le16_to_cpu (dev->bulk_in->wMaxPacketSize)); continue; @@ -1672,7 +1672,7 @@ static void kvaser_usb_leaf_read_bulk_callback(struct kvaser_usb *dev, * number of events in case of a heavy rx load on the bus. */ if (cmd->len == 0) { - pos = round_up(pos, le16_to_cpu + pos = round_up(pos + 1, le16_to_cpu (dev->bulk_in->wMaxPacketSize)); continue; } diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 5cfbb6205885..ff47c7cfc582 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -1342,6 +1342,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .supports_rgmii = {false, false, true}, .internal_phy = {true, true, false}, .gbit_capable = {false, false, true}, + .ptp_capable = true, .wr_table = &ksz8563_register_set, .rd_table = &ksz8563_register_set, }, @@ -1553,6 +1554,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .internal_phy = {true, true, true, true, true, false, false}, .gbit_capable = {true, true, true, true, true, true, true}, + .ptp_capable = true, .wr_table = &ksz9477_register_set, .rd_table = &ksz9477_register_set, }, @@ -1680,6 +1682,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .supports_rgmii = {false, false, true}, .internal_phy = {true, true, false}, .gbit_capable = {true, true, true}, + .ptp_capable = true, }, [KSZ8567] = { @@ -1715,6 +1718,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { true, false, false}, .gbit_capable = {false, false, false, false, false, true, true}, + .ptp_capable = true, }, [KSZ9567] = { @@ -1747,6 +1751,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .internal_phy = {true, true, true, true, true, false, false}, .gbit_capable = {true, true, true, true, true, true, true}, + .ptp_capable = true, }, [LAN9370] = { @@ -1775,6 +1780,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .supports_rmii = {false, false, false, false, true}, .supports_rgmii = {false, false, false, false, true}, .internal_phy = {true, true, true, true, false}, + .ptp_capable = true, }, [LAN9371] = { @@ -1803,6 +1809,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .supports_rmii = {false, false, false, false, true, true}, .supports_rgmii = {false, false, false, false, true, true}, .internal_phy = {true, true, true, true, false, false}, + .ptp_capable = true, }, [LAN9372] = { @@ -1835,6 +1842,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { true, true, false, false}, .internal_phy = {true, true, true, true, false, false, true, true}, + .ptp_capable = true, }, [LAN9373] = { @@ -1867,6 +1875,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { true, true, false, false}, .internal_phy = {true, true, true, false, false, false, true, true}, + .ptp_capable = true, }, [LAN9374] = { @@ -1899,6 +1908,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { true, true, false, false}, .internal_phy = {true, true, true, true, false, false, true, true}, + .ptp_capable = true, }, }; EXPORT_SYMBOL_GPL(ksz_switch_chips); @@ -2254,8 +2264,8 @@ static int ksz_irq_phy_setup(struct ksz_device *dev) if (BIT(phy) & ds->phys_mii_mask) { irq = irq_find_mapping(dev->ports[phy].pirq.domain, PORT_SRC_PHY_INT); - if (irq < 0) { - ret = irq; + if (!irq) { + ret = -EINVAL; goto out; } ds->user_mii_bus->irq[phy] = irq; @@ -2479,8 +2489,8 @@ static int ksz_pirq_setup(struct ksz_device *dev, u8 p) snprintf(pirq->name, sizeof(pirq->name), "port_irq-%d", p); pirq->irq_num = irq_find_mapping(dev->girq.domain, p); - if (pirq->irq_num < 0) - return pirq->irq_num; + if (!pirq->irq_num) + return -EINVAL; return ksz_irq_common_setup(dev, pirq); } @@ -2554,18 +2564,23 @@ static int ksz_setup(struct dsa_switch *ds) dsa_switch_for_each_user_port(dp, dev->ds) { ret = ksz_pirq_setup(dev, dp->index); if (ret) - goto out_girq; + goto port_release; - ret = ksz_ptp_irq_setup(ds, dp->index); - if (ret) - goto out_pirq; + if (dev->info->ptp_capable) { + ret = ksz_ptp_irq_setup(ds, dp->index); + if (ret) + goto pirq_release; + } } } - ret = ksz_ptp_clock_register(ds); - if (ret) { - dev_err(dev->dev, "Failed to register PTP clock: %d\n", ret); - goto out_ptpirq; + if (dev->info->ptp_capable) { + ret = ksz_ptp_clock_register(ds); + if (ret) { + dev_err(dev->dev, "Failed to register PTP clock: %d\n", + ret); + goto port_release; + } } ret = ksz_mdio_register(dev); @@ -2585,18 +2600,18 @@ static int ksz_setup(struct dsa_switch *ds) return 0; out_ptp_clock_unregister: - ksz_ptp_clock_unregister(ds); -out_ptpirq: - if (dev->irq > 0) - dsa_switch_for_each_user_port(dp, dev->ds) - ksz_ptp_irq_free(ds, dp->index); -out_pirq: - if (dev->irq > 0) - dsa_switch_for_each_user_port(dp, dev->ds) + if (dev->info->ptp_capable) + ksz_ptp_clock_unregister(ds); +port_release: + if (dev->irq > 0) { + dsa_switch_for_each_user_port_continue_reverse(dp, dev->ds) { + if (dev->info->ptp_capable) + ksz_ptp_irq_free(ds, dp->index); +pirq_release: ksz_irq_free(&dev->ports[dp->index].pirq); -out_girq: - if (dev->irq > 0) + } ksz_irq_free(&dev->girq); + } return ret; } @@ -2606,11 +2621,13 @@ static void ksz_teardown(struct dsa_switch *ds) struct ksz_device *dev = ds->priv; struct dsa_port *dp; - ksz_ptp_clock_unregister(ds); + if (dev->info->ptp_capable) + ksz_ptp_clock_unregister(ds); if (dev->irq > 0) { dsa_switch_for_each_user_port(dp, dev->ds) { - ksz_ptp_irq_free(ds, dp->index); + if (dev->info->ptp_capable) + ksz_ptp_irq_free(ds, dp->index); ksz_irq_free(&dev->ports[dp->index].pirq); } diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 4ee518f8addc..36f2fd77619f 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -86,6 +86,7 @@ struct ksz_chip_data { bool supports_rgmii[KSZ_MAX_NUM_PORTS]; bool internal_phy[KSZ_MAX_NUM_PORTS]; bool gbit_capable[KSZ_MAX_NUM_PORTS]; + bool ptp_capable; const struct regmap_access_table *wr_table; const struct regmap_access_table *rd_table; }; diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchip/ksz_ptp.c index 050f17c43ef6..b6fcdabbf5dd 100644 --- a/drivers/net/dsa/microchip/ksz_ptp.c +++ b/drivers/net/dsa/microchip/ksz_ptp.c @@ -1099,19 +1099,19 @@ static int ksz_ptp_msg_irq_setup(struct ksz_port *port, u8 n) static const char * const name[] = {"pdresp-msg", "xdreq-msg", "sync-msg"}; const struct ksz_dev_ops *ops = port->ksz_dev->dev_ops; + struct ksz_irq *ptpirq = &port->ptpirq; struct ksz_ptp_irq *ptpmsg_irq; ptpmsg_irq = &port->ptpmsg_irq[n]; + ptpmsg_irq->num = irq_create_mapping(ptpirq->domain, n); + if (!ptpmsg_irq->num) + return -EINVAL; ptpmsg_irq->port = port; ptpmsg_irq->ts_reg = ops->get_port_addr(port->num, ts_reg[n]); snprintf(ptpmsg_irq->name, sizeof(ptpmsg_irq->name), name[n]); - ptpmsg_irq->num = irq_find_mapping(port->ptpirq.domain, n); - if (ptpmsg_irq->num < 0) - return ptpmsg_irq->num; - return request_threaded_irq(ptpmsg_irq->num, NULL, ksz_ptp_msg_thread_fn, IRQF_ONESHOT, ptpmsg_irq->name, ptpmsg_irq); @@ -1141,12 +1141,9 @@ int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p) if (!ptpirq->domain) return -ENOMEM; - for (irq = 0; irq < ptpirq->nirqs; irq++) - irq_create_mapping(ptpirq->domain, irq); - ptpirq->irq_num = irq_find_mapping(port->pirq.domain, PORT_SRC_PTP_INT); - if (ptpirq->irq_num < 0) { - ret = ptpirq->irq_num; + if (!ptpirq->irq_num) { + ret = -EINVAL; goto out; } @@ -1165,12 +1162,11 @@ int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p) out_ptp_msg: free_irq(ptpirq->irq_num, ptpirq); - while (irq--) + while (irq--) { free_irq(port->ptpmsg_irq[irq].num, &port->ptpmsg_irq[irq]); -out: - for (irq = 0; irq < ptpirq->nirqs; irq++) irq_dispose_mapping(port->ptpmsg_irq[irq].num); - + } +out: irq_domain_remove(ptpirq->domain); return ret; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index fbac2a647b20..a078653531b5 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1257,29 +1257,11 @@ static int sja1105_parse_dt(struct sja1105_private *priv) return rc; } -/* Convert link speed from SJA1105 to ethtool encoding */ -static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv, - u64 speed) -{ - if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS]) - return SPEED_10; - if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS]) - return SPEED_100; - if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) - return SPEED_1000; - if (speed == priv->info->port_speed[SJA1105_SPEED_2500MBPS]) - return SPEED_2500; - return SPEED_UNKNOWN; -} - -/* Set link speed in the MAC configuration for a specific port. */ -static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, - int speed_mbps) +static int sja1105_set_port_speed(struct sja1105_private *priv, int port, + int speed_mbps) { struct sja1105_mac_config_entry *mac; - struct device *dev = priv->ds->dev; u64 speed; - int rc; /* On P/Q/R/S, one can read from the device via the MAC reconfiguration * tables. On E/T, MAC reconfig tables are not readable, only writable. @@ -1313,7 +1295,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; break; default: - dev_err(dev, "Invalid speed %iMbps\n", speed_mbps); + dev_err(priv->ds->dev, "Invalid speed %iMbps\n", speed_mbps); return -EINVAL; } @@ -1321,15 +1303,28 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, * table, since this will be used for the clocking setup, and we no * longer need to store it in the static config (already told hardware * we want auto during upload phase). - * Actually for the SGMII port, the MAC is fixed at 1 Gbps and - * we need to configure the PCS only (if even that). */ - if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) - mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; - else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) - mac[port].speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; - else - mac[port].speed = speed; + mac[port].speed = speed; + + return 0; +} + +/* Write the MAC Configuration Table entry and, if necessary, the CGU settings, + * after a link speedchange for this port. + */ +static int sja1105_set_port_config(struct sja1105_private *priv, int port) +{ + struct sja1105_mac_config_entry *mac; + struct device *dev = priv->ds->dev; + int rc; + + /* On P/Q/R/S, one can read from the device via the MAC reconfiguration + * tables. On E/T, MAC reconfig tables are not readable, only writable. + * We have to *know* what the MAC looks like. For the sake of keeping + * the code common, we'll use the static configuration tables as a + * reasonable approximation for both E/T and P/Q/R/S. + */ + mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; /* Write to the dynamic reconfiguration tables */ rc = sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, port, @@ -1390,7 +1385,8 @@ static void sja1105_mac_link_up(struct phylink_config *config, struct sja1105_private *priv = dp->ds->priv; int port = dp->index; - sja1105_adjust_port_config(priv, port, speed); + if (!sja1105_set_port_speed(priv, port, speed)) + sja1105_set_port_config(priv, port); sja1105_inhibit_tx(priv, BIT(port), false); } @@ -2289,8 +2285,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, { struct ptp_system_timestamp ptp_sts_before; struct ptp_system_timestamp ptp_sts_after; - int speed_mbps[SJA1105_MAX_NUM_PORTS]; u16 bmcr[SJA1105_MAX_NUM_PORTS] = {0}; + u64 mac_speed[SJA1105_MAX_NUM_PORTS]; struct sja1105_mac_config_entry *mac; struct dsa_switch *ds = priv->ds; s64 t1, t2, t3, t4; @@ -2303,14 +2299,13 @@ int sja1105_static_config_reload(struct sja1105_private *priv, mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; - /* Back up the dynamic link speed changed by sja1105_adjust_port_config + /* Back up the dynamic link speed changed by sja1105_set_port_speed() * in order to temporarily restore it to SJA1105_SPEED_AUTO - which the * switch wants to see in the static config in order to allow us to * change it through the dynamic interface later. */ for (i = 0; i < ds->num_ports; i++) { - speed_mbps[i] = sja1105_port_speed_to_ethtool(priv, - mac[i].speed); + mac_speed[i] = mac[i].speed; mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO]; if (priv->xpcs[i]) @@ -2373,7 +2368,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, struct dw_xpcs *xpcs = priv->xpcs[i]; unsigned int neg_mode; - rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]); + mac[i].speed = mac_speed[i]; + rc = sja1105_set_port_config(priv, i); if (rc < 0) goto out; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c index 1921741f7311..18b08277d2e1 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c @@ -15,6 +15,7 @@ #include "aq_hw.h" #include "aq_nic.h" +#include "hw_atl/hw_atl_llh.h" void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, u32 shift, u32 val) @@ -81,6 +82,27 @@ void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value) lo_hi_writeq(value, hw->mmio + reg); } +int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw) +{ + int err; + u32 val; + + /* Invalidate Descriptor Cache to prevent writing to the cached + * descriptors and to the data pointer of those descriptors + */ + hw_atl_rdm_rx_dma_desc_cache_init_tgl(hw); + + err = aq_hw_err_from_flags(hw); + if (err) + goto err_exit; + + readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, + hw, val, val == 1, 1000U, 10000U); + +err_exit: + return err; +} + int aq_hw_err_from_flags(struct aq_hw_s *hw) { int err = 0; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h index ffa6e4067c21..d89c63d88e4a 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h @@ -35,6 +35,7 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg); void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value); u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg); void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value); +int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw); int aq_hw_err_from_flags(struct aq_hw_s *hw); int aq_hw_num_tcs(struct aq_hw_s *hw); int aq_hw_q_per_tc(struct aq_hw_s *hw); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index f21de0c21e52..d23d23bed39f 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -547,6 +547,11 @@ static int __aq_ring_rx_clean(struct aq_ring_s *self, struct napi_struct *napi, if (!buff->is_eop) { unsigned int frag_cnt = 0U; + + /* There will be an extra fragment */ + if (buff->len > AQ_CFG_RX_HDR_SIZE) + frag_cnt++; + buff_ = buff; do { bool is_rsc_completed = true; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 56c46266bb0a..3a0b6d65d5fc 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -1198,26 +1198,9 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) static int hw_atl_b0_hw_stop(struct aq_hw_s *self) { - int err; - u32 val; - hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); - /* Invalidate Descriptor Cache to prevent writing to the cached - * descriptors and to the data pointer of those descriptors - */ - hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); - - err = aq_hw_err_from_flags(self); - - if (err) - goto err_exit; - - readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, - self, val, val == 1, 1000U, 10000U); - -err_exit: - return err; + return aq_hw_invalidate_descriptor_cache(self); } int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c index b0ed572e88c6..0ce9caae8799 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c @@ -759,7 +759,7 @@ static int hw_atl2_hw_stop(struct aq_hw_s *self) { hw_atl_b0_hw_irq_disable(self, HW_ATL2_INT_MASK); - return 0; + return aq_hw_invalidate_descriptor_cache(self); } static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 1cca0425d493..03fa6d6e6f0a 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -683,6 +683,7 @@ struct fec_enet_private { unsigned int reload_period; int pps_enable; unsigned int next_counter; + bool perout_enable; struct hrtimer perout_timer; u64 perout_stime; diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 7f6b57432071..4bb894b5afcb 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -129,6 +129,12 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) spin_lock_irqsave(&fep->tmreg_lock, flags); + if (fep->perout_enable) { + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + dev_err(&fep->pdev->dev, "PEROUT is running"); + return -EBUSY; + } + if (fep->pps_enable == enable) { spin_unlock_irqrestore(&fep->tmreg_lock, flags); return 0; @@ -244,6 +250,7 @@ static int fec_ptp_pps_perout(struct fec_enet_private *fep) * the FEC_TCCR register in time and missed the start time. */ if (fep->perout_stime < curr_time + 100 * NSEC_PER_MSEC) { + fep->perout_enable = false; dev_err(&fep->pdev->dev, "Current time is too close to the start time!\n"); spin_unlock_irqrestore(&fep->tmreg_lock, flags); return -1; @@ -498,7 +505,10 @@ static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel) { unsigned long flags; + hrtimer_cancel(&fep->perout_timer); + spin_lock_irqsave(&fep->tmreg_lock, flags); + fep->perout_enable = false; writel(0, fep->hwp + FEC_TCSR(channel)); spin_unlock_irqrestore(&fep->tmreg_lock, flags); @@ -530,6 +540,8 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, return ret; } else if (rq->type == PTP_CLK_REQ_PEROUT) { + u32 reload_period; + /* Reject requests with unsupported flags */ if (rq->perout.flags) return -EOPNOTSUPP; @@ -549,12 +561,14 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, return -EOPNOTSUPP; } - fep->reload_period = div_u64(period_ns, 2); - if (on && fep->reload_period) { + reload_period = div_u64(period_ns, 2); + if (on && reload_period) { + u64 perout_stime; + /* Convert 1588 timestamp to ns*/ start_time.tv_sec = rq->perout.start.sec; start_time.tv_nsec = rq->perout.start.nsec; - fep->perout_stime = timespec64_to_ns(&start_time); + perout_stime = timespec64_to_ns(&start_time); mutex_lock(&fep->ptp_clk_mutex); if (!fep->ptp_clk_on) { @@ -563,18 +577,41 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, return -EOPNOTSUPP; } spin_lock_irqsave(&fep->tmreg_lock, flags); + + if (fep->pps_enable) { + dev_err(&fep->pdev->dev, "PPS is running"); + ret = -EBUSY; + goto unlock; + } + + if (fep->perout_enable) { + dev_err(&fep->pdev->dev, + "PEROUT has been enabled\n"); + ret = -EBUSY; + goto unlock; + } + /* Read current timestamp */ curr_time = timecounter_read(&fep->tc); - spin_unlock_irqrestore(&fep->tmreg_lock, flags); - mutex_unlock(&fep->ptp_clk_mutex); + if (perout_stime <= curr_time) { + dev_err(&fep->pdev->dev, + "Start time must be greater than current time\n"); + ret = -EINVAL; + goto unlock; + } /* Calculate time difference */ - delta = fep->perout_stime - curr_time; + delta = perout_stime - curr_time; + fep->reload_period = reload_period; + fep->perout_stime = perout_stime; + fep->perout_enable = true; - if (fep->perout_stime <= curr_time) { - dev_err(&fep->pdev->dev, "Start time must larger than current time!\n"); - return -EINVAL; - } +unlock: + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + mutex_unlock(&fep->ptp_clk_mutex); + + if (ret) + return ret; /* Because the timer counter of FEC only has 31-bits, correspondingly, * the time comparison register FEC_TCCR also only low 31 bits can be @@ -682,8 +719,11 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id) fep->next_counter = (fep->next_counter + fep->reload_period) & fep->cc.mask; - event.type = PTP_CLOCK_PPS; - ptp_clock_event(fep->ptp_clock, &event); + if (fep->pps_enable) { + event.type = PTP_CLOCK_PPS; + ptp_clock_event(fep->ptp_clock, &event); + } + return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index 2ca32fb1961e..84e700777941 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -627,7 +627,7 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, MLX5E_100MB); max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; max_bw_unit[i] = MLX5_100_MBPS_UNIT; - } else if (max_bw_value[i] <= upper_limit_gbps) { + } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], MLX5E_1GB); max_bw_unit[i] = MLX5_GBPS_UNIT; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c index d6cf97ecf327..6f606bdfd229 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c @@ -198,7 +198,7 @@ static int fbnic_mbx_alloc_rx_msgs(struct fbnic_dev *fbd) return -ENODEV; /* Fill all but 1 unused descriptors in the Rx queue. */ - count = (head - tail - 1) % FBNIC_IPC_MBX_DESC_LEN; + count = (head - tail - 1) & (FBNIC_IPC_MBX_DESC_LEN - 1); while (!err && count--) { struct fbnic_tlv_msg *msg; diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c index 87e5e81d40dc..84f5b4410e48 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c @@ -1,11 +1,14 @@ // SPDX-License-Identifier: GPL-2.0+ #include <linux/ptp_classify.h> +#include <linux/units.h> #include "lan966x_main.h" #include "vcap_api.h" #include "vcap_api_client.h" +#define LAN9X66_CLOCK_RATE 165617754 + #define LAN966X_MAX_PTP_ID 512 /* Represents 1ppm adjustment in 2^59 format with 6.037735849ns as reference @@ -1132,5 +1135,5 @@ void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, u32 lan966x_ptp_get_period_ps(void) { /* This represents the system clock period in picoseconds */ - return 15125; + return PICO / LAN9X66_CLOCK_RATE; } diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c index 12c8396b6942..d2ba283f6123 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c @@ -1520,8 +1520,10 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) skb = priv->rxq[qnum]->rx_skbuff[entry]; - if (unlikely(!skb)) + if (unlikely(!skb)) { netdev_err(priv->dev, "rx descriptor is not consistent\n"); + break; + } prefetch(skb->data - NET_IP_ALIGN); priv->rxq[qnum]->rx_skbuff[entry] = NULL; diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c index e5f8ac4b4604..17b0654644de 100644 --- a/drivers/net/phy/mxl-gpy.c +++ b/drivers/net/phy/mxl-gpy.c @@ -523,7 +523,7 @@ static int gpy_update_interface(struct phy_device *phydev) /* Interface mode is fixed for USXGMII and integrated PHY */ if (phydev->interface == PHY_INTERFACE_MODE_USXGMII || phydev->interface == PHY_INTERFACE_MODE_INTERNAL) - return -EINVAL; + return 0; /* Automatically switch SERDES interface between SGMII and 2500-BaseX * according to speed. Disable ANEG in 2500-BaseX mode. diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index 6cfafaac1b4f..94c40c5cebdd 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -1190,10 +1190,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev, return -EPERM; } - err = team_dev_type_check_change(dev, port_dev); - if (err) - return err; - if (port_dev->flags & IFF_UP) { NL_SET_ERR_MSG(extack, "Device is up. Set it down before adding it as a team port"); netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", @@ -1211,10 +1207,16 @@ static int team_port_add(struct team *team, struct net_device *port_dev, INIT_LIST_HEAD(&port->qom_list); port->orig.mtu = port_dev->mtu; - err = dev_set_mtu(port_dev, dev->mtu); - if (err) { - netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); - goto err_set_mtu; + /* + * MTU assignment will be handled in team_dev_type_check_change + * if dev and port_dev are of different types + */ + if (dev->type == port_dev->type) { + err = dev_set_mtu(port_dev, dev->mtu); + if (err) { + netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); + goto err_set_mtu; + } } memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len); @@ -1289,6 +1291,10 @@ static int team_port_add(struct team *team, struct net_device *port_dev, } } + err = team_dev_type_check_change(dev, port_dev); + if (err) + goto err_set_dev_type; + if (dev->flags & IFF_UP) { netif_addr_lock_bh(dev); dev_uc_sync_multiple(port_dev, dev); @@ -1307,6 +1313,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev, return 0; +err_set_dev_type: err_set_slave_promisc: __team_option_inst_del_port(team, port); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 18148e068aa0..4ff0d4232914 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -306,12 +306,10 @@ static void __veth_xdp_flush(struct veth_rq *rq) static int veth_xdp_rx(struct veth_rq *rq, struct sk_buff *skb) { - if (unlikely(ptr_ring_produce(&rq->xdp_ring, skb))) { - dev_kfree_skb_any(skb); - return NET_RX_DROP; - } + if (unlikely(ptr_ring_produce(&rq->xdp_ring, skb))) + return NETDEV_TX_BUSY; /* signal qdisc layer */ - return NET_RX_SUCCESS; + return NET_RX_SUCCESS; /* same as NETDEV_TX_OK */ } static int veth_forward_skb(struct net_device *dev, struct sk_buff *skb, @@ -345,11 +343,11 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) { struct veth_priv *rcv_priv, *priv = netdev_priv(dev); struct veth_rq *rq = NULL; - int ret = NETDEV_TX_OK; + struct netdev_queue *txq; struct net_device *rcv; int length = skb->len; bool use_napi = false; - int rxq; + int ret, rxq; rcu_read_lock(); rcv = rcu_dereference(priv->peer); @@ -372,17 +370,43 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) } skb_tx_timestamp(skb); - if (likely(veth_forward_skb(rcv, skb, rq, use_napi) == NET_RX_SUCCESS)) { + + ret = veth_forward_skb(rcv, skb, rq, use_napi); + switch (ret) { + case NET_RX_SUCCESS: /* same as NETDEV_TX_OK */ if (!use_napi) dev_sw_netstats_tx_add(dev, 1, length); else __veth_xdp_flush(rq); - } else { + break; + case NETDEV_TX_BUSY: + /* If a qdisc is attached to our virtual device, returning + * NETDEV_TX_BUSY is allowed. + */ + txq = netdev_get_tx_queue(dev, rxq); + + if (qdisc_txq_has_no_queue(txq)) { + dev_kfree_skb_any(skb); + goto drop; + } + /* Restore Eth hdr pulled by dev_forward_skb/eth_type_trans */ + __skb_push(skb, ETH_HLEN); + netif_tx_stop_queue(txq); + /* Makes sure NAPI peer consumer runs. Consumer is responsible + * for starting txq again, until then ndo_start_xmit (this + * function) will not be invoked by the netstack again. + */ + __veth_xdp_flush(rq); + break; + case NET_RX_DROP: /* same as NET_XMIT_DROP */ drop: atomic64_inc(&priv->dropped); ret = NET_XMIT_DROP; + break; + default: + net_crit_ratelimited("%s(%s): Invalid return code(%d)", + __func__, dev->name, ret); } - rcu_read_unlock(); return ret; @@ -932,17 +956,28 @@ static int veth_poll(struct napi_struct *napi, int budget) { struct veth_rq *rq = container_of(napi, struct veth_rq, xdp_napi); + struct veth_priv *priv = netdev_priv(rq->dev); + int queue_idx = rq->xdp_rxq.queue_index; + struct netdev_queue *peer_txq; struct veth_stats stats = {}; + struct net_device *peer_dev; struct veth_xdp_tx_bq bq; int done; bq.count = 0; + /* NAPI functions as RCU section */ + peer_dev = rcu_dereference_check(priv->peer, rcu_read_lock_bh_held()); + peer_txq = peer_dev ? netdev_get_tx_queue(peer_dev, queue_idx) : NULL; + xdp_set_return_frame_no_direct(); done = veth_xdp_rcv(rq, budget, &bq, &stats); if (stats.xdp_redirect > 0) xdp_do_flush(); + if (stats.xdp_tx > 0) + veth_xdp_flush(rq, &bq); + xdp_clear_return_frame_no_direct(); if (done < budget && napi_complete_done(napi, done)) { /* Write rx_notify_masked before reading ptr_ring */ @@ -955,9 +990,12 @@ static int veth_poll(struct napi_struct *napi, int budget) } } - if (stats.xdp_tx > 0) - veth_xdp_flush(rq, &bq); - xdp_clear_return_frame_no_direct(); + /* Release backpressure per NAPI poll */ + smp_rmb(); /* Paired with netif_tx_stop_queue set_bit */ + if (peer_txq && netif_tx_queue_stopped(peer_txq)) { + txq_trans_cond_update(peer_txq); + netif_tx_wake_queue(peer_txq); + } return done; } diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 89dde220058a..b62462d8eff2 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -352,15 +352,13 @@ unlock: static bool qdisc_tx_is_default(const struct net_device *dev) { struct netdev_queue *txq; - struct Qdisc *qdisc; if (dev->num_tx_queues > 1) return false; txq = netdev_get_tx_queue(dev, 0); - qdisc = rcu_access_pointer(txq->qdisc); - return !qdisc->enqueue; + return qdisc_txq_has_no_queue(txq); } /* Local traffic destined to local address. Reinsert the packet to rx diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index eebdcc16e8fc..1c0d796ffc7a 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -2214,6 +2214,11 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar, spin_lock_bh(&ar->ab->base_lock); peer = ath12k_dp_rx_h_find_peer(ar->ab, msdu); if (peer) { + /* resetting mcbc bit because mcbc packets are unicast + * packets only for AP as STA sends unicast packets. + */ + rxcb->is_mcbc = rxcb->is_mcbc && !peer->ucast_ra_only; + if (rxcb->is_mcbc) enctype = peer->sec_type_grp; else diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c index 19c0626fbff1..461749b0f732 100644 --- a/drivers/net/wireless/ath/ath12k/peer.c +++ b/drivers/net/wireless/ath/ath12k/peer.c @@ -331,6 +331,9 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif, arvif->ast_idx = peer->hw_peer_id; } + if (arvif->vif->type == NL80211_IFTYPE_AP) + peer->ucast_ra_only = true; + peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h index 7b3500b5c8c2..05d4fdd3f82d 100644 --- a/drivers/net/wireless/ath/ath12k/peer.h +++ b/drivers/net/wireless/ath/ath12k/peer.h @@ -47,6 +47,8 @@ struct ath12k_peer { /* protected by ab->data_lock */ bool dp_setup_done; + + bool ucast_ra_only; }; void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c index d07f0f75d23f..260f72055013 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c @@ -8111,6 +8111,9 @@ static const struct usb_device_id dev_table[] = { /* TP-Link TL-WN823N V2 */ {USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0135, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192fu_fops}, +/* D-Link AN3U rev. A1 */ +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3328, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, #ifdef CONFIG_RTL8XXXU_UNTESTED /* Still supported by rtlwifi */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822cu.c b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c index 157d5102a4b1..ae633af717bd 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822cu.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c @@ -21,6 +21,8 @@ static const struct usb_device_id rtw_8822cu_id_table[] = { .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, /* Alpha - Alpha */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3329, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, /* D-Link AC13U rev. A1 */ {}, }; MODULE_DEVICE_TABLE(usb, rtw_8822cu_id_table); diff --git a/drivers/net/wwan/mhi_wwan_mbim.c b/drivers/net/wwan/mhi_wwan_mbim.c index c814fbd756a1..f8bc9a39bfa3 100644 --- a/drivers/net/wwan/mhi_wwan_mbim.c +++ b/drivers/net/wwan/mhi_wwan_mbim.c @@ -98,7 +98,7 @@ static struct mhi_mbim_link *mhi_mbim_get_link_rcu(struct mhi_mbim_context *mbim static int mhi_mbim_get_link_mux_id(struct mhi_controller *cntrl) { if (strcmp(cntrl->name, "foxconn-dw5934e") == 0 || - strcmp(cntrl->name, "foxconn-t99w515") == 0) + strcmp(cntrl->name, "foxconn-t99w640") == 0) return WDS_BIND_MUX_DATA_PORT_MUX_ID; return 0; |
