diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-25 12:25:36 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-25 12:25:36 -0700 |
| commit | 805185b7c7a1069e407b6f7b3bc98e44d415f484 (patch) | |
| tree | 8e252490fc55ac4a2ef591efa06d078211fc639f /drivers | |
| parent | c75597caada080effbfbc0a7fb10dc2a3bb543ad (diff) | |
| parent | fe9f4ee6c61a1410afd73bf011de5ae618004796 (diff) | |
Merge tag 'net-7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Including fixes from netfilter and IPsec.
Current release - regressions:
- do not acquire dev->tx_global_lock in netdev_watchdog_up()
- ethtool: keep rtnl_lock for ops using ethtool_op_get_link()
- fix deadlock in nested UP notifier events
Current release - new code bugs:
- eth:
- cn20k: fix subbank free list indexing for search order
- airoha: fix BQL underflow in shared QDMA TX ring
Previous releases - regressions:
- netfilter:
- flowtable: fix offloaded ct timeout never being extended
- nf_conncount: prevent connlimit drops for early confirmed ct
Previous releases - always broken:
- require CAP_NET_ADMIN in the originating netns when modifying
cross-netns devices
- report NAPI thread PID in the caller's pid namespace
- mac802154: fix dirty frag in in-place crypto for IOT radios
- sctp: hold socket lock when dumping endpoints in sctp_diag, avoid
an overflow
- eth: gve: fix header buffer corruption with header-split and HW-GRO
- af_key: initialize alg_key_len for IPComp states, prevent OOB read"
* tag 'net-7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (213 commits)
selftests: bonding: add a test for VLAN propagation over a bonded real device
vlan: defer real device state propagation to netdev_work
net: add the driver-facing netdev_work scheduling API
net: turn the rx_mode work into a generic netdev_work facility
net: ethtool: keep rtnl_lock for ops using ethtool_op_get_link()
rxrpc: Fix rxrpc_rotate_tx_rotate() to check there's something to rotate
rxrpc: Fix leak of released call in recvmsg(MSG_PEEK)
rxrpc: Fix socket notification race
rxrpc: Fix potential infinite loop in rxrpc_recvmsg()
rxrpc: Fix oob challenge leak in cleanup after notification failure
rxrpc: Fix the reception of a reply packet before data transmission
afs: Fix uncancelled rxrpc OOB message handler
afs: Fix further netns teardown to cancel the preallocation charger
rxrpc: Fix double unlock in rxrpc_recvmsg()
rxrpc: Fix leak of connection from OOB challenge
rxrpc: Fix ACKALL packet handling
net: hns3: differentiate autoneg default values between copper and fiber
net: hns3: fix permanent link down deadlock after reset
net: hns3: refactor MAC autoneg and speed configuration
net: hns3: unify copper port ksettings configuration path
...
Diffstat (limited to 'drivers')
82 files changed, 848 insertions, 391 deletions
diff --git a/drivers/net/dsa/mxl862xx/mxl862xx-host.c b/drivers/net/dsa/mxl862xx/mxl862xx-host.c index d55f9dff6433..4acd216f7cc0 100644 --- a/drivers/net/dsa/mxl862xx/mxl862xx-host.c +++ b/drivers/net/dsa/mxl862xx/mxl862xx-host.c @@ -12,6 +12,7 @@ #include <linux/crc16.h> #include <linux/iopoll.h> #include <linux/limits.h> +#include <linux/unaligned.h> #include <net/dsa.h> #include "mxl862xx.h" #include "mxl862xx-host.h" @@ -40,12 +41,13 @@ static void mxl862xx_crc_err_work_fn(struct work_struct *work) crc_err_work); struct dsa_port *dp; - dev_warn(&priv->mdiodev->dev, - "MDIO CRC error detected, shutting down all ports\n"); - rtnl_lock(); - dsa_switch_for_each_cpu_port(dp, priv->ds) - dev_close(dp->conduit); + if (!test_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags)) { + dev_warn(&priv->mdiodev->dev, + "MDIO CRC error detected, shutting down all ports\n"); + dsa_switch_for_each_cpu_port(dp, priv->ds) + dev_close(dp->conduit); + } rtnl_unlock(); clear_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags); @@ -349,7 +351,7 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *_data, * zero words individually. */ for (i = 0, zeros = 0; i < size / 2 && zeros < RST_DATA_THRESHOLD; i++) - if (!data[i]) + if (!get_unaligned_le16(&data[i])) zeros++; if (zeros < RST_DATA_THRESHOLD && (size & 1) && !*(u8 *)&data[i]) @@ -395,7 +397,7 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *_data, */ val = *(u8 *)&data[i] | ((crc & 0xff) << 8); } else { - val = le16_to_cpu(data[i]); + val = get_unaligned_le16(&data[i]); } /* After RST_DATA, skip zero data words as the registers @@ -453,7 +455,7 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *_data, *(uint8_t *)&data[i] = ret & 0xff; crc = (ret >> 8) & 0xff; } else { - data[i] = cpu_to_le16((u16)ret); + put_unaligned_le16((u16)ret, &data[i]); } } diff --git a/drivers/net/dsa/realtek/rtl8366rb-leds.c b/drivers/net/dsa/realtek/rtl8366rb-leds.c index 509ffd3f8db5..ba50d311cb15 100644 --- a/drivers/net/dsa/realtek/rtl8366rb-leds.c +++ b/drivers/net/dsa/realtek/rtl8366rb-leds.c @@ -89,6 +89,7 @@ static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp, struct led_init_data init_data = { }; enum led_default_state state; struct rtl8366rb_led *led; + char name[64]; u32 led_group; int ret; @@ -129,10 +130,9 @@ static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp, init_data.fwnode = led_fwnode; init_data.devname_mandatory = true; - init_data.devicename = kasprintf(GFP_KERNEL, "Realtek-%d:0%d:%d", - dp->ds->index, dp->index, led_group); - if (!init_data.devicename) - return -ENOMEM; + snprintf(name, sizeof(name), "Realtek-%d:0%d:%d", + dp->ds->index, dp->index, led_group); + init_data.devicename = name; ret = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data); if (ret) { diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c index fefe46e2a5e6..350f958dcb2a 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.c +++ b/drivers/net/dsa/sja1105/sja1105_ptp.c @@ -755,7 +755,7 @@ static int sja1105_per_out_enable(struct sja1105_private *priv, * 2 edges on PTP_CLK. So check for truncation which happens * at periods larger than around 68.7 seconds. */ - pin_duration = ns_to_sja1105_ticks(pin_duration / 2); + pin_duration = max_t(u64, ns_to_sja1105_ticks(pin_duration / 2), 1); if (pin_duration > U32_MAX) { rc = -ERANGE; goto out; diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c index 64dde6464f3f..932b3a3df2e5 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c @@ -1004,6 +1004,7 @@ static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget) e = &q->entry[index]; skb = e->skb; + e->skb = NULL; dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, DMA_TO_DEVICE); @@ -1147,55 +1148,76 @@ static int airoha_qdma_init_tx(struct airoha_qdma *qdma) return 0; } -static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q) +static void airoha_qdma_tx_cleanup(struct airoha_qdma *qdma) { - struct airoha_qdma *qdma = q->qdma; - struct airoha_eth *eth = qdma->eth; - int i, qid = q - &qdma->q_tx[0]; - u16 index = 0; + u32 status; + int i; - spin_lock_bh(&q->lock); - for (i = 0; i < q->ndesc; i++) { - struct airoha_queue_entry *e = &q->entry[i]; - struct airoha_qdma_desc *desc = &q->desc[i]; + airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, + GLOBAL_CFG_TX_DMA_EN_MASK); + if (read_poll_timeout(airoha_qdma_rr, status, + !(status & GLOBAL_CFG_TX_DMA_BUSY_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, true, + qdma, REG_QDMA_GLOBAL_CFG)) + dev_warn(qdma->eth->dev, "QDMA TX DMA busy timeout\n"); - if (!e->dma_addr) + for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { + struct airoha_queue *q = &qdma->q_tx[i]; + u16 index = 0; + int j; + + if (!q->ndesc) continue; - dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, - DMA_TO_DEVICE); - dev_kfree_skb_any(e->skb); - e->dma_addr = 0; - e->skb = NULL; - list_add_tail(&e->list, &q->tx_list); + spin_lock_bh(&q->lock); - /* Reset DMA descriptor */ - WRITE_ONCE(desc->ctrl, 0); - WRITE_ONCE(desc->addr, 0); - WRITE_ONCE(desc->data, 0); - WRITE_ONCE(desc->msg0, 0); - WRITE_ONCE(desc->msg1, 0); - WRITE_ONCE(desc->msg2, 0); + q->flushing = true; + for (j = 0; j < q->ndesc; j++) { + struct airoha_queue_entry *e = &q->entry[j]; + struct airoha_qdma_desc *desc = &q->desc[j]; + struct sk_buff *skb = e->skb; - q->queued--; - } + if (!e->dma_addr) + continue; - if (!list_empty(&q->tx_list)) { - struct airoha_queue_entry *e; + dma_unmap_single(qdma->eth->dev, e->dma_addr, + e->dma_len, DMA_TO_DEVICE); + e->dma_addr = 0; + list_add_tail(&e->list, &q->tx_list); + + WRITE_ONCE(desc->ctrl, 0); + WRITE_ONCE(desc->addr, 0); + WRITE_ONCE(desc->data, 0); + WRITE_ONCE(desc->msg0, 0); + WRITE_ONCE(desc->msg1, 0); + WRITE_ONCE(desc->msg2, 0); + + if (skb) { + struct netdev_queue *txq; + + txq = skb_get_tx_queue(skb->dev, skb); + netdev_tx_completed_queue(txq, 1, skb->len); + dev_kfree_skb_any(skb); + e->skb = NULL; + } - e = list_first_entry(&q->tx_list, struct airoha_queue_entry, - list); - index = e - q->entry; - } - /* Set TX_DMA_IDX to TX_CPU_IDX to notify the hw the QDMA TX ring is - * empty. - */ - airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK, - FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); - airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK, - FIELD_PREP(TX_RING_DMA_IDX_MASK, index)); + q->queued--; + } - spin_unlock_bh(&q->lock); + if (!list_empty(&q->tx_list)) { + struct airoha_queue_entry *e; + + e = list_first_entry(&q->tx_list, + struct airoha_queue_entry, list); + index = e - q->entry; + } + airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(i), TX_RING_CPU_IDX_MASK, + FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); + airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(i), TX_RING_DMA_IDX_MASK, + FIELD_PREP(TX_RING_DMA_IDX_MASK, index)); + + spin_unlock_bh(&q->lock); + } } static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma) @@ -1523,10 +1545,23 @@ static int airoha_qdma_init(struct platform_device *pdev, return airoha_qdma_hw_init(qdma); } -static void airoha_qdma_cleanup(struct airoha_qdma *qdma) +static void airoha_qdma_cleanup(struct airoha_eth *eth, + struct airoha_qdma *qdma) { int i; + if (test_bit(DEV_STATE_INITIALIZED, ð->state)) { + u32 status; + + airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, + GLOBAL_CFG_RX_DMA_EN_MASK); + if (read_poll_timeout(airoha_qdma_rr, status, + !(status & GLOBAL_CFG_RX_DMA_BUSY_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, true, + qdma, REG_QDMA_GLOBAL_CFG)) + dev_warn(eth->dev, "QDMA RX DMA busy timeout\n"); + } + for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { if (!qdma->q_rx[i].ndesc) continue; @@ -1546,12 +1581,6 @@ static void airoha_qdma_cleanup(struct airoha_qdma *qdma) netif_napi_del(&qdma->q_tx_irq[i].napi); } - for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { - if (!qdma->q_tx[i].ndesc) - continue; - - airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); - } } static int airoha_hw_init(struct platform_device *pdev, @@ -1593,7 +1622,7 @@ static int airoha_hw_init(struct platform_device *pdev, return 0; error: for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) - airoha_qdma_cleanup(ð->qdma[i]); + airoha_qdma_cleanup(eth, ð->qdma[i]); return err; } @@ -1603,7 +1632,7 @@ static void airoha_hw_cleanup(struct airoha_eth *eth) int i; for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) - airoha_qdma_cleanup(ð->qdma[i]); + airoha_qdma_cleanup(eth, ð->qdma[i]); airoha_ppe_deinit(eth); } @@ -1837,11 +1866,6 @@ static int airoha_dev_open(struct net_device *netdev) } port->users++; - airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, - GLOBAL_CFG_TX_DMA_EN_MASK | - GLOBAL_CFG_RX_DMA_EN_MASK); - qdma->users++; - if (!airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(qdma->eth, 1)) pse_port = FE_PSE_PORT_PPE2; @@ -1880,12 +1904,9 @@ static int airoha_dev_stop(struct net_device *netdev) struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; struct airoha_qdma *qdma = dev->qdma; - int i; netif_tx_disable(netdev); airoha_set_vip_for_gdm_port(dev, false); - for (i = 0; i < netdev->num_tx_queues; i++) - netdev_tx_reset_subqueue(netdev, i); if (--port->users) airoha_set_port_mtu(dev->eth, port); @@ -1893,20 +1914,6 @@ static int airoha_dev_stop(struct net_device *netdev) airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), FE_PSE_PORT_DROP); - - if (!--qdma->users) { - airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, - GLOBAL_CFG_TX_DMA_EN_MASK | - GLOBAL_CFG_RX_DMA_EN_MASK); - - for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { - if (!qdma->q_tx[i].ndesc) - continue; - - airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); - } - } - return 0; } @@ -2110,7 +2117,7 @@ static u16 airoha_dev_select_queue(struct net_device *netdev, */ channel = netdev_uses_dsa(netdev) ? skb_get_queue_mapping(skb) : port->id; channel = channel % AIROHA_NUM_QOS_CHANNELS; - queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */ + queue = skb->priority % AIROHA_NUM_QOS_QUEUES; queue = channel * AIROHA_NUM_QOS_QUEUES + queue; return queue < netdev->num_tx_queues ? queue : 0; @@ -2229,6 +2236,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, spin_lock_bh(&q->lock); + if (q->flushing) + goto error_unlock; + txq = skb_get_tx_queue(netdev, skb); nr_frags = 1 + skb_shinfo(skb)->nr_frags; @@ -2309,7 +2319,7 @@ error_unmap: e->dma_addr = 0; } list_splice(&tx_list, &q->tx_list); - +error_unlock: spin_unlock_bh(&q->lock); error: dev_kfree_skb_any(skb); @@ -2395,7 +2405,7 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, struct airoha_gdm_dev *dev = netdev_priv(netdev); int i; - for (i = 0; i < AIROHA_NUM_TX_RING; i++) + for (i = 0; i < AIROHA_NUM_QOS_QUEUES; i++) airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel), TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i)); @@ -2789,7 +2799,7 @@ static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev, struct tc_htb_qopt_offload *opt) { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; - int err, num_tx_queues = netdev->real_num_tx_queues; + int err, num_tx_queues = AIROHA_NUM_TX_RING + channel + 1; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_qdma *qdma = dev->qdma; @@ -2806,13 +2816,15 @@ static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev, if (err) goto error; - err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1); - if (err) { - airoha_qdma_set_tx_rate_limit(netdev, channel, 0, - opt->quantum); - NL_SET_ERR_MSG_MOD(opt->extack, - "failed setting real_num_tx_queues"); - goto error; + if (num_tx_queues > netdev->real_num_tx_queues) { + err = netif_set_real_num_tx_queues(netdev, num_tx_queues); + if (err) { + airoha_qdma_set_tx_rate_limit(netdev, channel, 0, + opt->quantum); + NL_SET_ERR_MSG_MOD(opt->extack, + "failed setting real_num_tx_queues"); + goto error; + } } set_bit(channel, dev->qos_sq_bmap); @@ -3003,13 +3015,18 @@ static int airoha_dev_setup_tc_block(struct net_device *dev, static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) { struct airoha_gdm_dev *dev = netdev_priv(netdev); + int num_tx_queues = AIROHA_NUM_TX_RING; struct airoha_qdma *qdma = dev->qdma; - netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1); - airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0); + airoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0); clear_bit(queue, qdma->qos_channel_map); clear_bit(queue, dev->qos_sq_bmap); + + if (!bitmap_empty(dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)) + num_tx_queues += find_last_bit(dev->qos_sq_bmap, + AIROHA_NUM_QOS_CHANNELS) + 1; + netif_set_real_num_tx_queues(netdev, num_tx_queues); } static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev, @@ -3413,8 +3430,12 @@ static int airoha_probe(struct platform_device *pdev) if (err) goto error_netdev_free; - for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) + for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { airoha_qdma_start_napi(ð->qdma[i]); + airoha_qdma_set(ð->qdma[i], REG_QDMA_GLOBAL_CFG, + GLOBAL_CFG_TX_DMA_EN_MASK | + GLOBAL_CFG_RX_DMA_EN_MASK); + } for_each_child_of_node(pdev->dev.of_node, np) { if (!of_device_is_compatible(np, "airoha,eth-mac")) @@ -3437,8 +3458,10 @@ static int airoha_probe(struct platform_device *pdev) return 0; error_napi_stop: - for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) + for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { airoha_qdma_stop_napi(ð->qdma[i]); + airoha_qdma_tx_cleanup(ð->qdma[i]); + } for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -3474,8 +3497,10 @@ static void airoha_remove(struct platform_device *pdev) struct airoha_eth *eth = platform_get_drvdata(pdev); int i; - for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) + for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { airoha_qdma_stop_napi(ð->qdma[i]); + airoha_qdma_tx_cleanup(ð->qdma[i]); + } for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h index 41d2e7a1f9fb..d7ff8c5200e2 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h @@ -197,6 +197,7 @@ struct airoha_queue { int free_thr; int buf_size; bool txq_stopped; + bool flushing; struct napi_struct napi; struct page_pool *page_pool; @@ -524,8 +525,6 @@ struct airoha_qdma { struct airoha_eth *eth; void __iomem *regs; - int users; - struct airoha_irq_bank irq_banks[AIROHA_MAX_NUM_IRQ_BANKS]; struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ]; diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c index 329e7c2aae89..42f4b0f21d17 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c @@ -1601,7 +1601,8 @@ int airoha_ppe_init(struct airoha_eth *eth) return -ENOMEM; } - ppe->foe_check_time = devm_kzalloc(eth->dev, ppe_num_entries, + ppe->foe_check_time = devm_kzalloc(eth->dev, + ppe_num_entries * sizeof(*ppe->foe_check_time), GFP_KERNEL); if (!ppe->foe_check_time) return -ENOMEM; diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 92d149d4f091..5d05020a6d05 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -752,6 +752,18 @@ static void ena_destroy_all_tx_queues(struct ena_adapter *adapter) } } +static void ena_destroy_xdp_tx_queues(struct ena_adapter *adapter) +{ + u16 ena_qid; + int i; + + for (i = adapter->xdp_first_ring; + i < adapter->xdp_first_ring + adapter->xdp_num_queues; i++) { + ena_qid = ENA_IO_TXQ_IDX(i); + ena_com_destroy_io_queue(adapter->ena_dev, ena_qid); + } +} + static void ena_destroy_all_rx_queues(struct ena_adapter *adapter) { u16 ena_qid; @@ -2078,14 +2090,21 @@ static int create_queues_with_size_backoff(struct ena_adapter *adapter) rc = ena_setup_tx_resources_in_range(adapter, 0, adapter->num_io_queues); - if (rc) + if (rc) { + ena_destroy_xdp_tx_queues(adapter); + ena_free_all_io_tx_resources_in_range(adapter, + adapter->xdp_first_ring, + adapter->xdp_num_queues); goto err_setup_tx; + } rc = ena_create_io_tx_queues_in_range(adapter, 0, adapter->num_io_queues); - if (rc) + if (rc) { + ena_destroy_xdp_tx_queues(adapter); goto err_create_tx_queues; + } rc = ena_setup_all_rx_resources(adapter); if (rc) diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index 9d35ac348ebe..5a04056e38fa 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -943,9 +943,10 @@ static int au1000_close(struct net_device *dev) /* stop the device */ netif_stop_queue(dev); + spin_unlock_irqrestore(&aup->lock, flags); + /* disable the interrupt */ free_irq(dev->irq, dev); - spin_unlock_irqrestore(&aup->lock, flags); return 0; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 19e078479b0d..5b2640bd31c3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -4748,6 +4748,7 @@ int bnx2x_alloc_mem_bp(struct bnx2x *bp) fp = kzalloc_objs(*fp, bp->fp_array_size); if (!fp) goto alloc_err; + bp->fp = fp; for (i = 0; i < bp->fp_array_size; i++) { fp[i].tpa_info = kzalloc_objs(struct bnx2x_agg_info, @@ -4756,8 +4757,6 @@ int bnx2x_alloc_mem_bp(struct bnx2x *bp) goto alloc_err; } - bp->fp = fp; - /* allocate sp objs */ bp->sp_objs = kzalloc_objs(struct bnx2x_sp_objs, bp->fp_array_size); if (!bp->sp_objs) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 055e93a417b6..7513618793da 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -10530,7 +10530,7 @@ static void bnxt_accumulate_stats(struct bnxt_stats_mem *stats) stats->hw_masks, stats->len / 8, false); } -static void bnxt_accumulate_all_stats(struct bnxt *bp) +static void bnxt_accumulate_ring_stats(struct bnxt *bp) { struct bnxt_stats_mem *ring0_stats; bool ignore_zero = false; @@ -10553,6 +10553,10 @@ static void bnxt_accumulate_all_stats(struct bnxt *bp) ring0_stats->hw_masks, ring0_stats->len / 8, ignore_zero); } +} + +static void bnxt_accumulate_port_stats(struct bnxt *bp) +{ if (bp->flags & BNXT_FLAG_PORT_STATS) { struct bnxt_stats_mem *stats = &bp->port_stats; __le64 *hw_stats = stats->hw_stats; @@ -10575,6 +10579,41 @@ static void bnxt_accumulate_all_stats(struct bnxt *bp) } } +static void bnxt_accumulate_all_stats(struct bnxt *bp) +{ + bnxt_accumulate_ring_stats(bp); + bnxt_accumulate_port_stats(bp); +} + +/* Re-accumulate ring stats from DMA buffers if stale. + * uAPIs for reading sw_stats should call this first. + * + * We promise user space update frequency of bp->stats_coal_ticks but + * the update is a two step process - first device updates the DMA buffer, + * then we have to update from that buffer to driver stats in the service work. + * Worst case we would be 2x off from the desired frequency. + * Sync the stats sooner, if stale. The 20% threshold was chosen arbitrarily. + * + * Ideally we would split the user-configured time into two portions, + * i.e. also lower the DMA period by the 20%. But the DMA timer seems to have + * too coarse granularity to play such tricks. + */ +void bnxt_sync_ring_stats(struct bnxt *bp) +{ + unsigned long stale; + + if (!netif_running(bp->dev) || !bp->stats_coal_ticks) + return; + + spin_lock(&bp->stats_lock); + stale = usecs_to_jiffies(bp->stats_coal_ticks / 5); + if (time_after_eq(jiffies, bp->stats_updated_jiffies + stale)) { + bnxt_accumulate_ring_stats(bp); + bp->stats_updated_jiffies = jiffies; + } + spin_unlock(&bp->stats_lock); +} + static int bnxt_hwrm_port_qstats(struct bnxt *bp, u8 flags) { struct hwrm_port_qstats_input *req; @@ -13577,6 +13616,7 @@ bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) return; } + bnxt_sync_ring_stats(bp); bnxt_get_ring_stats(bp, stats); bnxt_add_prev_stats(bp, stats); @@ -14753,7 +14793,10 @@ static void bnxt_sp_task(struct work_struct *work) if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event)) { bnxt_hwrm_port_qstats(bp, 0); bnxt_hwrm_port_qstats_ext(bp, 0); + spin_lock(&bp->stats_lock); bnxt_accumulate_all_stats(bp); + bp->stats_updated_jiffies = jiffies; + spin_unlock(&bp->stats_lock); } if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) { @@ -15488,6 +15531,7 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) INIT_DELAYED_WORK(&bp->fw_reset_task, bnxt_fw_reset_task); spin_lock_init(&bp->ntp_fltr_lock); + spin_lock_init(&bp->stats_lock); #if BITS_PER_LONG == 32 spin_lock_init(&bp->db_lock); #endif @@ -16056,6 +16100,7 @@ static void bnxt_get_queue_stats_rx(struct net_device *dev, int i, if (!bp->bnapi) return; + bnxt_sync_ring_stats(bp); cpr = &bp->bnapi[i]->cp_ring; sw = cpr->stats.sw_stats; @@ -16084,6 +16129,7 @@ static void bnxt_get_queue_stats_tx(struct net_device *dev, int i, if (!bp->tx_ring) return; + bnxt_sync_ring_stats(bp); bnapi = bp->tx_ring[bp->tx_ring_map[i]].bnapi; sw = bnapi->cp_ring.stats.sw_stats; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 6d312259f852..6335dfc14c98 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -2620,6 +2620,10 @@ struct bnxt { #define BNXT_MIN_STATS_COAL_TICKS 250000 #define BNXT_MAX_STATS_COAL_TICKS 1000000 + /* Protects stats_updated_jiffies and writes to sw_stats */ + spinlock_t stats_lock; + unsigned long stats_updated_jiffies; + struct work_struct sp_task; unsigned long sp_event; #define BNXT_RX_NTP_FLTR_SP_EVENT 1 @@ -3027,6 +3031,7 @@ void bnxt_reenable_sriov(struct bnxt *bp); void bnxt_close_nic(struct bnxt *, bool, bool); void bnxt_get_ring_drv_stats(struct bnxt *bp, struct bnxt_total_ring_drv_stats *stats); +void bnxt_sync_ring_stats(struct bnxt *bp); bool bnxt_rfs_capable(struct bnxt *bp, bool new_rss_ctx); int bnxt_dbg_hwrm_rd_reg(struct bnxt *bp, u32 reg_off, u16 num_words, u32 *reg_buf); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 56d74a3c24b7..62bc9cae613c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -606,6 +606,7 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, goto skip_ring_stats; } + bnxt_sync_ring_stats(bp); tpa_stats = bnxt_get_num_tpa_ring_stats(bp); for (i = 0; i < bp->cp_nr_rings; i++) { struct bnxt_napi *bnapi = bp->bnapi[i]; diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index a12aa21244e8..fd282a1700fb 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -4522,6 +4522,13 @@ static int macb_setup_tc(struct net_device *dev, enum tc_setup_type type, } } +static void macb_tx_timeout(struct net_device *dev, unsigned int q) +{ + struct macb *bp = netdev_priv(dev); + + macb_tx_restart(&bp->queues[q]); +} + static const struct net_device_ops macb_netdev_ops = { .ndo_open = macb_open, .ndo_stop = macb_close, @@ -4540,6 +4547,7 @@ static const struct net_device_ops macb_netdev_ops = { .ndo_hwtstamp_set = macb_hwtstamp_set, .ndo_hwtstamp_get = macb_hwtstamp_get, .ndo_setup_tc = macb_setup_tc, + .ndo_tx_timeout = macb_tx_timeout, }; /* Configure peripheral capabilities according to device tree diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c index 45f276c2c3ec..858ba844ac51 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c @@ -2212,7 +2212,7 @@ dpaa2_switch_prechangeupper_sanity_checks(struct net_device *netdev, if (err) { NL_SET_ERR_MSG_MOD(extack, "Cannot join a bridge while VLAN uppers are present"); - return 0; + return err; } netdev_for_each_lower_dev(upper_dev, other_dev, iter) { @@ -2233,6 +2233,7 @@ dpaa2_switch_prechangeupper_sanity_checks(struct net_device *netdev, static int dpaa2_switch_port_prechangeupper(struct net_device *netdev, struct netdev_notifier_changeupper_info *info) { + struct ethsw_port_priv *port_priv; struct netlink_ext_ack *extack; struct net_device *upper_dev; int err; @@ -2251,6 +2252,13 @@ static int dpaa2_switch_port_prechangeupper(struct net_device *netdev, if (!info->linking) dpaa2_switch_port_pre_bridge_leave(netdev); + } else if (is_vlan_dev(upper_dev)) { + port_priv = netdev_priv(netdev); + if (port_priv->fdb->bridge_dev) { + NL_SET_ERR_MSG_MOD(extack, + "Cannot accept VLAN uppers while bridged"); + return -EOPNOTSUPP; + } } return 0; diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c index 4e771f852358..437a15bbb47b 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c @@ -322,6 +322,9 @@ static void enetc4_default_rings_allocation(struct enetc_pf *pf) val = enetc4_psicfgr0_val_construct(false, num_tx_bdr, num_rx_bdr); enetc_port_wr(hw, ENETC4_PSICFGR0(0), val); + if (!pf->caps.num_vsi) + return; + num_rx_bdr = pf->caps.num_rx_bdr - num_rx_bdr; rx_rem = num_rx_bdr % pf->caps.num_vsi; num_rx_bdr = num_rx_bdr / pf->caps.num_vsi; diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index 7cc22916852f..8199738ba979 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -984,7 +984,8 @@ const struct ethtool_ops gve_ethtool_ops = { .supported_ring_params = ETHTOOL_RING_USE_TCP_DATA_SPLIT | ETHTOOL_RING_USE_RX_BUF_LEN, .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS | - ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM, + ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM | + ETHTOOL_OP_NEEDS_RTNL_GLINK, .get_drvinfo = gve_get_drvinfo, .get_strings = gve_get_strings, .get_sset_count = gve_get_sset_count, diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c index 7924dce719e2..02cba280d81a 100644 --- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c +++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c @@ -21,11 +21,13 @@ static void gve_rx_free_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx) { struct device *hdev = &priv->pdev->dev; - int buf_count = rx->dqo.bufq.mask + 1; if (rx->dqo.hdr_bufs.data) { - dma_free_coherent(hdev, priv->header_buf_size * buf_count, - rx->dqo.hdr_bufs.data, rx->dqo.hdr_bufs.addr); + size_t size = + (size_t)priv->header_buf_size * rx->dqo.num_buf_states; + + dma_free_coherent(hdev, size, rx->dqo.hdr_bufs.data, + rx->dqo.hdr_bufs.addr); rx->dqo.hdr_bufs.data = NULL; } } @@ -254,7 +256,7 @@ int gve_rx_alloc_ring_dqo(struct gve_priv *priv, /* Allocate header buffers for header-split */ if (cfg->enable_header_split) - if (gve_rx_alloc_hdr_bufs(priv, rx, buffer_queue_slots)) + if (gve_rx_alloc_hdr_bufs(priv, rx, rx->dqo.num_buf_states)) goto err; /* Allocate RX completion queue */ @@ -381,10 +383,13 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx) break; } - if (rx->dqo.hdr_bufs.data) + if (rx->dqo.hdr_bufs.data) { + u16 buf_id = le16_to_cpu(desc->buf_id); + desc->header_buf_addr = cpu_to_le64(rx->dqo.hdr_bufs.addr + - priv->header_buf_size * bufq->tail); + (size_t)priv->header_buf_size * buf_id); + } bufq->tail = (bufq->tail + 1) & bufq->mask; complq->num_free_slots--; @@ -826,10 +831,13 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx, int unsplit = 0; if (hdr_len && !hbo) { - rx->ctx.skb_head = gve_rx_copy_data(priv->dev, napi, - rx->dqo.hdr_bufs.data + - desc_idx * priv->header_buf_size, - hdr_len); + size_t offset = + (size_t)buffer_id * priv->header_buf_size; + + rx->ctx.skb_head = + gve_rx_copy_data(priv->dev, napi, + rx->dqo.hdr_bufs.data + offset, + hdr_len); if (unlikely(!rx->ctx.skb_head)) goto error; rx->ctx.skb_tail = rx->ctx.skb_head; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 9cb7ce9fd311..442f15476af3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -811,12 +811,11 @@ static int hns3_get_link_ksettings(struct net_device *netdev, } static int hns3_check_ksettings_param(const struct net_device *netdev, - const struct ethtool_link_ksettings *cmd) + const struct ethtool_link_ksettings *cmd, + u8 media_type) { struct hnae3_handle *handle = hns3_get_handle(netdev); const struct hnae3_ae_ops *ops = hns3_get_ops(handle); - u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN; - u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN; u32 lane_num; u8 autoneg; u32 speed; @@ -836,9 +835,6 @@ static int hns3_check_ksettings_param(const struct net_device *netdev, return 0; } - if (ops->get_media_type) - ops->get_media_type(handle, &media_type, &module_type); - if (cmd->base.duplex == DUPLEX_HALF && media_type != HNAE3_MEDIA_TYPE_COPPER) { netdev_err(netdev, @@ -863,6 +859,8 @@ static int hns3_set_link_ksettings(struct net_device *netdev, struct hnae3_handle *handle = hns3_get_handle(netdev); struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(handle); const struct hnae3_ae_ops *ops = hns3_get_ops(handle); + u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN; + u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN; int ret; /* Chip don't support this mode. */ @@ -878,22 +876,23 @@ static int hns3_set_link_ksettings(struct net_device *netdev, cmd->base.autoneg, cmd->base.speed, cmd->base.duplex, cmd->lanes); - /* Only support ksettings_set for netdev with phy attached for now */ - if (netdev->phydev) { - if (cmd->base.speed == SPEED_1000 && - cmd->base.autoneg == AUTONEG_DISABLE) - return -EINVAL; + if (!ops->get_media_type) + return -EOPNOTSUPP; + ops->get_media_type(handle, &media_type, &module_type); - return phy_ethtool_ksettings_set(netdev->phydev, cmd); - } else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) && - ops->set_phy_link_ksettings) { - return ops->set_phy_link_ksettings(handle, cmd); + if (media_type == HNAE3_MEDIA_TYPE_COPPER) { + if (!ops->set_phy_link_ksettings) + return -EOPNOTSUPP; + ret = ops->set_phy_link_ksettings(handle, cmd); + if (ret != -ENODEV) + return ret; + /* PHY_INEXISTENT, use MAC-level configuration */ } if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) return -EOPNOTSUPP; - ret = hns3_check_ksettings_param(netdev, cmd); + ret = hns3_check_ksettings_param(netdev, cmd, media_type); if (ret) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 2f1984930da2..fc8587c80813 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1504,6 +1504,11 @@ static int hclge_configure(struct hclge_dev *hdev) hdev->hw.mac.req_autoneg = AUTONEG_ENABLE; hdev->hw.mac.req_duplex = DUPLEX_FULL; + /* When lane_num is 0, the firmware will automatically + * select the appropriate lane_num based on the speed. + */ + hdev->hw.mac.req_lane_num = 0; + hclge_parse_link_mode(hdev, cfg.speed_ability); hdev->hw.mac.max_speed = hclge_get_max_speed(cfg.speed_ability); @@ -2579,8 +2584,11 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed, if (ret) return ret; - hdev->hw.mac.req_speed = (u32)speed; - hdev->hw.mac.req_duplex = duplex; + hdev->hw.mac.req_lane_num = lane_num; + if (speed != SPEED_UNKNOWN) + hdev->hw.mac.req_speed = (u32)speed; + if (duplex != DUPLEX_UNKNOWN) + hdev->hw.mac.req_duplex = duplex; return 0; } @@ -2611,6 +2619,7 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + int ret; if (!hdev->hw.mac.support_autoneg) { if (enable) { @@ -2622,7 +2631,10 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable) } } - return hclge_set_autoneg_en(hdev, enable); + ret = hclge_set_autoneg_en(hdev, enable); + if (!ret) + hdev->hw.mac.req_autoneg = enable; + return ret; } static int hclge_get_autoneg(struct hnae3_handle *handle) @@ -2884,20 +2896,6 @@ static int hclge_mac_init(struct hclge_dev *hdev) if (!test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) hdev->hw.mac.duplex = HCLGE_MAC_FULL; - if (hdev->hw.mac.support_autoneg) { - ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.autoneg); - if (ret) - return ret; - } - - if (!hdev->hw.mac.autoneg) { - ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed, - hdev->hw.mac.req_duplex, - hdev->hw.mac.lane_num); - if (ret) - return ret; - } - mac->link = 0; if (mac->user_fec_mode & BIT(HNAE3_FEC_USER_DEF)) { @@ -3285,8 +3283,8 @@ static int hclge_get_phy_link_ksettings(struct hnae3_handle *handle, } static int -hclge_set_phy_link_ksettings(struct hnae3_handle *handle, - const struct ethtool_link_ksettings *cmd) +hclge_ethtool_ksettings_set(struct hnae3_handle *handle, + const struct ethtool_link_ksettings *cmd) { struct hclge_desc desc[HCLGE_PHY_LINK_SETTING_BD_NUM]; struct hclge_vport *vport = hclge_get_vport(handle); @@ -3327,10 +3325,34 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle, return ret; } - hdev->hw.mac.req_autoneg = cmd->base.autoneg; - hdev->hw.mac.req_speed = cmd->base.speed; - hdev->hw.mac.req_duplex = cmd->base.duplex; linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising); + return 0; +} + +static int +hclge_set_phy_link_ksettings(struct hnae3_handle *handle, + const struct ethtool_link_ksettings *cmd) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + int ret = -ENODEV; + + if (hnae3_dev_phy_imp_supported(hdev)) { + ret = hclge_ethtool_ksettings_set(handle, cmd); + } else if (handle->netdev->phydev) { + if (cmd->base.speed == SPEED_1000 && + cmd->base.autoneg == AUTONEG_DISABLE) + return -EINVAL; + ret = phy_ethtool_ksettings_set(handle->netdev->phydev, cmd); + } + if (ret) + return ret; + + hdev->hw.mac.req_autoneg = cmd->base.autoneg; + if (cmd->base.speed != SPEED_UNKNOWN) + hdev->hw.mac.req_speed = cmd->base.speed; + if (cmd->base.duplex != DUPLEX_UNKNOWN) + hdev->hw.mac.req_duplex = cmd->base.duplex; return 0; } @@ -9294,6 +9316,27 @@ static int hclge_set_wol(struct hnae3_handle *handle, return ret; } +static int hclge_set_autoneg_speed_dup(struct hclge_dev *hdev) +{ + int ret; + + if (hdev->hw.mac.support_autoneg) { + ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.req_autoneg); + if (ret) + return ret; + } + + if (!hdev->hw.mac.req_autoneg) { + ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed, + hdev->hw.mac.req_duplex, + hdev->hw.mac.req_lane_num); + if (ret) + return ret; + } + + return 0; +} + static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) { struct pci_dev *pdev = ae_dev->pdev; @@ -9455,6 +9498,20 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) if (ret) goto err_ptp_uninit; + if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_COPPER) { + hdev->hw.mac.req_autoneg = hdev->hw.mac.autoneg; + if (hdev->hw.mac.autoneg == AUTONEG_DISABLE && + hdev->hw.mac.speed != SPEED_UNKNOWN) + hdev->hw.mac.req_speed = hdev->hw.mac.speed; + } + + ret = hclge_set_autoneg_speed_dup(hdev); + if (ret) { + dev_err(&pdev->dev, + "failed to set autoneg speed duplex, ret = %d\n", ret); + goto err_ptp_uninit; + } + INIT_KFIFO(hdev->mac_tnl_log); hclge_dcb_ops_set(hdev); @@ -9785,6 +9842,13 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) return ret; } + ret = hclge_set_autoneg_speed_dup(hdev); + if (ret) { + dev_err(&pdev->dev, + "failed to set autoneg speed duplex, ret = %d\n", ret); + return ret; + } + ret = hclge_tp_port_init(hdev); if (ret) { dev_err(&pdev->dev, "failed to init tp port, ret = %d\n", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 87adeb64e6ea..7419481422c3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -287,6 +287,7 @@ struct hclge_mac { u8 support_autoneg; u8 speed_type; /* 0: sfp speed, 1: active speed */ u8 lane_num; + u8 req_lane_num; u32 speed; u32 req_speed; u32 max_speed; diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index ff67c4fd66a3..bfc8699a05b9 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -3216,6 +3216,8 @@ static int ehea_create_device_sysfs(struct platform_device *dev) goto out; ret = device_create_file(&dev->dev, &dev_attr_remove_port); + if (ret) + device_remove_file(&dev->dev, &dev_attr_probe_port); out: return ret; } diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index c0e1d85fce3f..1d46cf6c2c12 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -3044,6 +3044,12 @@ static int emac_probe(struct platform_device *ofdev) if (err) goto err_gone; + dev->emacp = devm_platform_ioremap_resource(ofdev, 0); + if (IS_ERR(dev->emacp)) { + err = PTR_ERR(dev->emacp); + goto err_gone; + } + /* Setup error IRQ handler */ dev->emac_irq = platform_get_irq(ofdev, 0); if (dev->emac_irq < 0) { @@ -3061,13 +3067,6 @@ static int emac_probe(struct platform_device *ofdev) ndev->irq = dev->emac_irq; - dev->emacp = devm_platform_ioremap_resource(ofdev, 0); - if (IS_ERR(dev->emacp)) { - dev_err(&ofdev->dev, "can't map device registers"); - err = PTR_ERR(dev->emacp); - goto err_gone; - } - /* Wait for dependent devices */ err = emac_wait_deps(dev); if (err) diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index dea208db1be5..aa90e0ce8aca 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1594,6 +1594,9 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) phy_reg &= ~I217_PLL_CLOCK_GATE_MASK; if (speed == SPEED_100 || speed == SPEED_10) phy_reg |= 0x3E8; + else if (hw->mac.type == e1000_pch_mtp || + hw->mac.type == e1000_pch_ptp) + phy_reg |= 0x1D5; else phy_reg |= 0xFA; e1e_wphy_locked(hw, I217_PLL_CLOCK_GATE_REG, phy_reg); diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 808e5cddd6a9..844f31ab37ad 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -25,6 +25,7 @@ #include <linux/pm_runtime.h> #include <linux/prefetch.h> #include <linux/suspend.h> +#include <linux/dmi.h> #include "e1000.h" #define CREATE_TRACE_POINTS @@ -58,6 +59,17 @@ static const struct e1000_info *e1000_info_tbl[] = { [board_pch_ptp] = &e1000_pch_ptp_info, }; +static const struct dmi_system_id disable_k1_list[] = { + { + .ident = "Dell Pro 16 Plus PB16250", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell Pro 16 Plus PB16250"), + }, + }, + {} +}; + struct e1000_reg_info { u32 ofs; char *name; @@ -7670,7 +7682,8 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* init PTP hardware clock */ e1000e_ptp_init(adapter); - if (hw->mac.type >= e1000_pch_mtp) + /* disable K1 by default on known problematic systems */ + if (hw->mac.type >= e1000_pch_mtp && dmi_check_system(disable_k1_list)) adapter->flags2 |= FLAG2_DISABLE_K1; /* reset the hardware with the new settings */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_debug.h b/drivers/net/ethernet/intel/i40e/i40e_debug.h index e9871dfb32bd..01fd70db9086 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debug.h +++ b/drivers/net/ethernet/intel/i40e/i40e_debug.h @@ -42,7 +42,7 @@ struct device *i40e_hw_to_dev(struct i40e_hw *hw); #define i40e_debug(h, m, s, ...) \ do { \ if (((m) & (h)->debug_mask)) \ - dev_info(i40e_hw_to_dev(hw), s, ##__VA_ARGS__); \ + dev_info(i40e_hw_to_dev(h), s, ##__VA_ARGS__); \ } while (0) #endif /* _I40E_DEBUG_H_ */ diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c index a615d599b88e..e7cf12eaa268 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c @@ -1855,6 +1855,7 @@ static const struct ethtool_ops iavf_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_USE_ADAPTIVE, .supported_input_xfrm = RXH_XFRM_SYM_XOR, + .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_GLINK, .get_drvinfo = iavf_get_drvinfo, .get_link = ethtool_op_get_link, .get_ringparam = iavf_get_ringparam, diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 31e0de9e7f60..ef1ce106f81b 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -3882,7 +3882,6 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update) if (!pi || !aq_failures) return -EINVAL; - *aq_failures = 0; hw = pi->hw; pcaps = kzalloc_obj(*pcaps); diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c index 462c69cc11e1..30c3a4db7d61 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.c +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c @@ -4645,9 +4645,13 @@ ice_dpll_init_pins_info(struct ice_pf *pf, enum ice_dpll_pin_type pin_type) static void ice_dpll_deinit_info(struct ice_pf *pf) { kfree(pf->dplls.inputs); + pf->dplls.inputs = NULL; kfree(pf->dplls.outputs); + pf->dplls.outputs = NULL; kfree(pf->dplls.eec.input_prio); + pf->dplls.eec.input_prio = NULL; kfree(pf->dplls.pps.input_prio); + pf->dplls.pps.input_prio = NULL; } /** @@ -4748,12 +4752,16 @@ static int ice_dpll_init_info(struct ice_pf *pf, bool cgu) alloc_size = sizeof(*de->input_prio) * d->num_inputs; de->input_prio = kzalloc(alloc_size, GFP_KERNEL); - if (!de->input_prio) - return -ENOMEM; + if (!de->input_prio) { + ret = -ENOMEM; + goto deinit_info; + } dp->input_prio = kzalloc(alloc_size, GFP_KERNEL); - if (!dp->input_prio) - return -ENOMEM; + if (!dp->input_prio) { + ret = -ENOMEM; + goto deinit_info; + } ret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_INPUT); if (ret) @@ -4778,12 +4786,12 @@ static int ice_dpll_init_info(struct ice_pf *pf, bool cgu) ret = ice_get_cgu_rclk_pin_info(&pf->hw, &d->base_rclk_idx, &pf->dplls.rclk.num_parents); if (ret) - return ret; + goto deinit_info; for (i = 0; i < pf->dplls.rclk.num_parents; i++) pf->dplls.rclk.parent_idx[i] = d->base_rclk_idx + i; ret = ice_dpll_init_pins_info(pf, ICE_DPLL_PIN_TYPE_RCLK_INPUT); if (ret) - return ret; + goto deinit_info; de->mode = DPLL_MODE_AUTOMATIC; dp->mode = DPLL_MODE_AUTOMATIC; diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index 2e4f0969035f..c30e27bbfe6e 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -117,8 +117,6 @@ static int ice_eswitch_setup_repr(struct ice_pf *pf, struct ice_repr *repr) if (!repr->dst) return -ENOMEM; - netif_keep_dst(uplink_vsi->netdev); - dst = repr->dst; dst->u.port_info.port_id = vsi->vsi_num; dst->u.port_info.lower_dev = uplink_vsi->netdev; @@ -312,6 +310,8 @@ static int ice_eswitch_enable_switchdev(struct ice_pf *pf) if (ice_eswitch_br_offloads_init(pf)) goto err_br_offloads; + netif_keep_dst(uplink_vsi->netdev); + pf->eswitch.is_running = true; return 0; diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 236d293aba98..49371b065845 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -3508,7 +3508,7 @@ ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) struct ice_vsi *vsi = np->vsi; struct ice_hw *hw = &pf->hw; struct ice_port_info *pi; - u8 aq_failures; + u8 aq_failures = 0; bool link_up; u32 is_an; int err; @@ -3579,18 +3579,22 @@ ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) /* Set the FC mode and only restart AN if link is up */ err = ice_set_fc(pi, &aq_failures, link_up); - if (aq_failures & ICE_SET_FC_AQ_FAIL_GET) { + switch (aq_failures) { + case ICE_SET_FC_AQ_FAIL_GET: netdev_info(netdev, "Set fc failed on the get_phy_capabilities call with err %d aq_err %s\n", err, libie_aq_str(hw->adminq.sq_last_status)); err = -EAGAIN; - } else if (aq_failures & ICE_SET_FC_AQ_FAIL_SET) { + break; + case ICE_SET_FC_AQ_FAIL_SET: netdev_info(netdev, "Set fc failed on the set_phy_config call with err %d aq_err %s\n", err, libie_aq_str(hw->adminq.sq_last_status)); err = -EAGAIN; - } else if (aq_failures & ICE_SET_FC_AQ_FAIL_UPDATE) { + break; + case ICE_SET_FC_AQ_FAIL_UPDATE: netdev_info(netdev, "Set fc failed on the get_link_info call with err %d aq_err %s\n", err, libie_aq_str(hw->adminq.sq_last_status)); err = -EAGAIN; + break; } return err; diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index e2fbe111f849..e2fd2dab03e3 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -4789,16 +4789,14 @@ static void ice_init_wakeup(struct ice_pf *pf) device_set_wakeup_enable(ice_pf_to_dev(pf), false); } -static int ice_init_link(struct ice_pf *pf) +static void ice_init_link(struct ice_pf *pf) { struct device *dev = ice_pf_to_dev(pf); int err; err = ice_init_link_events(pf->hw.port_info); - if (err) { + if (err) dev_err(dev, "ice_init_link_events failed: %d\n", err); - return err; - } /* not a fatal error if this fails */ err = ice_init_nvm_phy_type(pf->hw.port_info); @@ -4838,8 +4836,6 @@ static int ice_init_link(struct ice_pf *pf) } else { set_bit(ICE_FLAG_NO_MEDIA, pf->flags); } - - return err; } static int ice_init_pf_sw(struct ice_pf *pf) @@ -4982,13 +4978,11 @@ static int ice_init(struct ice_pf *pf) ice_init_wakeup(pf); - err = ice_init_link(pf); - if (err) - goto err_init_link; + ice_init_link(pf); err = ice_send_version(pf); if (err) - goto err_init_link; + goto err_deinit_pf_sw; ice_verify_cacheline_size(pf); @@ -5007,7 +5001,7 @@ static int ice_init(struct ice_pf *pf) return 0; -err_init_link: +err_deinit_pf_sw: ice_deinit_pf_sw(pf); err_init_pf_sw: ice_dealloc_vsis(pf); diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index b1f46707dcc0..27e4acb1620f 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -801,7 +801,7 @@ void ice_reset_all_vfs(struct ice_pf *pf) * setup only when VF creates its first FDIR rule. */ if (vf->ctrl_vsi_idx != ICE_NO_VSI) - ice_vf_ctrl_invalidate_vsi(vf); + ice_vf_ctrl_vsi_release(vf); ice_vf_pre_vsi_rebuild(vf); if (ice_vf_rebuild_vsi(vf)) { diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 0c061fb0ed07..744d6585a949 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -5900,6 +5900,9 @@ static int mvneta_resume(struct device *device) rtnl_unlock(); mvneta_set_rx_mode(dev); + if (!pp->neta_armada3700) + on_each_cpu(mvneta_percpu_enable, pp, true); + return 0; } #endif diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c index 354c4e881c6a..3070700b952b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -3423,6 +3423,36 @@ static int npc_create_srch_order(int cnt) return 0; } +static int npc_subbanks_srch_order_init(struct rvu *rvu) +{ + struct npc_subbank *sb; + int sb_idx; + int i, j; + int rc; + + for (i = 0; i < npc_priv->num_subbanks; i++) { + sb_idx = subbank_srch_order[i]; + sb = &npc_priv->sb[sb_idx]; + sb->arr_idx = i; + + dev_dbg(rvu->dev, "%s: sb->idx=%u sb->arr_idx=%u\n", + __func__, sb->idx, sb->arr_idx); + + rc = xa_err(xa_store(&npc_priv->xa_sb_free, sb->arr_idx, + xa_mk_value(sb->idx), GFP_KERNEL)); + if (rc) { + dev_err(rvu->dev, + "%s: xa_store(xa_sb_free) failed at slot %d (sb=%d): %d\n", + __func__, i, sb_idx, rc); + for (j = 0; j < i; j++) + xa_erase(&npc_priv->xa_sb_free, j); + return rc; + } + } + + return 0; +} + static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int idx) { mutex_init(&sb->lock); @@ -3435,16 +3465,6 @@ static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int idx) sb->flags = NPC_SUBBANK_FLAG_FREE; sb->idx = idx; - sb->arr_idx = subbank_srch_order[idx]; - - dev_dbg(rvu->dev, "%s: sb->idx=%u sb->arr_idx=%u\n", - __func__, sb->idx, sb->arr_idx); - - /* Keep first and last subbank at end of free array; so that - * it will be used at last - */ - xa_store(&npc_priv->xa_sb_free, sb->arr_idx, - xa_mk_value(sb->idx), GFP_KERNEL); } static int npc_pcifunc_map_create(struct rvu *rvu) @@ -3569,15 +3589,18 @@ static int npc_defrag_alloc_free_slots(struct rvu *rvu, alloc_cnt2 = 0; rc = __npc_subbank_alloc(rvu, sb, - NPC_MCAM_KEY_X2, sb->b0b, + f->key_type, sb->b0b, sb->b0t, NPC_MCAM_LOWER_PRIO, false, cnt, save, cnt, true, &alloc_cnt1); - if (alloc_cnt1 < cnt) { + /* X4 entries only occupy bank 0 (b0b..b0t); see npc_subbank_idx_2_mcam_idx(). + * X2 uses both halves of the subbank, so spill into bank 1 if needed. + */ + if (alloc_cnt1 < cnt && f->key_type == NPC_MCAM_KEY_X2) { rc = __npc_subbank_alloc(rvu, sb, - NPC_MCAM_KEY_X2, sb->b1b, + f->key_type, sb->b1b, sb->b1t, NPC_MCAM_LOWER_PRIO, false, cnt - alloc_cnt1, @@ -4635,6 +4658,7 @@ static int npc_priv_init(struct rvu *rvu) int num_subbanks, subbank_depth; u64 npc_const1, npc_const2 = 0; struct npc_subbank *sb; + int ret = -ENOMEM; u64 cfg; int i; @@ -4727,13 +4751,19 @@ static int npc_priv_init(struct rvu *rvu) for (i = 0, sb = npc_priv->sb; i < num_subbanks; i++, sb++) npc_subbank_init(rvu, sb, i); + ret = npc_subbanks_srch_order_init(rvu); + if (ret) + goto fail3; + /* Get number of pcifuncs in the system */ npc_priv->pf_cnt = npc_pcifunc_map_create(rvu); npc_priv->xa_pf2idx_map = kcalloc(npc_priv->pf_cnt, sizeof(struct xarray), GFP_KERNEL); - if (!npc_priv->xa_pf2idx_map) + if (!npc_priv->xa_pf2idx_map) { + ret = -ENOMEM; goto fail3; + } for (i = 0; i < npc_priv->pf_cnt; i++) xa_init_flags(&npc_priv->xa_pf2idx_map[i], XA_FLAGS_ALLOC); @@ -4760,7 +4790,7 @@ fail2: fail1: kfree(npc_priv); npc_priv = NULL; - return -ENOMEM; + return ret; } void npc_cn20k_deinit(struct rvu *rvu) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mcs.c b/drivers/net/ethernet/marvell/octeontx2/af/mcs.c index c1775bd01c2b..a07e0b3d8d00 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mcs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/mcs.c @@ -120,13 +120,13 @@ void mcs_get_rx_secy_stats(struct mcs *mcs, struct mcs_secy_stats *stats, int id reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYUNTAGGEDX(id); stats->pkt_untaged_cnt = mcs_reg_read(mcs, reg); - reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYCTLX(id); - stats->pkt_ctl_cnt = mcs_reg_read(mcs, reg); - if (mcs->hw->mcs_blks > 1) { reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYNOTAGX(id); stats->pkt_notag_cnt = mcs_reg_read(mcs, reg); + return; } + reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYCTLX(id); + stats->pkt_ctl_cnt = mcs_reg_read(mcs, reg); } void mcs_get_flowid_stats(struct mcs *mcs, struct mcs_flowid_stats *stats, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c index d2163da28d18..fa4ea1258d29 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c @@ -178,6 +178,15 @@ int rvu_mbox_handler_lmtst_tbl_setup(struct rvu *rvu, * pcifunc (will be the one who is calling this mailbox). */ if (req->base_pcifunc) { + /* A VF is untrusted and must not redirect its LMTLINE to + * another PF's region, so confine VF callers to their own PF. + */ + if (is_vf(req->hdr.pcifunc) && + (!is_pf_func_valid(rvu, req->base_pcifunc) || + rvu_get_pf(rvu->pdev, req->hdr.pcifunc) != + rvu_get_pf(rvu->pdev, req->base_pcifunc))) + return -EPERM; + /* Calculating the LMT table index equivalent to primary * pcifunc. */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index fa461489acdd..3456313d3b3c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -482,10 +482,11 @@ static int rvu_dbg_mcs_rx_secy_stats_display(struct seq_file *filp, void *unused seq_printf(filp, "secy%d: Tagged ctrl pkts: %lld\n", secy_id, stats.pkt_tagged_ctl_cnt); seq_printf(filp, "secy%d: Untaged pkts: %lld\n", secy_id, stats.pkt_untaged_cnt); - seq_printf(filp, "secy%d: Ctrl pkts: %lld\n", secy_id, stats.pkt_ctl_cnt); if (mcs->hw->mcs_blks > 1) seq_printf(filp, "secy%d: pkts notag: %lld\n", secy_id, stats.pkt_notag_cnt); + else + seq_printf(filp, "secy%d: Ctrl pkts: %lld\n", secy_id, stats.pkt_ctl_cnt); } mutex_unlock(&mcs->stats_lock); return 0; @@ -2809,6 +2810,14 @@ static void rvu_dbg_npa_init(struct rvu *rvu) &rvu_dbg_npa_ndc_hits_miss_fops); } +/* Per-lmac CGX debugfs files need both RVU and CGX handle; inode->i_private + * points here so seq_file ops avoid pci_get_device(PCI_DEVID_OCTEONTX2_RVU_AF). + */ +struct rvu_cgx_lmac_dbgfs_ctx { + struct rvu *rvu; + void *cgxd; +}; + #define PRINT_CGX_CUML_NIXRX_STATUS(idx, name) \ ({ \ u64 cnt; \ @@ -2831,18 +2840,14 @@ static void rvu_dbg_npa_init(struct rvu *rvu) static int cgx_print_stats(struct seq_file *s, int lmac_id) { + struct rvu_cgx_lmac_dbgfs_ctx *dctx = s->private; struct cgx_link_user_info linfo; + struct rvu *rvu = dctx->rvu; struct mac_ops *mac_ops; - void *cgxd = s->private; + void *cgxd = dctx->cgxd; u64 ucast, mcast, bcast; int stat = 0, err = 0; u64 tx_stat, rx_stat; - struct rvu *rvu; - - rvu = pci_get_drvdata(pci_get_device(PCI_VENDOR_ID_CAVIUM, - PCI_DEVID_OCTEONTX2_RVU_AF, NULL)); - if (!rvu) - return -ENODEV; mac_ops = get_mac_ops(cgxd); /* There can be no CGX devices at all */ @@ -2949,20 +2954,16 @@ RVU_DEBUG_SEQ_FOPS(cgx_stat, cgx_stat_display, NULL); static int cgx_print_dmac_flt(struct seq_file *s, int lmac_id) { + struct rvu_cgx_lmac_dbgfs_ctx *dctx = s->private; + struct rvu *rvu = dctx->rvu; struct pci_dev *pdev = NULL; - void *cgxd = s->private; + void *cgxd = dctx->cgxd; char *bcast, *mcast; u16 index, domain; u8 dmac[ETH_ALEN]; - struct rvu *rvu; u64 cfg, mac; int pf; - rvu = pci_get_drvdata(pci_get_device(PCI_VENDOR_ID_CAVIUM, - PCI_DEVID_OCTEONTX2_RVU_AF, NULL)); - if (!rvu) - return -ENODEV; - pf = cgxlmac_to_pf(rvu, cgx_get_cgxid(cgxd), lmac_id); domain = 2; @@ -3009,17 +3010,13 @@ RVU_DEBUG_SEQ_FOPS(cgx_dmac_flt, cgx_dmac_flt_display, NULL); static int cgx_print_fwdata(struct seq_file *s, int lmac_id) { + struct rvu_cgx_lmac_dbgfs_ctx *dctx = s->private; struct cgx_lmac_fwdata_s *fwdata; - void *cgxd = s->private; + struct rvu *rvu = dctx->rvu; + void *cgxd = dctx->cgxd; struct phy_s *phy; - struct rvu *rvu; int cgx_id, i; - rvu = pci_get_drvdata(pci_get_device(PCI_VENDOR_ID_CAVIUM, - PCI_DEVID_OCTEONTX2_RVU_AF, NULL)); - if (!rvu) - return -ENODEV; - if (!rvu->fwdata) return -EAGAIN; @@ -3100,6 +3097,7 @@ RVU_DEBUG_SEQ_FOPS(cgx_fwdata, cgx_fwdata_display, NULL); static void rvu_dbg_cgx_init(struct rvu *rvu) { + struct rvu_cgx_lmac_dbgfs_ctx *ctx; struct mac_ops *mac_ops; unsigned long lmac_bmap; int i, lmac_id; @@ -3126,6 +3124,13 @@ static void rvu_dbg_cgx_init(struct rvu *rvu) rvu->rvu_dbg.cgx = debugfs_create_dir(dname, rvu->rvu_dbg.cgx_root); + ctx = devm_kzalloc(rvu->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + continue; + + ctx->rvu = rvu; + ctx->cgxd = cgx; + for_each_set_bit(lmac_id, &lmac_bmap, rvu->hw->lmac_per_cgx) { /* lmac debugfs dir */ sprintf(dname, "lmac%d", lmac_id); @@ -3133,13 +3138,13 @@ static void rvu_dbg_cgx_init(struct rvu *rvu) debugfs_create_dir(dname, rvu->rvu_dbg.cgx); debugfs_create_file_aux_num("stats", 0600, rvu->rvu_dbg.lmac, - cgx, lmac_id, &rvu_dbg_cgx_stat_fops); + ctx, lmac_id, &rvu_dbg_cgx_stat_fops); debugfs_create_file_aux_num("mac_filter", 0600, - rvu->rvu_dbg.lmac, cgx, lmac_id, + rvu->rvu_dbg.lmac, ctx, lmac_id, &rvu_dbg_cgx_dmac_flt_fops); - debugfs_create_file("fwdata", 0600, - rvu->rvu_dbg.lmac, cgx, - &rvu_dbg_cgx_fwdata_fops); + debugfs_create_file_aux_num("fwdata", 0600, + rvu->rvu_dbg.lmac, ctx, + lmac_id, &rvu_dbg_cgx_fwdata_fops); } } } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c index aa3ecab5ebd8..d63c3d33775a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c @@ -1511,7 +1511,9 @@ static int rvu_af_dl_nix_maxlf_validate(struct devlink *devlink, u32 id, struct rvu_devlink *rvu_dl = devlink_priv(devlink); struct rvu *rvu = rvu_dl->rvu; u16 max_nix0_lf, max_nix1_lf; - struct npc_mcam *mcam; + struct rvu_block *block; + int blkaddr = 0; + int free_lfs; u64 cfg; cfg = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_CONST2); @@ -1519,14 +1521,23 @@ static int rvu_af_dl_nix_maxlf_validate(struct devlink *devlink, u32 id, cfg = rvu_read64(rvu, BLKADDR_NIX1, NIX_AF_CONST2); max_nix1_lf = cfg & 0xFFF; - /* Do not allow user to modify maximum NIX LFs while mcam entries - * have already been assigned. + /* Do not allow user to modify maximum NIX LFs while NIX LFs + * have already been assigned. Note that modifying NIX LFs count + * can be done only before any LF attach requests from PFs and VFs + * and not later or concurrently. */ - mcam = &rvu->hw->mcam; - if (mcam->bmap_fcnt < mcam->bmap_entries) { - NL_SET_ERR_MSG_MOD(extack, - "mcam entries have already been assigned, can't resize"); - return -EPERM; + blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr); + while (blkaddr) { + block = &rvu->hw->block[blkaddr]; + + free_lfs = rvu_rsrc_free_count(&block->lf); + if (free_lfs != block->lf.max) { + NL_SET_ERR_MSG_MOD(extack, + "NIX LFs already assigned, can't resize"); + return -EPERM; + } + + blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr); } if (max_nix0_lf && val->vu16 > max_nix0_lf) { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index d8989395e875..0297c7ab0614 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -528,19 +528,24 @@ static int nix_setup_bpids(struct rvu *rvu, struct nix_hw *hw, int blkaddr) bp->fn_map = devm_kcalloc(rvu->dev, bp->bpids.max, sizeof(u16), GFP_KERNEL); if (!bp->fn_map) - return -ENOMEM; + goto free_bpids; bp->intf_map = devm_kcalloc(rvu->dev, bp->bpids.max, sizeof(u8), GFP_KERNEL); if (!bp->intf_map) - return -ENOMEM; + goto free_bpids; bp->ref_cnt = devm_kcalloc(rvu->dev, bp->bpids.max, sizeof(u8), GFP_KERNEL); if (!bp->ref_cnt) - return -ENOMEM; + goto free_bpids; return 0; + +free_bpids: + rvu_free_bitmap(&bp->bpids); + bp->bpids.bmap = NULL; + return -ENOMEM; } void rvu_nix_flr_free_bpids(struct rvu *rvu, u16 pcifunc) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c index a22decbe3449..91b5947dae06 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -2225,7 +2225,7 @@ int npc_install_mcam_drop_rule(struct rvu *rvu, int mcam_idx, u16 *counter_idx, return err; } - dev_err(rvu->dev, + dev_dbg(rvu->dev, "%s: Installed single drop on non hit rule at %d, cntr=%d\n", __func__, mcam_idx, req.cntr); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c index 2cc1bdfd9b2e..9524d38f1582 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c @@ -182,6 +182,7 @@ static void cn10k_mcs_free_rsrc(struct otx2_nic *pfvf, enum mcs_direction dir, clear_req->id = hw_rsrc_id; clear_req->type = type; clear_req->dir = dir; + clear_req->all = all; req = otx2_mbox_alloc_msg_mcs_free_resources(mbox); if (!req) @@ -1776,11 +1777,16 @@ fail: void cn10k_mcs_free(struct otx2_nic *pfvf) { + struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg; + if (!test_bit(CN10K_HW_MACSEC, &pfvf->hw.cap_flag)) return; - cn10k_mcs_free_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SECY, 0, true); - cn10k_mcs_free_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SECY, 0, true); + if (!list_empty(&cfg->txsc_list)) { + cn10k_mcs_free_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SECY, 0, true); + cn10k_mcs_free_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SECY, 0, true); + } + kfree(pfvf->macsec_cfg); pfvf->macsec_cfg = NULL; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index 41a0ebdf201e..b63df5737ff2 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -1575,6 +1575,7 @@ static void otx2_free_sq_res(struct otx2_nic *pf) qmem_free(pf->dev, sq->sqe_ring); qmem_free(pf->dev, sq->cpt_resp); qmem_free(pf->dev, sq->tso_hdrs); + qmem_free(pf->dev, sq->timestamps); kfree(sq->sg); kfree(sq->sqb_ptrs); } diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c index 41e19e9ad28d..a82e7a802985 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_main.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c @@ -373,7 +373,7 @@ static int prestera_port_sfp_bind(struct prestera_port *port) struct device_node *ports, *node; struct fwnode_handle *fwnode; struct phylink *phy_link; - int err; + int err = 0; if (!sw->np) return 0; diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 7d771168b990..5d291e50a47b 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -4960,6 +4960,11 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) mac_ops = &rt5350_phylink_ops; + if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_2P5GPHY) && + id == MTK_GMAC2_ID) + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + mac->phylink_config.supported_interfaces); + phylink = phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, mac_ops); @@ -4970,11 +4975,6 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) mac->phylink = phylink; - if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_2P5GPHY) && - id == MTK_GMAC2_ID) - __set_bit(PHY_INTERFACE_MODE_INTERNAL, - mac->phylink_config.supported_interfaces); - SET_NETDEV_DEV(eth->netdev[id], eth->dev); eth->netdev[id]->watchdog_timeo = 5 * HZ; eth->netdev[id]->netdev_ops = &mtk_netdev_ops; diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c index 18279e2a7022..8451dc3fd00a 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c @@ -918,7 +918,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index) mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib), &ppe->mib_phys, GFP_KERNEL); if (!mib) - return NULL; + goto err_free_l2_flows; ppe->mib_table = mib; @@ -926,7 +926,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index) GFP_KERNEL); if (!acct) - return NULL; + goto err_free_l2_flows; ppe->acct_table = acct; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig index 3c3e84100d5a..925ee25d05b4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -143,7 +143,7 @@ config MLX5_CORE_IPOIB config MLX5_MACSEC bool "Connect-X support for MACSec offload" depends on MLX5_CORE_EN - depends on MACSEC + depends on MACSEC=y || MACSEC=MLX5_CORE default n help Build support for MACsec cryptography-offload acceleration in the NIC. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 2f5b626ba33f..112926d07634 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -2721,7 +2721,8 @@ const struct ethtool_ops mlx5e_ethtool_ops = { .rxfh_max_num_contexts = MLX5E_MAX_NUM_RSS, .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS | ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM | - ETHTOOL_OP_NEEDS_RTNL_SPFLAGS, + ETHTOOL_OP_NEEDS_RTNL_SPFLAGS | + ETHTOOL_OP_NEEDS_RTNL_GLINK, .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_MAX_FRAMES | ETHTOOL_COALESCE_USE_ADAPTIVE | diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 1a8a19f980d3..c8b76d301c92 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -419,7 +419,8 @@ static const struct ethtool_ops mlx5e_rep_ethtool_ops = { ETHTOOL_COALESCE_MAX_FRAMES | ETHTOOL_COALESCE_USE_ADAPTIVE, .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS | - ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM, + ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM | + ETHTOOL_OP_NEEDS_RTNL_GLINK, .get_drvinfo = mlx5e_rep_get_drvinfo, .get_link = ethtool_op_get_link, .get_strings = mlx5e_rep_get_strings, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c index 9b3b32408c64..01ddc3def9ac 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c @@ -286,7 +286,8 @@ const struct ethtool_ops mlx5i_ethtool_ops = { ETHTOOL_COALESCE_MAX_FRAMES | ETHTOOL_COALESCE_USE_ADAPTIVE, .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS | - ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM, + ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM | + ETHTOOL_OP_NEEDS_RTNL_GLINK, .get_drvinfo = mlx5i_get_drvinfo, .get_strings = mlx5i_get_strings, .get_sset_count = mlx5i_get_sset_count, @@ -309,6 +310,7 @@ const struct ethtool_ops mlx5i_ethtool_ops = { }; const struct ethtool_ops mlx5i_pkey_ethtool_ops = { + .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_GLINK, .get_drvinfo = mlx5i_get_drvinfo, .get_link = ethtool_op_get_link, .get_ts_info = mlx5i_get_ts_info, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 51637e58a48b..09e669f83dba 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -297,7 +297,6 @@ void mlx5_core_reps_aux_devs_remove(struct mlx5_core_dev *dev); void mlx5_fw_reporters_create(struct mlx5_core_dev *dev); int mlx5_query_mtpps(struct mlx5_core_dev *dev, u32 *mtpps, u32 mtpps_size); int mlx5_set_mtpps(struct mlx5_core_dev *mdev, u32 *mtpps, u32 mtpps_size); -int mlx5_query_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 *arm, u8 *mode); int mlx5_set_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 arm, u8 mode); struct mlx5_dm *mlx5_dm_create(struct mlx5_core_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index ee8b9765c5ba..ddbe9ca8971d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -908,25 +908,6 @@ int mlx5_set_mtpps(struct mlx5_core_dev *mdev, u32 *mtpps, u32 mtpps_size) sizeof(out), MLX5_REG_MTPPS, 0, 1); } -int mlx5_query_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 *arm, u8 *mode) -{ - u32 out[MLX5_ST_SZ_DW(mtppse_reg)] = {0}; - u32 in[MLX5_ST_SZ_DW(mtppse_reg)] = {0}; - int err = 0; - - MLX5_SET(mtppse_reg, in, pin, pin); - - err = mlx5_core_access_reg(mdev, in, sizeof(in), out, - sizeof(out), MLX5_REG_MTPPSE, 0, 0); - if (err) - return err; - - *arm = MLX5_GET(mtppse_reg, in, event_arm); - *mode = MLX5_GET(mtppse_reg, in, event_generation_mode); - - return err; -} - int mlx5_set_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 arm, u8 mode) { u32 out[MLX5_ST_SZ_DW(mtppse_reg)] = {0}; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c index cb34fc166ef9..0e47088ec44b 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c @@ -2024,7 +2024,8 @@ static const struct ethtool_ops fbnic_ethtool_ops = { ETHTOOL_OP_NEEDS_RTNL_GPAUSEPARAM | ETHTOOL_OP_NEEDS_RTNL_SPAUSEPARAM | ETHTOOL_OP_NEEDS_RTNL_SCHANNELS | - ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM, + ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM | + ETHTOOL_OP_NEEDS_RTNL_GLINK, .get_drvinfo = fbnic_get_drvinfo, .get_regs_len = fbnic_get_regs_len, .get_regs = fbnic_get_regs, diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c index 0c6812fcf185..283d25fae79e 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c @@ -526,15 +526,10 @@ int fbnic_fw_xmit_ownership_msg(struct fbnic_dev *fbd, bool take_ownership) goto free_message; } - err = fbnic_mbx_map_tlv_msg(fbd, msg); - if (err) - goto free_message; - /* Initialize heartbeat, set last response to 1 second in the past * so that we will trigger a timeout if the firmware doesn't respond */ fbd->last_heartbeat_response = req_time - HZ; - fbd->last_heartbeat_request = req_time; /* Set prev_firmware_time to 0 to avoid triggering firmware crash @@ -542,6 +537,10 @@ int fbnic_fw_xmit_ownership_msg(struct fbnic_dev *fbd, bool take_ownership) */ fbd->prev_firmware_time = 0; + err = fbnic_mbx_map_tlv_msg(fbd, msg); + if (err) + goto free_message; + /* Set heartbeat detection based on if we are taking ownership */ fbd->fw_heartbeat_enabled = take_ownership; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c index dd77ab6052c8..10bf99be3f24 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c @@ -264,8 +264,11 @@ static int fbnic_set_mac(struct net_device *netdev, void *p) eth_hw_addr_set(netdev, addr->sa_data); - if (netif_running(netdev)) + if (netif_running(netdev)) { + netif_addr_lock_bh(netdev); __fbnic_set_rx_mode(fbn->fbd, &netdev->uc, &netdev->mc); + netif_addr_unlock_bh(netdev); + } return 0; } @@ -310,8 +313,10 @@ void fbnic_clear_rx_mode(struct fbnic_dev *fbd) /* Write updates to hardware */ fbnic_write_macda(fbd); + netif_addr_lock_bh(netdev); __dev_uc_unsync(netdev, NULL); __dev_mc_unsync(netdev, NULL); + netif_addr_unlock_bh(netdev); } static int fbnic_hwtstamp_get(struct net_device *netdev, diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c index 7e85b480203c..8b9bc9e8ea56 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c @@ -135,7 +135,9 @@ void fbnic_up(struct fbnic_net *fbn) fbnic_rss_reinit_hw(fbn->fbd, fbn); + netif_addr_lock_bh(fbn->netdev); __fbnic_set_rx_mode(fbn->fbd, &fbn->netdev->uc, &fbn->netdev->mc); + netif_addr_unlock_bh(fbn->netdev); /* Enable Tx/Rx processing */ fbnic_napi_enable(fbn); @@ -180,7 +182,9 @@ static int fbnic_fw_config_after_crash(struct fbnic_dev *fbd) } fbnic_rpc_reset_valid_entries(fbd); + netif_addr_lock_bh(fbd->netdev); __fbnic_set_rx_mode(fbd, &fbd->netdev->uc, &fbd->netdev->mc); + netif_addr_unlock_bh(fbd->netdev); return 0; } diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c index fe95b6f69646..bc0f38b6a2b2 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c @@ -244,7 +244,9 @@ void fbnic_bmc_rpc_check(struct fbnic_dev *fbd) if (fbd->fw_cap.need_bmc_tcam_reinit) { fbnic_bmc_rpc_init(fbd); + netif_addr_lock_bh(fbd->netdev); __fbnic_set_rx_mode(fbd, &fbd->netdev->uc, &fbd->netdev->mc); + netif_addr_unlock_bh(fbd->netdev); fbd->fw_cap.need_bmc_tcam_reinit = false; } diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c index 644458108dd2..dac4dd833127 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c @@ -765,11 +765,13 @@ int sparx5_register_notifier_blocks(struct sparx5 *s5) sparx5_owq = alloc_ordered_workqueue("sparx5_order", 0); if (!sparx5_owq) { err = -ENOMEM; - goto err_switchdev_blocking_nb; + goto err_alloc_workqueue; } return 0; +err_alloc_workqueue: + unregister_switchdev_blocking_notifier(&s5->switchdev_blocking_nb); err_switchdev_blocking_nb: unregister_switchdev_notifier(&s5->switchdev_nb); err_switchdev_nb: diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c index a0fdd052d7f1..e8b7ffb47eb9 100644 --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c @@ -210,6 +210,8 @@ static int mana_gd_query_max_resources(struct pci_dev *pdev) } else { /* If dynamic allocation is enabled we have already allocated * hwc msi + * Also, we make sure in this case the following is always true + * (num_msix_usable - 1 HWC) <= num_online_cpus() */ gc->num_msix_usable = min(resp.max_msix, num_online_cpus() + 1); } @@ -1909,8 +1911,8 @@ void mana_gd_free_res_map(struct gdma_resource *r) * do the same thing. */ -static int irq_setup(unsigned int *irqs, unsigned int len, int node, - bool skip_first_cpu) +static int mana_irq_setup_numa_aware(unsigned int *irqs, unsigned int len, + int node, bool skip_first_cpu) { const struct cpumask *next, *prev = cpu_none_mask; cpumask_var_t cpus __free(free_cpumask_var); @@ -1946,11 +1948,24 @@ done: return 0; } +/* must be called with cpus_read_lock() held */ +static void mana_irq_setup_linear(unsigned int *irqs, unsigned int len) +{ + int cpu; + + for_each_online_cpu(cpu) { + if (len == 0) + break; + + irq_set_affinity_and_hint(*irqs++, cpumask_of(cpu)); + len--; + } +} + static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec) { struct gdma_context *gc = pci_get_drvdata(pdev); struct gdma_irq_context *gic; - bool skip_first_cpu = false; int *irqs, err, i, msi; irqs = kmalloc_objs(int, nvec); @@ -1958,10 +1973,12 @@ static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec) return -ENOMEM; /* + * In this function, num_msix_usable = HWC IRQ + Queue IRQ. + * nvec is only Queue IRQ (HWC already setup). * While processing the next pci irq vector, we start with index 1, * as IRQ vector at index 0 is already processed for HWC. * However, the population of irqs array starts with index 0, to be - * further used in irq_setup() + * further used in mana_irq_setup_numa_aware() */ for (i = 1; i <= nvec; i++) { msi = i; @@ -1975,18 +1992,51 @@ static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec) } /* - * When calling irq_setup() for dynamically added IRQs, if number of - * CPUs is more than or equal to allocated MSI-X, we need to skip the - * first CPU sibling group since they are already affinitized to HWC IRQ + * When calling mana_irq_setup_numa_aware() for dynamically added IRQs, + * if number of CPUs is more than or equal to allocated MSI-X, we need to + * skip the first CPU sibling group since they are already affinitized to + * HWC IRQ */ cpus_read_lock(); - if (gc->num_msix_usable <= num_online_cpus()) - skip_first_cpu = true; + if (gc->num_msix_usable <= num_online_cpus()) { + err = mana_irq_setup_numa_aware(irqs, nvec, gc->numa_node, + true); + if (err) { + cpus_read_unlock(); + goto free_irq; + } + } else { + /* + * When num_msix_usable are more than num_online_cpus, our + * queue IRQs should be equal to num of online vCPUs. + * We try to make sure queue IRQs spread across all vCPUs. + * In such a case NUMA or CPU core affinity does not matter. + * Note: in this case the total mana IRQ should always be + * num_online_cpus + 1. The first HWC IRQ is already handled + * in HWC setup calls + * However, if CPUs went offline since num_msix_usable was + * computed, queue IRQs will be more than num_online_cpus(). + * In such cases remaining extra IRQs will retain their default + * affinity. + */ + int first_unassigned = num_online_cpus(); - err = irq_setup(irqs, nvec, gc->numa_node, skip_first_cpu); - if (err) { - cpus_read_unlock(); - goto free_irq; + if (nvec > first_unassigned) { + char buf[32]; + + if (first_unassigned == nvec - 1) + snprintf(buf, sizeof(buf), "%d", + first_unassigned); + else + snprintf(buf, sizeof(buf), "%d-%d", + first_unassigned, nvec - 1); + + dev_dbg(&pdev->dev, + "MANA IRQ indices #%s will retain the default CPU affinity\n", + buf); + } + + mana_irq_setup_linear(irqs, nvec); } cpus_read_unlock(); @@ -2041,7 +2091,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev, int nvec) nvec -= 1; } - err = irq_setup(irqs, nvec, gc->numa_node, false); + err = mana_irq_setup_numa_aware(irqs, nvec, gc->numa_node, false); if (err) { cpus_read_unlock(); goto free_irq; diff --git a/drivers/net/ethernet/microsoft/mana/mana_bpf.c b/drivers/net/ethernet/microsoft/mana/mana_bpf.c index b5e9bb184a1d..53308e139cbe 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_bpf.c +++ b/drivers/net/ethernet/microsoft/mana/mana_bpf.c @@ -237,7 +237,8 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog, bpf_prog_put(old_prog); if (prog) - ndev->max_mtu = MANA_XDP_MTU_MAX; + ndev->max_mtu = min_t(unsigned int, MANA_XDP_MTU_MAX, + gc->adapter_mtu - ETH_HLEN); else ndev->max_mtu = gc->adapter_mtu - ETH_HLEN; diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index 87862b0434c7..7438ea6b3f26 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -1233,12 +1233,24 @@ int mana_gd_query_device_cfg(struct gdma_context *gc, u32 proto_major_ver, *max_num_vports = resp.max_num_vports; if (resp.hdr.response.msg_version >= GDMA_MESSAGE_V2) { - if (resp.adapter_mtu < ETH_MIN_MTU + ETH_HLEN) { + if (resp.adapter_mtu == 0) { + /* + * Some older PF firmware versions report an + * adapter_mtu of 0. MANA hardware always supports the + * standard Ethernet MTU, so fall back to ETH_FRAME_LEN. + * Jumbo frames will not be available in this case. + */ + dev_info(dev, + "PF reported adapter_mtu of 0, falling back to %u (jumbo frames disabled)\n", + ETH_FRAME_LEN); + gc->adapter_mtu = ETH_FRAME_LEN; + } else if (resp.adapter_mtu < ETH_MIN_MTU + ETH_HLEN) { dev_err(dev, "Adapter MTU too small: %u\n", resp.adapter_mtu); return -EPROTO; + } else { + gc->adapter_mtu = resp.adapter_mtu; } - gc->adapter_mtu = resp.adapter_mtu; } else { gc->adapter_mtu = ETH_FRAME_LEN; } diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c index 94e658d07a27..881df597d7f9 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c +++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c @@ -597,7 +597,8 @@ static int mana_get_link_ksettings(struct net_device *ndev, const struct ethtool_ops mana_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_RX_CQE_FRAMES, .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS | - ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM, + ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM | + ETHTOOL_OP_NEEDS_RTNL_GLINK, .get_ethtool_stats = mana_get_ethtool_stats, .get_sset_count = mana_get_sset_count, .get_strings = mana_get_strings, diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 62f05f4569b1..48b94ce77490 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -1420,13 +1420,25 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter, return 0; } +static void pch_gbe_free_rx_buffers_pool(struct pch_gbe_adapter *adapter, + struct pch_gbe_rx_ring *rx_ring) +{ + dma_free_coherent(&adapter->pdev->dev, rx_ring->rx_buff_pool_size, + rx_ring->rx_buff_pool, rx_ring->rx_buff_pool_logic); + rx_ring->rx_buff_pool_logic = 0; + rx_ring->rx_buff_pool_size = 0; + rx_ring->rx_buff_pool = NULL; +} + /** * pch_gbe_alloc_tx_buffers - Allocate transmit buffers * @adapter: Board private structure * @tx_ring: Tx descriptor ring + * + * Return: 0 on success, -ENOMEM if a TX skb allocation fails. */ -static void pch_gbe_alloc_tx_buffers(struct pch_gbe_adapter *adapter, - struct pch_gbe_tx_ring *tx_ring) +static int pch_gbe_alloc_tx_buffers(struct pch_gbe_adapter *adapter, + struct pch_gbe_tx_ring *tx_ring) { struct pch_gbe_buffer *buffer_info; struct sk_buff *skb; @@ -1440,12 +1452,17 @@ static void pch_gbe_alloc_tx_buffers(struct pch_gbe_adapter *adapter, for (i = 0; i < tx_ring->count; i++) { buffer_info = &tx_ring->buffer_info[i]; skb = netdev_alloc_skb(adapter->netdev, bufsz); + if (!skb) { + pch_gbe_clean_tx_ring(adapter, tx_ring); + return -ENOMEM; + } skb_reserve(skb, PCH_GBE_DMA_ALIGN); buffer_info->skb = skb; tx_desc = PCH_GBE_TX_DESC(*tx_ring, i); tx_desc->gbec_status = (DSC_INIT16); } - return; + + return 0; } /** @@ -1887,7 +1904,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) "Error: can't bring device up - alloc rx buffers pool failed\n"); goto freeirq; } - pch_gbe_alloc_tx_buffers(adapter, tx_ring); + err = pch_gbe_alloc_tx_buffers(adapter, tx_ring); + if (err) { + netdev_err(netdev, + "Error: can't bring device up - alloc tx buffers failed\n"); + goto freebuf; + } pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count); adapter->tx_queue_len = netdev->tx_queue_len; pch_gbe_enable_dma_rx(&adapter->hw); @@ -1901,6 +1923,8 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) return 0; +freebuf: + pch_gbe_free_rx_buffers_pool(adapter, rx_ring); freeirq: pch_gbe_free_irq(adapter); out: @@ -1936,11 +1960,7 @@ void pch_gbe_down(struct pch_gbe_adapter *adapter) pch_gbe_clean_tx_ring(adapter, adapter->tx_ring); pch_gbe_clean_rx_ring(adapter, adapter->rx_ring); - dma_free_coherent(&adapter->pdev->dev, rx_ring->rx_buff_pool_size, - rx_ring->rx_buff_pool, rx_ring->rx_buff_pool_logic); - rx_ring->rx_buff_pool_logic = 0; - rx_ring->rx_buff_pool_size = 0; - rx_ring->rx_buff_pool = NULL; + pch_gbe_free_rx_buffers_pool(adapter, rx_ring); } /** diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c index 66a8ae67c3ea..15d19a8a1710 100644 --- a/drivers/net/ethernet/rocker/rocker_ofdpa.c +++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c @@ -1924,6 +1924,9 @@ static int ofdpa_port_fdb(struct ofdpa_port *ofdpa_port, flags |= OFDPA_OP_FLAG_REFRESH; } + if (found && removing) + kfree(found); + return ofdpa_port_fdb_learn(ofdpa_port, flags, addr, vlan_id); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-spacemit.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-spacemit.c index 223754cc5c79..322bdf167a4a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-spacemit.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-spacemit.c @@ -18,10 +18,12 @@ #include "stmmac_platform.h" /* ctrl register bits */ -#define CTRL_PHY_INTF_RGMII BIT(3) -#define CTRL_PHY_INTF_MII BIT(4) -#define CTRL_WAKE_IRQ_EN BIT(9) -#define CTRL_PHY_IRQ_EN BIT(12) +#define CTRL_PHY_INTF_MODE GENMASK(4, 3) +#define CTRL_PHY_INTF_RMII FIELD_PREP(CTRL_PHY_INTF_MODE, 0) +#define CTRL_PHY_INTF_RGMII FIELD_PREP(CTRL_PHY_INTF_MODE, 1) +#define CTRL_PHY_INTF_MII FIELD_PREP(CTRL_PHY_INTF_MODE, 3) +#define CTRL_LPI_IRQ_EN BIT(9) +#define CTRL_WAKE_IRQ_EN BIT(12) /* dline register bits */ #define RGMII_RX_DLINE_EN BIT(0) @@ -118,7 +120,7 @@ static void spacemit_get_interfaces(struct stmmac_priv *priv, void *bsp_priv, static int spacemit_set_phy_intf_sel(void *bsp_priv, u8 phy_intf_sel) { - unsigned int mask = CTRL_PHY_INTF_MII | CTRL_PHY_INTF_RGMII; + unsigned int mask = CTRL_PHY_INTF_MODE; struct spacmit_dwmac *dwmac = bsp_priv; unsigned int val = 0; @@ -128,6 +130,7 @@ static int spacemit_set_phy_intf_sel(void *bsp_priv, u8 phy_intf_sel) break; case PHY_INTF_SEL_RMII: + val = CTRL_PHY_INTF_RMII; break; case PHY_INTF_SEL_RGMII: diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index b56a0d4cdb12..dc5638d105db 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -2978,10 +2978,10 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->max_mtu = GEM_MAX_MTU; /* Register with kernel */ - if (register_netdev(dev)) { + err = register_netdev(dev); + if (err) { pr_err("Cannot register net device, aborting\n"); - err = -ENOMEM; - goto err_out_free_consistent; + goto err_out_clear_drvdata; } /* Undo the get_cell with appropriate locking (we could use @@ -2995,8 +2995,13 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->dev_addr); return 0; +err_out_clear_drvdata: + pci_set_drvdata(pdev, NULL); + netif_napi_del(&gp->napi); + err_out_free_consistent: - gem_remove_one(pdev); + dma_free_coherent(&pdev->dev, sizeof(struct gem_init_block), + gp->init_block, gp->gblock_dvma); err_out_iounmap: gem_put_cell(gp); iounmap(gp->regs); diff --git a/drivers/net/ethernet/sunplus/spl2sw_phy.c b/drivers/net/ethernet/sunplus/spl2sw_phy.c index 6f899e48f51d..a4889c52e00e 100644 --- a/drivers/net/ethernet/sunplus/spl2sw_phy.c +++ b/drivers/net/ethernet/sunplus/spl2sw_phy.c @@ -79,12 +79,14 @@ int spl2sw_phy_connect(struct spl2sw_common *comm) void spl2sw_phy_remove(struct spl2sw_common *comm) { struct net_device *ndev; + struct spl2sw_mac *mac; int i; for (i = 0; i < MAX_NETDEV_NUM; i++) if (comm->ndev[i]) { ndev = comm->ndev[i]; - if (ndev) - phy_disconnect(ndev->phydev); + mac = netdev_priv(ndev); + phy_disconnect(ndev->phydev); + of_node_put(mac->phy_node); } } diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c index 82ddef9c17d5..4a7d1a6f470b 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_common.c +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c @@ -93,8 +93,8 @@ void prueth_ndev_del_tx_napi(struct prueth_emac *emac, int num) } EXPORT_SYMBOL_GPL(prueth_ndev_del_tx_napi); -static int emac_xsk_xmit_zc(struct prueth_emac *emac, - unsigned int q_idx) +static void emac_xsk_xmit_zc(struct prueth_emac *emac, + unsigned int q_idx) { struct prueth_tx_chn *tx_chn = &emac->tx_chns[q_idx]; struct xsk_buff_pool *pool = tx_chn->xsk_pool; @@ -115,7 +115,7 @@ static int emac_xsk_xmit_zc(struct prueth_emac *emac, * necessary */ if (descs_avail <= MAX_SKB_FRAGS) - return 0; + return; descs_avail -= MAX_SKB_FRAGS; @@ -170,8 +170,8 @@ static int emac_xsk_xmit_zc(struct prueth_emac *emac, num_tx++; } - xsk_tx_release(tx_chn->xsk_pool); - return num_tx; + if (num_tx) + xsk_tx_release(tx_chn->xsk_pool); } void prueth_xmit_free(struct prueth_tx_chn *tx_chn, @@ -279,9 +279,6 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn, num_tx++; } - if (!num_tx) - return 0; - netif_txq = netdev_get_tx_queue(ndev, chn); netdev_tx_completed_queue(netif_txq, num_tx, total_bytes); @@ -297,16 +294,18 @@ int emac_tx_complete_packets(struct prueth_emac *emac, int chn, __netif_tx_unlock(netif_txq); } - if (tx_chn->xsk_pool) { - if (xsk_frames_done) + if (budget && tx_chn->xsk_pool) { + if (xsk_frames_done) { xsk_tx_completed(tx_chn->xsk_pool, xsk_frames_done); + txq_trans_cond_update(netif_txq); + } if (xsk_uses_need_wakeup(tx_chn->xsk_pool)) xsk_set_tx_need_wakeup(tx_chn->xsk_pool); - netif_txq = netdev_get_tx_queue(ndev, chn); - txq_trans_cond_update(netif_txq); + __netif_tx_lock(netif_txq, smp_processor_id()); emac_xsk_xmit_zc(emac, chn); + __netif_tx_unlock(netif_txq); } return num_tx; @@ -1652,28 +1651,35 @@ void icssg_ndo_get_stats64(struct net_device *ndev, stats->rx_over_errors = emac_get_stat_by_name(emac, "rx_over_errors"); stats->multicast = emac_get_stat_by_name(emac, "rx_multicast_frames"); - stats->rx_errors = ndev->stats.rx_errors + - emac_get_stat_by_name(emac, "FW_RX_ERROR") + - emac_get_stat_by_name(emac, "FW_RX_EOF_SHORT_FRMERR") + - emac_get_stat_by_name(emac, "FW_RX_B0_DROP_EARLY_EOF") + - emac_get_stat_by_name(emac, "FW_RX_EXP_FRAG_Q_DROP") + - emac_get_stat_by_name(emac, "FW_RX_FIFO_OVERRUN"); - stats->rx_dropped = ndev->stats.rx_dropped + - emac_get_stat_by_name(emac, "FW_DROPPED_PKT") + - emac_get_stat_by_name(emac, "FW_INF_PORT_DISABLED") + - emac_get_stat_by_name(emac, "FW_INF_SAV") + - emac_get_stat_by_name(emac, "FW_INF_SA_DL") + - emac_get_stat_by_name(emac, "FW_INF_PORT_BLOCKED") + - emac_get_stat_by_name(emac, "FW_INF_DROP_TAGGED") + - emac_get_stat_by_name(emac, "FW_INF_DROP_PRIOTAGGED") + - emac_get_stat_by_name(emac, "FW_INF_DROP_NOTAG") + - emac_get_stat_by_name(emac, "FW_INF_DROP_NOTMEMBER"); + stats->rx_errors = ndev->stats.rx_errors; + stats->rx_dropped = ndev->stats.rx_dropped; stats->tx_errors = ndev->stats.tx_errors; - stats->tx_dropped = ndev->stats.tx_dropped + - emac_get_stat_by_name(emac, "FW_RTU_PKT_DROP") + - emac_get_stat_by_name(emac, "FW_TX_DROPPED_PACKET") + - emac_get_stat_by_name(emac, "FW_TX_TS_DROPPED_PACKET") + - emac_get_stat_by_name(emac, "FW_TX_JUMBO_FRM_CUTOFF"); + stats->tx_dropped = ndev->stats.tx_dropped; + + if (!emac->prueth->pa_stats) + return; + + stats->rx_errors += + emac_get_stat_by_name(emac, "FW_RX_ERROR") + + emac_get_stat_by_name(emac, "FW_RX_EOF_SHORT_FRMERR") + + emac_get_stat_by_name(emac, "FW_RX_B0_DROP_EARLY_EOF") + + emac_get_stat_by_name(emac, "FW_RX_EXP_FRAG_Q_DROP") + + emac_get_stat_by_name(emac, "FW_RX_FIFO_OVERRUN"); + stats->rx_dropped += + emac_get_stat_by_name(emac, "FW_DROPPED_PKT") + + emac_get_stat_by_name(emac, "FW_INF_PORT_DISABLED") + + emac_get_stat_by_name(emac, "FW_INF_SAV") + + emac_get_stat_by_name(emac, "FW_INF_SA_DL") + + emac_get_stat_by_name(emac, "FW_INF_PORT_BLOCKED") + + emac_get_stat_by_name(emac, "FW_INF_DROP_TAGGED") + + emac_get_stat_by_name(emac, "FW_INF_DROP_PRIOTAGGED") + + emac_get_stat_by_name(emac, "FW_INF_DROP_NOTAG") + + emac_get_stat_by_name(emac, "FW_INF_DROP_NOTMEMBER"); + stats->tx_dropped += + emac_get_stat_by_name(emac, "FW_RTU_PKT_DROP") + + emac_get_stat_by_name(emac, "FW_TX_DROPPED_PACKET") + + emac_get_stat_by_name(emac, "FW_TX_TS_DROPPED_PACKET") + + emac_get_stat_by_name(emac, "FW_TX_JUMBO_FRM_CUTOFF"); } EXPORT_SYMBOL_GPL(icssg_ndo_get_stats64); diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c index 8678c49b892a..a16221995909 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c @@ -715,7 +715,6 @@ static int ngbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_GRO; netdev->priv_flags |= IFF_UNICAST_FLT; - netdev->priv_flags |= IFF_SUPP_NOFCS; netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; netdev->min_mtu = ETH_MIN_MTU; diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index ce82e13aa8ae..20c5a295c6c2 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -796,7 +796,6 @@ static int txgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_RX_UDP_TUNNEL_PORT; netdev->priv_flags |= IFF_UNICAST_FLT; - netdev->priv_flags |= IFF_SUPP_NOFCS; netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; netdev->min_mtu = ETH_MIN_MTU; diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 9afff7bcaa0b..396e1a113cd4 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -954,13 +954,27 @@ static int geneve_gro_complete(struct sock *sk, struct sk_buff *skb, struct genevehdr *gh; struct packet_offload *ptype; __be16 type; - int gh_len; + unsigned int gh_len; int err = -ENOSYS; gh = (struct genevehdr *)(skb->data + nhoff); gh_len = geneve_hlen(gh); type = gh->proto_type; - geneve_opt_gro_hint_off(gh, &type, &gh_len); + geneve_sk_gro_hint_off(sk, gh, &type, &gh_len); + + /* Bail out if we are about to dispatch past the inner network header + * gro_receive() validated. An inner VLAN tag only pushes + * inner_network_offset out, so use a lower bound. + */ + if (skb->encapsulation) { + unsigned int inner_nh = nhoff + gh_len; + + if (type == htons(ETH_P_TEB)) + inner_nh += ETH_HLEN; + + if (unlikely(inner_nh > NAPI_GRO_CB(skb)->inner_network_offset)) + return -EINVAL; + } /* since skb->encapsulation is set, eth_gro_complete() sets the inner mac header */ if (likely(type == htons(ETH_P_TEB))) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index ed4178155a5d..01af4f9cf7f2 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -595,7 +595,7 @@ static int ca8210_test_int_driver_write( fifo_buffer = kmemdup(buf, len, GFP_KERNEL); if (!fifo_buffer) return -ENOMEM; - kfifo_in(&test->up_fifo, &fifo_buffer, 4); + kfifo_in(&test->up_fifo, &fifo_buffer, sizeof(fifo_buffer)); wake_up_interruptible(&priv->test.readq); return 0; @@ -919,9 +919,10 @@ static int ca8210_spi_transfer( if (status < 0) { dev_crit( &spi->dev, - "status %d from spi_sync in write\n", + "status %d from spi_async in write\n", status ); + kfree(cas_ctl); } return status; @@ -2525,6 +2526,7 @@ static ssize_t ca8210_test_int_user_read( struct ca8210_priv *priv = filp->private_data; unsigned char *fifo_buffer; unsigned long bytes_not_copied; + unsigned int copied; if (filp->f_flags & O_NONBLOCK) { /* Non-blocking mode */ @@ -2538,7 +2540,8 @@ static ssize_t ca8210_test_int_user_read( ); } - if (kfifo_out(&priv->test.up_fifo, &fifo_buffer, 4) != 4) { + copied = kfifo_out(&priv->test.up_fifo, &fifo_buffer, sizeof(fifo_buffer)); + if (copied != sizeof(fifo_buffer)) { dev_err( &priv->spi->dev, "test_interface: Wrong number of elements popped from upstream fifo\n" diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index a159cb293981..862001d09aa8 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -190,8 +190,10 @@ struct netconsole_target { bool extended; bool release; struct netpoll np; - /* protected by target_list_lock */ - char buf[MAX_PRINT_CHUNK]; + /* protected by target_list_lock; +1 gives scnprintf() room for its + * NUL terminator so a full MAX_PRINT_CHUNK payload is not truncated + */ + char buf[MAX_PRINT_CHUNK + 1]; struct work_struct resume_wq; }; @@ -1938,7 +1940,7 @@ static void send_msg_no_fragmentation(struct netconsole_target *nt, if (release_len) { release = init_utsname()->release; - scnprintf(nt->buf, MAX_PRINT_CHUNK, "%s,%.*s", release, + scnprintf(nt->buf, sizeof(nt->buf), "%s,%.*s", release, msg_len, msg); msg_len += release_len; } else { @@ -1947,12 +1949,12 @@ static void send_msg_no_fragmentation(struct netconsole_target *nt, if (userdata) msg_len += scnprintf(&nt->buf[msg_len], - MAX_PRINT_CHUNK - msg_len, "%s", + sizeof(nt->buf) - msg_len, "%s", userdata); if (sysdata) msg_len += scnprintf(&nt->buf[msg_len], - MAX_PRINT_CHUNK - msg_len, "%s", + sizeof(nt->buf) - msg_len, "%s", sysdata); send_udp(nt, nt->buf, msg_len); diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c index 27268811f564..b65d0f5fa1a0 100644 --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c @@ -1802,7 +1802,8 @@ static int rtl822x_config_aneg(struct phy_device *phydev) ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL_MDIO_AN_10GBT_CTRL, MDIO_AN_10GBT_CTRL_ADV2_5G | - MDIO_AN_10GBT_CTRL_ADV5G, adv); + MDIO_AN_10GBT_CTRL_ADV5G | + MDIO_AN_10GBT_CTRL_ADV10G, adv); if (ret < 0) return ret; } diff --git a/drivers/net/pse-pd/pd692x0.c b/drivers/net/pse-pd/pd692x0.c index cb377d5ba7af..209de9cec849 100644 --- a/drivers/net/pse-pd/pd692x0.c +++ b/drivers/net/pse-pd/pd692x0.c @@ -200,7 +200,7 @@ static const struct pd692x0_msg pd692x0_msg_template_list[PD692X0_MSG_CNT] = { }, [PD692X0_MSG_SET_USER_BYTE] = { .key = PD692X0_KEY_PRG, - .sub = {0x41, PD692X0_USER_BYTE}, + .sub = {0x41, PD692X0_USER_BYTE, 0x4e}, .data = {0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e}, }, diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c index f8f97e8e2226..02a91650561a 100644 --- a/drivers/net/thunderbolt/main.c +++ b/drivers/net/thunderbolt/main.c @@ -783,8 +783,12 @@ static bool tbnet_check_frame(struct tbnet *net, const struct tbnet_frame *tf, return true; } - /* Start of packet, validate the frame header */ - if (frame_count == 0 || frame_count > TBNET_RING_SIZE / 4) { + /* Start of packet, validate the frame header. tbnet_poll() puts the + * first frame in the skb linear area and every further frame in a page + * fragment, so a packet may not span more than MAX_SKB_FRAGS + 1 frames + * without overflowing skb_shinfo()->frags[]. + */ + if (frame_count == 0 || frame_count > MAX_SKB_FRAGS + 1) { net->stats.rx_length_errors++; return false; } diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c index ee9c48f7f68f..0dd0a30c3db4 100644 --- a/drivers/net/usb/kalmia.c +++ b/drivers/net/usb/kalmia.c @@ -276,6 +276,14 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) "Received header: %6phC. Package length: %i\n", header_start, skb->len - KALMIA_HEADER_LENGTH); + /* both framing headers must be present before we subtract + * them, otherwise usb_packet_length underflows and the + * device-supplied ether_packet_length drives an out of bounds + * access below + */ + if (skb->len < 2 * KALMIA_HEADER_LENGTH) + return 0; + /* subtract start header and end header */ usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH); ether_packet_length = get_unaligned_le16(&header_start[2]); diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index bcf293ea1bd3..c4cebacabcb5 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1452,6 +1452,15 @@ static inline u32 lan78xx_hash(char addr[ETH_ALEN]) return (ether_crc(ETH_ALEN, addr) >> 23) & 0x1ff; } +static int lan78xx_write_mchash_table(struct lan78xx_net *dev) +{ + struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); + + return lan78xx_dataport_write(dev, DP_SEL_RSEL_VLAN_DA_, + DP_SEL_VHF_VLAN_LEN, + DP_SEL_VHF_HASH_LEN, pdata->mchash_table); +} + static void lan78xx_deferred_multicast_write(struct work_struct *param) { struct lan78xx_priv *pdata = @@ -1462,9 +1471,7 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param) netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n", pdata->rfe_ctl); - ret = lan78xx_dataport_write(dev, DP_SEL_RSEL_VLAN_DA_, - DP_SEL_VHF_VLAN_LEN, - DP_SEL_VHF_HASH_LEN, pdata->mchash_table); + ret = lan78xx_write_mchash_table(dev); if (ret < 0) goto multicast_write_done; @@ -1557,6 +1564,7 @@ static void lan78xx_set_multicast(struct net_device *netdev) } static void lan78xx_rx_urb_submit_all(struct lan78xx_net *dev); +static int lan78xx_write_vlan_table(struct lan78xx_net *dev); static int lan78xx_mac_reset(struct lan78xx_net *dev) { @@ -2514,6 +2522,17 @@ static void lan78xx_mac_link_up(struct phylink_config *config, if (ret < 0) goto link_up_fail; + /* The RFE clears the VLAN/DA hash filter (VHF) on a link down/up + * cycle, so reprogram both tables from their shadow copies. + */ + ret = lan78xx_write_vlan_table(dev); + if (ret < 0) + goto link_up_fail; + + ret = lan78xx_write_mchash_table(dev); + if (ret < 0) + goto link_up_fail; + netif_start_queue(net); return; @@ -3065,14 +3084,20 @@ static int lan78xx_set_features(struct net_device *netdev, return lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); } +static int lan78xx_write_vlan_table(struct lan78xx_net *dev) +{ + struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); + + return lan78xx_dataport_write(dev, DP_SEL_RSEL_VLAN_DA_, 0, + DP_SEL_VHF_VLAN_LEN, pdata->vlan_table); +} + static void lan78xx_deferred_vlan_write(struct work_struct *param) { struct lan78xx_priv *pdata = container_of(param, struct lan78xx_priv, set_vlan); - struct lan78xx_net *dev = pdata->dev; - lan78xx_dataport_write(dev, DP_SEL_RSEL_VLAN_DA_, 0, - DP_SEL_VHF_VLAN_LEN, pdata->vlan_table); + lan78xx_write_vlan_table(pdata->dev); } static int lan78xx_vlan_rx_add_vid(struct net_device *netdev, diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 0cfb19b760dd..1c5142149175 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1137,6 +1137,8 @@ static int veth_enable_xdp_range(struct net_device *dev, int start, int end, err_reg_mem: xdp_rxq_info_unreg(&priv->rq[i].xdp_rxq); err_rxq_reg: + if (!napi_already_on) + netif_napi_del(&priv->rq[i].xdp_napi); for (i--; i >= start; i--) { struct veth_rq *rq = &priv->rq[i]; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 7d2eeb9b1226..26afa6341d16 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1999,15 +1999,18 @@ static struct sk_buff *receive_big(struct net_device *dev, struct virtnet_rq_stats *stats) { struct page *page = buf; + unsigned long max_len; struct sk_buff *skb; + max_len = (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE - + sizeof(struct padded_vnet_hdr) + vi->hdr_len; + /* Make sure that len does not exceed the size allocated in * add_recvbuf_big. */ - if (unlikely(len > (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE)) { + if (unlikely(len > max_len)) { pr_debug("%s: rx error: len %u exceeds allocated size %lu\n", - dev->name, len, - (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE); + dev->name, len, max_len); goto err; } diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 159295c4bd6d..302ed27944e7 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -619,7 +619,6 @@ static void ppp_start(struct net_device *dev) struct proto *proto = &ppp->protos[i]; proto->dev = dev; - timer_setup(&proto->timer, ppp_timer, 0); proto->state = CLOSED; } ppp->protos[IDX_LCP].pid = PID_LCP; @@ -639,6 +638,15 @@ static void ppp_close(struct net_device *dev) ppp_tx_flush(); } +static void ppp_timer_release(struct net_device *dev) +{ + struct ppp *ppp = get_ppp(dev); + int i; + + for (i = 0; i < IDX_COUNT; i++) + timer_shutdown_sync(&ppp->protos[i].timer); +} + static struct hdlc_proto proto = { .start = ppp_start, .stop = ppp_stop, @@ -647,6 +655,7 @@ static struct hdlc_proto proto = { .ioctl = ppp_ioctl, .netif_rx = ppp_rx, .module = THIS_MODULE, + .detach = ppp_timer_release, }; static const struct header_ops ppp_header_ops = { @@ -657,7 +666,7 @@ static int ppp_ioctl(struct net_device *dev, struct if_settings *ifs) { hdlc_device *hdlc = dev_to_hdlc(dev); struct ppp *ppp; - int result; + int i, result; switch (ifs->type) { case IF_GET_PROTO: @@ -685,6 +694,8 @@ static int ppp_ioctl(struct net_device *dev, struct if_settings *ifs) return result; ppp = get_ppp(dev); + for (i = 0; i < IDX_COUNT; i++) + timer_setup(&ppp->protos[i].timer, ppp_timer, 0); spin_lock_init(&ppp->lock); ppp->req_timeout = 2; ppp->cr_retries = 10; diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 720c5dc889ea..7f4645ff90aa 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -1487,11 +1487,11 @@ static int ixp4xx_hss_probe(struct platform_device *pdev) "unable to get CLK internal GPIO\n"); ndev = alloc_hdlcdev(port); - port->netdev = alloc_hdlcdev(port); - if (!port->netdev) { + if (!ndev) { err = -ENOMEM; goto err_plat; } + port->netdev = ndev; SET_NETDEV_DEV(ndev, &pdev->dev); hdlc = dev_to_hdlc(ndev); diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c index e10cb4f9104e..2917cee9b802 100644 --- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c +++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c @@ -1063,6 +1063,9 @@ err_free_tx_ring: while (i--) t7xx_cldma_ring_free(md_ctrl, &md_ctrl->tx_ring[i], DMA_TO_DEVICE); + dma_pool_destroy(md_ctrl->gpd_dmapool); + md_ctrl->gpd_dmapool = NULL; + return ret; } |
