1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-11 17:10:13 +00:00

Including fixes from Bluetooth and WiFi. Notably this includes the fix

for the iwlwifi issue you reported.
 
 Current release - regressions:
 
   - core: avoid prefetching NULL pointers
 
   - wifi:
     - iwlwifi: implement settime64 as stub for MVM/MLD PTP
     - mac80211: fix list iteration in ieee80211_add_virtual_monitor()
 
   - handshake: fix null-ptr-deref in handshake_complete()
 
   - eth: mana: fix use-after-free in reset service rescan path
 
 Previous releases - regressions:
 
   - openvswitch: avoid needlessly taking the RTNL on vport destroy
 
   - dsa: properly keep track of conduit reference
 
   - ipv4:
     - fix reference count leak when using error routes with nexthop objects
     - fib: restore ECMP balance from loopback
 
   - mptcp: ensure context reset on disconnect()
 
   - bluetooth: fix potential UaF in btusb
 
   - nfc: fix deadlock between nfc_unregister_device and rfkill_fop_write
 
   - eth: gve: defer interrupt enabling until NAPI registration
 
   - eth: i40e: fix scheduling in set_rx_mode
 
   - eth: macb: relocate mog_init_rings() callback from macb_mac_link_up() to macb_open()
 
   - eth: rtl8150: fix memory leak on usb_submit_urb() failure
 
   - wifi: 8192cu: fix tid out of range in rtl92cu_tx_fill_desc()
 
 Previous releases - always broken:
 
   - ip6_gre: make ip6gre_header() robust
 
   - ipv6: fix a BUG in rt6_get_pcpu_route() under PREEMPT_RT
 
   - af_unix: don't post cmsg for SO_INQ unless explicitly asked for
 
   - phy: mediatek: fix nvmem cell reference leak in mt798x_phy_calibration
 
   - wifi: mac80211: discard beacon frames to non-broadcast address
 
   - eth: iavf: fix off-by-one issues in iavf_config_rss_reg()
 
   - eth: stmmac: fix the crash issue for zero copy XDP_TX action
 
   - eth: team: fix check for port enabled in team_queue_override_port_prio_changed()
 
 Signed-off-by: Paolo Abeni <pabeni@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCgAwFiEEg1AjqC77wbdLX2LbKSR5jcyPE6QFAmlT43wSHHBhYmVuaUBy
 ZWRoYXQuY29tAAoJECkkeY3MjxOkHhMP/jF3B8c3djMgpYpEwPRgqJlzdpBGQvcO
 UsN/8fYI/XowIcU6T/yC/KM5cABCWyfnj6yZe743wPrlj8DnWK7+Fezrfwx7l8e0
 0LH9kVwOIaQXg/QthtXaDHNB/9OanDtgcpitI209gENRjF81bYWCehImil6jbVnn
 DUnVmfZIQ6k3dFsAPC4W7uJdA2FORtQzEZ1dZ13Ivx9jmbazK81ptUbIMAAnyfIZ
 rUhv+UqaDIlflYwuay58ZPdu8no4nQlJMPiPybXiizfTVStEne9SQKOacP8j7XL0
 GSjEyDO8lJXCPVSVnGEyybBH50M0myGUSH73+56o2QRRLtrHLDfieOL/N8AarNDh
 7U2g9pq0+IFPuJsm9SFR14dIpUAvpKohc57ZvsmworC8NuENzl6H3b6/U4n/1oNE
 JCbcitl91GkyF0Bvyac5a9wfk8SsYEJEGLPrtNX8UwH0UJh8spkfoQq5oHkC3juQ
 77n//eOFSz8oPDlV7ayNv+W3CEzOW09mSYFu8bdjBKC5HeyBJsm3HnJdaAhSqNEH
 6duRvcMlUJQ0JPILJoS1Zoy166uIu8hs2mZtygcAzyacia8yckL+Oq2UCYMi2oKP
 psOIzfd6G/+f203w37jdSY0OVlQSHvmCFSeaY6FHs2LEApDrNWK1cMLYO+lMU8EE
 q0j2SmDNMHhM
 =P1hX
 -----END PGP SIGNATURE-----

Merge tag 'net-6.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull networking fixes from Paolo Abeni:
 "Including fixes from Bluetooth and WiFi. Notably this includes the fix
  for the iwlwifi issue you reported.

  Current release - regressions:

   - core: avoid prefetching NULL pointers

   - wifi:
      - iwlwifi: implement settime64 as stub for MVM/MLD PTP
      - mac80211: fix list iteration in ieee80211_add_virtual_monitor()

   - handshake: fix null-ptr-deref in handshake_complete()

   - eth: mana: fix use-after-free in reset service rescan path

  Previous releases - regressions:

   - openvswitch: avoid needlessly taking the RTNL on vport destroy

   - dsa: properly keep track of conduit reference

   - ipv4:
      - fix error route reference count leak with nexthop objects
      - fib: restore ECMP balance from loopback

   - mptcp: ensure context reset on disconnect()

   - bluetooth: fix potential UaF in btusb

   - nfc: fix deadlock between nfc_unregister_device and
     rfkill_fop_write

   - eth:
      - gve: defer interrupt enabling until NAPI registration
      - i40e: fix scheduling in set_rx_mode
      - macb: relocate mog_init_rings() callback from macb_mac_link_up()
        to macb_open()
      - rtl8150: fix memory leak on usb_submit_urb() failure

   - wifi: 8192cu: fix tid out of range in rtl92cu_tx_fill_desc()

  Previous releases - always broken:

   - ip6_gre: make ip6gre_header() robust

   - ipv6: fix a BUG in rt6_get_pcpu_route() under PREEMPT_RT

   - af_unix: don't post cmsg for SO_INQ unless explicitly asked for

   - phy: mediatek: fix nvmem cell reference leak in
     mt798x_phy_calibration

   - wifi: mac80211: discard beacon frames to non-broadcast address

   - eth:
      - iavf: fix off-by-one issues in iavf_config_rss_reg()
      - stmmac: fix the crash issue for zero copy XDP_TX action
      - team: fix check for port enabled when priority changes"

* tag 'net-6.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (64 commits)
  ipv6: fix a BUG in rt6_get_pcpu_route() under PREEMPT_RT
  net: rose: fix invalid array index in rose_kill_by_device()
  net: enetc: do not print error log if addr is 0
  net: macb: Relocate mog_init_rings() callback from macb_mac_link_up() to macb_open()
  selftests: fib_test: Add test case for ipv4 multi nexthops
  net: fib: restore ECMP balance from loopback
  selftests: fib_nexthops: Add test cases for error routes deletion
  ipv4: Fix reference count leak when using error routes with nexthop objects
  net: usb: sr9700: fix incorrect command used to write single register
  ipv6: BUG() in pskb_expand_head() as part of calipso_skbuff_setattr()
  usbnet: avoid a possible crash in dql_completed()
  gve: defer interrupt enabling until NAPI registration
  net: stmmac: fix the crash issue for zero copy XDP_TX action
  octeontx2-pf: fix "UBSAN: shift-out-of-bounds error"
  af_unix: don't post cmsg for SO_INQ unless explicitly asked for
  net: mana: Fix use-after-free in reset service rescan path
  net: avoid prefetching NULL pointers
  net: bridge: Describe @tunnel_hash member in net_bridge_vlan_group struct
  net: nfc: fix deadlock between nfc_unregister_device and rfkill_fop_write
  net: usb: asix: validate PHY address before use
  ...
This commit is contained in:
Linus Torvalds 2025-12-30 08:45:58 -08:00
commit dbf8fe85a1
71 changed files with 428 additions and 194 deletions

View File

@ -4052,7 +4052,7 @@ static int btusb_probe(struct usb_interface *intf,
return -ENODEV; return -ENODEV;
} }
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
@ -4075,8 +4075,10 @@ static int btusb_probe(struct usb_interface *intf,
} }
} }
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
kfree(data);
return -ENODEV; return -ENODEV;
}
if (id->driver_info & BTUSB_AMP) { if (id->driver_info & BTUSB_AMP) {
data->cmdreq_type = USB_TYPE_CLASS | 0x01; data->cmdreq_type = USB_TYPE_CLASS | 0x01;
@ -4131,8 +4133,10 @@ static int btusb_probe(struct usb_interface *intf,
data->recv_acl = hci_recv_frame; data->recv_acl = hci_recv_frame;
hdev = hci_alloc_dev_priv(priv_size); hdev = hci_alloc_dev_priv(priv_size);
if (!hdev) if (!hdev) {
kfree(data);
return -ENOMEM; return -ENOMEM;
}
hdev->bus = HCI_USB; hdev->bus = HCI_USB;
hci_set_drvdata(hdev, data); hci_set_drvdata(hdev, data);
@ -4406,6 +4410,7 @@ out_free_dev:
if (data->reset_gpio) if (data->reset_gpio)
gpiod_put(data->reset_gpio); gpiod_put(data->reset_gpio);
hci_free_dev(hdev); hci_free_dev(hdev);
kfree(data);
return err; return err;
} }
@ -4454,6 +4459,7 @@ static void btusb_disconnect(struct usb_interface *intf)
} }
hci_free_dev(hdev); hci_free_dev(hdev);
kfree(data);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM

View File

@ -2169,6 +2169,9 @@ static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
if (!ent->is_valid) if (!ent->is_valid)
return 0; return 0;
if (is_multicast_ether_addr(ent->mac))
return 0;
if (port != ent->port) if (port != ent->port)
return 0; return 0;

View File

@ -2924,19 +2924,26 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
port->id = id; port->id = id;
eth->ports[p] = port; eth->ports[p] = port;
err = airoha_metadata_dst_alloc(port); return airoha_metadata_dst_alloc(port);
if (err) }
return err;
err = register_netdev(dev); static int airoha_register_gdm_devices(struct airoha_eth *eth)
if (err) {
goto free_metadata_dst; int i;
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
int err;
if (!port)
continue;
err = register_netdev(port->dev);
if (err)
return err;
}
return 0; return 0;
free_metadata_dst:
airoha_metadata_dst_free(port);
return err;
} }
static int airoha_probe(struct platform_device *pdev) static int airoha_probe(struct platform_device *pdev)
@ -3027,6 +3034,10 @@ static int airoha_probe(struct platform_device *pdev)
} }
} }
err = airoha_register_gdm_devices(eth);
if (err)
goto error_napi_stop;
return 0; return 0;
error_napi_stop: error_napi_stop:
@ -3040,10 +3051,12 @@ error_hw_cleanup:
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i]; struct airoha_gdm_port *port = eth->ports[i];
if (port && port->dev->reg_state == NETREG_REGISTERED) { if (!port)
continue;
if (port->dev->reg_state == NETREG_REGISTERED)
unregister_netdev(port->dev); unregister_netdev(port->dev);
airoha_metadata_dst_free(port); airoha_metadata_dst_free(port);
}
} }
free_netdev(eth->napi_dev); free_netdev(eth->napi_dev);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);

View File

@ -1928,6 +1928,7 @@ static void xgbe_set_rx_adap_mode(struct xgbe_prv_data *pdata,
{ {
if (pdata->rx_adapt_retries++ >= MAX_RX_ADAPT_RETRIES) { if (pdata->rx_adapt_retries++ >= MAX_RX_ADAPT_RETRIES) {
pdata->rx_adapt_retries = 0; pdata->rx_adapt_retries = 0;
pdata->mode_set = false;
return; return;
} }
@ -1974,6 +1975,7 @@ static void xgbe_rx_adaptation(struct xgbe_prv_data *pdata)
*/ */
netif_dbg(pdata, link, pdata->netdev, "Block_lock done"); netif_dbg(pdata, link, pdata->netdev, "Block_lock done");
pdata->rx_adapt_done = true; pdata->rx_adapt_done = true;
pdata->rx_adapt_retries = 0;
pdata->mode_set = false; pdata->mode_set = false;
return; return;
} }

View File

@ -255,14 +255,14 @@ config BNXT_HWMON
devices, via the hwmon sysfs interface. devices, via the hwmon sysfs interface.
config BNGE config BNGE
tristate "Broadcom Ethernet device support" tristate "Broadcom ThorUltra Ethernet device support"
depends on PCI depends on PCI
select NET_DEVLINK select NET_DEVLINK
select PAGE_POOL select PAGE_POOL
help help
This driver supports Broadcom 50/100/200/400/800 gigabit Ethernet cards. This driver supports Broadcom ThorUltra 50/100/200/400/800 gigabit
The module will be called bng_en. To compile this driver as a module, Ethernet cards. The module will be called bng_en. To compile this
choose M here. driver as a module, choose M here.
config BCMASP config BCMASP
tristate "Broadcom ASP 2.0 Ethernet support" tristate "Broadcom ASP 2.0 Ethernet support"

View File

@ -5,7 +5,7 @@
#define _BNGE_H_ #define _BNGE_H_
#define DRV_NAME "bng_en" #define DRV_NAME "bng_en"
#define DRV_SUMMARY "Broadcom 800G Ethernet Linux Driver" #define DRV_SUMMARY "Broadcom ThorUltra NIC Ethernet Driver"
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/bnxt/hsi.h> #include <linux/bnxt/hsi.h>

View File

@ -19,7 +19,7 @@ char bnge_driver_name[] = DRV_NAME;
static const struct { static const struct {
char *name; char *name;
} board_info[] = { } board_info[] = {
[BCM57708] = { "Broadcom BCM57708 50Gb/100Gb/200Gb/400Gb/800Gb Ethernet" }, [BCM57708] = { "Broadcom BCM57708 ThorUltra 50Gb/100Gb/200Gb/400Gb/800Gb Ethernet" },
}; };
static const struct pci_device_id bnge_pci_tbl[] = { static const struct pci_device_id bnge_pci_tbl[] = {

View File

@ -708,7 +708,6 @@ static void macb_mac_link_up(struct phylink_config *config,
/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
* cleared the pipeline and control registers. * cleared the pipeline and control registers.
*/ */
bp->macbgem_ops.mog_init_rings(bp);
macb_init_buffers(bp); macb_init_buffers(bp);
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
@ -2954,6 +2953,8 @@ static int macb_open(struct net_device *dev)
goto pm_exit; goto pm_exit;
} }
bp->macbgem_ops.mog_init_rings(bp);
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
napi_enable(&queue->napi_rx); napi_enable(&queue->napi_rx);
napi_enable(&queue->napi_tx); napi_enable(&queue->napi_tx);

View File

@ -577,11 +577,17 @@ static int imx94_enetc_mdio_phyaddr_config(struct netc_blk_ctrl *priv,
} }
addr = netc_get_phy_addr(np); addr = netc_get_phy_addr(np);
if (addr <= 0) { if (addr < 0) {
dev_err(dev, "Failed to get PHY address\n"); dev_err(dev, "Failed to get PHY address\n");
return addr; return addr;
} }
/* The default value of LaBCR[MDIO_PHYAD_PRTAD] is 0,
* so no need to set the register.
*/
if (!addr)
return 0;
if (phy_mask & BIT(addr)) { if (phy_mask & BIT(addr)) {
dev_err(dev, dev_err(dev,
"Find same PHY address in EMDIO and ENETC node\n"); "Find same PHY address in EMDIO and ENETC node\n");

View File

@ -558,7 +558,7 @@ static int gve_alloc_notify_blocks(struct gve_priv *priv)
block->priv = priv; block->priv = priv;
err = request_irq(priv->msix_vectors[msix_idx].vector, err = request_irq(priv->msix_vectors[msix_idx].vector,
gve_is_gqi(priv) ? gve_intr : gve_intr_dqo, gve_is_gqi(priv) ? gve_intr : gve_intr_dqo,
0, block->name, block); IRQF_NO_AUTOEN, block->name, block);
if (err) { if (err) {
dev_err(&priv->pdev->dev, dev_err(&priv->pdev->dev,
"Failed to receive msix vector %d\n", i); "Failed to receive msix vector %d\n", i);

View File

@ -112,11 +112,13 @@ void gve_add_napi(struct gve_priv *priv, int ntfy_idx,
netif_napi_add_locked(priv->dev, &block->napi, gve_poll); netif_napi_add_locked(priv->dev, &block->napi, gve_poll);
netif_napi_set_irq_locked(&block->napi, block->irq); netif_napi_set_irq_locked(&block->napi, block->irq);
enable_irq(block->irq);
} }
void gve_remove_napi(struct gve_priv *priv, int ntfy_idx) void gve_remove_napi(struct gve_priv *priv, int ntfy_idx)
{ {
struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx]; struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
disable_irq(block->irq);
netif_napi_del_locked(&block->napi); netif_napi_del_locked(&block->napi);
} }

View File

@ -4094,7 +4094,15 @@ static bool e1000_tbi_should_accept(struct e1000_adapter *adapter,
u32 length, const u8 *data) u32 length, const u8 *data)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u8 last_byte = *(data + length - 1); u8 last_byte;
/* Guard against OOB on data[length - 1] */
if (unlikely(!length))
return false;
/* Upper bound: length must not exceed rx_buffer_len */
if (unlikely(length > adapter->rx_buffer_len))
return false;
last_byte = *(data + length - 1);
if (TBI_ACCEPT(hw, status, errors, length, last_byte)) { if (TBI_ACCEPT(hw, status, errors, length, last_byte)) {
unsigned long irq_flags; unsigned long irq_flags;

View File

@ -1422,4 +1422,15 @@ static inline struct i40e_veb *i40e_pf_get_main_veb(struct i40e_pf *pf)
return (pf->lan_veb != I40E_NO_VEB) ? pf->veb[pf->lan_veb] : NULL; return (pf->lan_veb != I40E_NO_VEB) ? pf->veb[pf->lan_veb] : NULL;
} }
static inline u32 i40e_get_max_num_descriptors(const struct i40e_pf *pf)
{
const struct i40e_hw *hw = &pf->hw;
switch (hw->mac.type) {
case I40E_MAC_XL710:
return I40E_MAX_NUM_DESCRIPTORS_XL710;
default:
return I40E_MAX_NUM_DESCRIPTORS;
}
}
#endif /* _I40E_H_ */ #endif /* _I40E_H_ */

View File

@ -2013,18 +2013,6 @@ static void i40e_get_drvinfo(struct net_device *netdev,
drvinfo->n_priv_flags += I40E_GL_PRIV_FLAGS_STR_LEN; drvinfo->n_priv_flags += I40E_GL_PRIV_FLAGS_STR_LEN;
} }
static u32 i40e_get_max_num_descriptors(struct i40e_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
switch (hw->mac.type) {
case I40E_MAC_XL710:
return I40E_MAX_NUM_DESCRIPTORS_XL710;
default:
return I40E_MAX_NUM_DESCRIPTORS;
}
}
static void i40e_get_ringparam(struct net_device *netdev, static void i40e_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring, struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring, struct kernel_ethtool_ringparam *kernel_ring,

View File

@ -2234,6 +2234,7 @@ static void i40e_set_rx_mode(struct net_device *netdev)
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
set_bit(__I40E_MACVLAN_SYNC_PENDING, vsi->back->state); set_bit(__I40E_MACVLAN_SYNC_PENDING, vsi->back->state);
} }
i40e_service_event_schedule(vsi->back);
} }
/** /**

View File

@ -656,7 +656,7 @@ static int i40e_config_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_id,
/* ring_len has to be multiple of 8 */ /* ring_len has to be multiple of 8 */
if (!IS_ALIGNED(info->ring_len, 8) || if (!IS_ALIGNED(info->ring_len, 8) ||
info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) { info->ring_len > i40e_get_max_num_descriptors(pf)) {
ret = -EINVAL; ret = -EINVAL;
goto error_context; goto error_context;
} }
@ -726,7 +726,7 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id,
/* ring_len has to be multiple of 32 */ /* ring_len has to be multiple of 32 */
if (!IS_ALIGNED(info->ring_len, 32) || if (!IS_ALIGNED(info->ring_len, 32) ||
info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) { info->ring_len > i40e_get_max_num_descriptors(pf)) {
ret = -EINVAL; ret = -EINVAL;
goto error_param; goto error_param;
} }

View File

@ -1726,11 +1726,11 @@ static int iavf_config_rss_reg(struct iavf_adapter *adapter)
u16 i; u16 i;
dw = (u32 *)adapter->rss_key; dw = (u32 *)adapter->rss_key;
for (i = 0; i <= adapter->rss_key_size / 4; i++) for (i = 0; i < adapter->rss_key_size / 4; i++)
wr32(hw, IAVF_VFQF_HKEY(i), dw[i]); wr32(hw, IAVF_VFQF_HKEY(i), dw[i]);
dw = (u32 *)adapter->rss_lut; dw = (u32 *)adapter->rss_lut;
for (i = 0; i <= adapter->rss_lut_size / 4; i++) for (i = 0; i < adapter->rss_lut_size / 4; i++)
wr32(hw, IAVF_VFQF_HLUT(i), dw[i]); wr32(hw, IAVF_VFQF_HLUT(i), dw[i]);
iavf_flush(hw); iavf_flush(hw);

View File

@ -1271,7 +1271,7 @@ void idpf_mbx_task(struct work_struct *work)
idpf_mb_irq_enable(adapter); idpf_mb_irq_enable(adapter);
else else
queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task,
msecs_to_jiffies(300)); usecs_to_jiffies(300));
idpf_recv_mb_msg(adapter); idpf_recv_mb_msg(adapter);
} }

View File

@ -1016,6 +1016,9 @@ static int idpf_send_get_lan_memory_regions(struct idpf_adapter *adapter)
struct idpf_vc_xn_params xn_params = { struct idpf_vc_xn_params xn_params = {
.vc_op = VIRTCHNL2_OP_GET_LAN_MEMORY_REGIONS, .vc_op = VIRTCHNL2_OP_GET_LAN_MEMORY_REGIONS,
.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN, .recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN,
.send_buf.iov_len =
sizeof(struct virtchnl2_get_lan_memory_regions) +
sizeof(struct virtchnl2_mem_region),
.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC, .timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC,
}; };
int num_regions, size; int num_regions, size;
@ -1028,6 +1031,8 @@ static int idpf_send_get_lan_memory_regions(struct idpf_adapter *adapter)
return -ENOMEM; return -ENOMEM;
xn_params.recv_buf.iov_base = rcvd_regions; xn_params.recv_buf.iov_base = rcvd_regions;
rcvd_regions->num_memory_regions = cpu_to_le16(1);
xn_params.send_buf.iov_base = rcvd_regions;
reply_sz = idpf_vc_xn_exec(adapter, &xn_params); reply_sz = idpf_vc_xn_exec(adapter, &xn_params);
if (reply_sz < 0) if (reply_sz < 0)
return reply_sz; return reply_sz;

View File

@ -418,6 +418,14 @@ static int otx2_set_ringparam(struct net_device *netdev,
*/ */
if (rx_count < pfvf->hw.rq_skid) if (rx_count < pfvf->hw.rq_skid)
rx_count = pfvf->hw.rq_skid; rx_count = pfvf->hw.rq_skid;
if (ring->rx_pending < 16) {
netdev_err(netdev,
"rx ring size %u invalid, min is 16\n",
ring->rx_pending);
return -EINVAL;
}
rx_count = Q_COUNT(Q_SIZE(rx_count, 3)); rx_count = Q_COUNT(Q_SIZE(rx_count, 3));
/* Due pipelining impact minimum 2000 unused SQ CQE's /* Due pipelining impact minimum 2000 unused SQ CQE's

View File

@ -481,7 +481,7 @@ static void mana_serv_reset(struct pci_dev *pdev)
/* Perform PCI rescan on device if we failed on HWC */ /* Perform PCI rescan on device if we failed on HWC */
dev_err(&pdev->dev, "MANA service: resume failed, rescanning\n"); dev_err(&pdev->dev, "MANA service: resume failed, rescanning\n");
mana_serv_rescan(pdev); mana_serv_rescan(pdev);
goto out; return;
} }
if (ret) if (ret)

View File

@ -516,15 +516,7 @@ static inline void smc_rcv(struct net_device *dev)
* any other concurrent access and C would always interrupt B. But life * any other concurrent access and C would always interrupt B. But life
* isn't that easy in a SMP world... * isn't that easy in a SMP world...
*/ */
#define smc_special_trylock(lock, flags) \ #define smc_special_trylock(lock, flags) spin_trylock_irqsave(lock, flags)
({ \
int __ret; \
local_irq_save(flags); \
__ret = spin_trylock(lock); \
if (!__ret) \
local_irq_restore(flags); \
__ret; \
})
#define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags) #define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags)
#define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags) #define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags)
#else #else

View File

@ -89,6 +89,7 @@ MODULE_PARM_DESC(phyaddr, "Physical device address");
#define STMMAC_XDP_CONSUMED BIT(0) #define STMMAC_XDP_CONSUMED BIT(0)
#define STMMAC_XDP_TX BIT(1) #define STMMAC_XDP_TX BIT(1)
#define STMMAC_XDP_REDIRECT BIT(2) #define STMMAC_XDP_REDIRECT BIT(2)
#define STMMAC_XSK_CONSUMED BIT(3)
static int flow_ctrl = 0xdead; static int flow_ctrl = 0xdead;
module_param(flow_ctrl, int, 0644); module_param(flow_ctrl, int, 0644);
@ -5126,6 +5127,7 @@ static int stmmac_xdp_get_tx_queue(struct stmmac_priv *priv,
static int stmmac_xdp_xmit_back(struct stmmac_priv *priv, static int stmmac_xdp_xmit_back(struct stmmac_priv *priv,
struct xdp_buff *xdp) struct xdp_buff *xdp)
{ {
bool zc = !!(xdp->rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL);
struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp);
int cpu = smp_processor_id(); int cpu = smp_processor_id();
struct netdev_queue *nq; struct netdev_queue *nq;
@ -5142,9 +5144,18 @@ static int stmmac_xdp_xmit_back(struct stmmac_priv *priv,
/* Avoids TX time-out as we are sharing with slow path */ /* Avoids TX time-out as we are sharing with slow path */
txq_trans_cond_update(nq); txq_trans_cond_update(nq);
res = stmmac_xdp_xmit_xdpf(priv, queue, xdpf, false); /* For zero copy XDP_TX action, dma_map is true */
if (res == STMMAC_XDP_TX) res = stmmac_xdp_xmit_xdpf(priv, queue, xdpf, zc);
if (res == STMMAC_XDP_TX) {
stmmac_flush_tx_descriptors(priv, queue); stmmac_flush_tx_descriptors(priv, queue);
} else if (res == STMMAC_XDP_CONSUMED && zc) {
/* xdp has been freed by xdp_convert_buff_to_frame(),
* no need to call xsk_buff_free() again, so return
* STMMAC_XSK_CONSUMED.
*/
res = STMMAC_XSK_CONSUMED;
xdp_return_frame(xdpf);
}
__netif_tx_unlock(nq); __netif_tx_unlock(nq);
@ -5494,6 +5505,8 @@ read_again:
break; break;
case STMMAC_XDP_CONSUMED: case STMMAC_XDP_CONSUMED:
xsk_buff_free(buf->xdp); xsk_buff_free(buf->xdp);
fallthrough;
case STMMAC_XSK_CONSUMED:
rx_dropped++; rx_dropped++;
break; break;
case STMMAC_XDP_TX: case STMMAC_XDP_TX:

View File

@ -21,6 +21,7 @@ config LIBWX
depends on PTP_1588_CLOCK_OPTIONAL depends on PTP_1588_CLOCK_OPTIONAL
select PAGE_POOL select PAGE_POOL
select DIMLIB select DIMLIB
select PHYLINK
help help
Common library for Wangxun(R) Ethernet drivers. Common library for Wangxun(R) Ethernet drivers.
@ -29,7 +30,6 @@ config NGBE
depends on PCI depends on PCI
depends on PTP_1588_CLOCK_OPTIONAL depends on PTP_1588_CLOCK_OPTIONAL
select LIBWX select LIBWX
select PHYLINK
help help
This driver supports Wangxun(R) GbE PCI Express family of This driver supports Wangxun(R) GbE PCI Express family of
adapters. adapters.
@ -48,7 +48,6 @@ config TXGBE
depends on PTP_1588_CLOCK_OPTIONAL depends on PTP_1588_CLOCK_OPTIONAL
select MARVELL_10G_PHY select MARVELL_10G_PHY
select REGMAP select REGMAP
select PHYLINK
select HWMON if TXGBE=y select HWMON if TXGBE=y
select SFP select SFP
select GPIOLIB select GPIOLIB
@ -71,7 +70,6 @@ config TXGBEVF
depends on PCI_MSI depends on PCI_MSI
depends on PTP_1588_CLOCK_OPTIONAL depends on PTP_1588_CLOCK_OPTIONAL
select LIBWX select LIBWX
select PHYLINK
help help
This driver supports virtual functions for SP1000A, WX1820AL, This driver supports virtual functions for SP1000A, WX1820AL,
WX5XXX, WX5XXXAL. WX5XXX, WX5XXXAL.

View File

@ -334,7 +334,7 @@ int fjes_hw_init(struct fjes_hw *hw)
ret = fjes_hw_reset(hw); ret = fjes_hw_reset(hw);
if (ret) if (ret)
return ret; goto err_iounmap;
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true); fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
@ -347,8 +347,10 @@ int fjes_hw_init(struct fjes_hw *hw)
hw->max_epid = fjes_hw_get_max_epid(hw); hw->max_epid = fjes_hw_get_max_epid(hw);
hw->my_epid = fjes_hw_get_my_epid(hw); hw->my_epid = fjes_hw_get_my_epid(hw);
if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid)) if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid)) {
return -ENXIO; ret = -ENXIO;
goto err_iounmap;
}
ret = fjes_hw_setup(hw); ret = fjes_hw_setup(hw);
@ -356,6 +358,10 @@ int fjes_hw_init(struct fjes_hw *hw)
hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE; hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
return ret; return ret;
err_iounmap:
fjes_hw_iounmap(hw);
return ret;
} }
void fjes_hw_exit(struct fjes_hw *hw) void fjes_hw_exit(struct fjes_hw *hw)

View File

@ -63,6 +63,13 @@ static int aspeed_mdio_op(struct mii_bus *bus, u8 st, u8 op, u8 phyad, u8 regad,
iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL); iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL);
/* Workaround for read-after-write issue.
* The controller may return stale data if a read follows immediately
* after a write. A dummy read forces the hardware to update its
* internal state, ensuring that the next real read returns correct data.
*/
ioread32(ctx->base + ASPEED_MDIO_CTRL);
return readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl, return readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl,
!(ctrl & ASPEED_MDIO_CTRL_FIRE), !(ctrl & ASPEED_MDIO_CTRL_FIRE),
ASPEED_MDIO_INTERVAL_US, ASPEED_MDIO_INTERVAL_US,

View File

@ -354,7 +354,6 @@ static int rtl9300_mdiobus_probe_one(struct device *dev, struct rtl9300_mdio_pri
struct fwnode_handle *node) struct fwnode_handle *node)
{ {
struct rtl9300_mdio_chan *chan; struct rtl9300_mdio_chan *chan;
struct fwnode_handle *child;
struct mii_bus *bus; struct mii_bus *bus;
u32 mdio_bus; u32 mdio_bus;
int err; int err;
@ -371,7 +370,7 @@ static int rtl9300_mdiobus_probe_one(struct device *dev, struct rtl9300_mdio_pri
* compatible = "ethernet-phy-ieee802.3-c45". This does mean we can't * compatible = "ethernet-phy-ieee802.3-c45". This does mean we can't
* support both c45 and c22 on the same MDIO bus. * support both c45 and c22 on the same MDIO bus.
*/ */
fwnode_for_each_child_node(node, child) fwnode_for_each_child_node_scoped(node, child)
if (fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45")) if (fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"))
priv->smi_bus_is_c45[mdio_bus] = true; priv->smi_bus_is_c45[mdio_bus] = true;
@ -409,7 +408,6 @@ static int rtl9300_mdiobus_map_ports(struct device *dev)
{ {
struct rtl9300_mdio_priv *priv = dev_get_drvdata(dev); struct rtl9300_mdio_priv *priv = dev_get_drvdata(dev);
struct device *parent = dev->parent; struct device *parent = dev->parent;
struct fwnode_handle *port;
int err; int err;
struct fwnode_handle *ports __free(fwnode_handle) = struct fwnode_handle *ports __free(fwnode_handle) =
@ -418,7 +416,7 @@ static int rtl9300_mdiobus_map_ports(struct device *dev)
return dev_err_probe(dev, -EINVAL, "%pfwP missing ethernet-ports\n", return dev_err_probe(dev, -EINVAL, "%pfwP missing ethernet-ports\n",
dev_fwnode(parent)); dev_fwnode(parent));
fwnode_for_each_child_node(ports, port) { fwnode_for_each_child_node_scoped(ports, port) {
struct device_node *mdio_dn; struct device_node *mdio_dn;
u32 addr; u32 addr;
u32 bus; u32 bus;

View File

@ -1167,9 +1167,9 @@ static int mt798x_phy_calibration(struct phy_device *phydev)
} }
buf = (u32 *)nvmem_cell_read(cell, &len); buf = (u32 *)nvmem_cell_read(cell, &len);
nvmem_cell_put(cell);
if (IS_ERR(buf)) if (IS_ERR(buf))
return PTR_ERR(buf); return PTR_ERR(buf);
nvmem_cell_put(cell);
if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) { if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
phydev_err(phydev, "invalid efuse data\n"); phydev_err(phydev, "invalid efuse data\n");

View File

@ -878,7 +878,7 @@ static void __team_queue_override_enabled_check(struct team *team)
static void team_queue_override_port_prio_changed(struct team *team, static void team_queue_override_port_prio_changed(struct team *team,
struct team_port *port) struct team_port *port)
{ {
if (!port->queue_id || team_port_enabled(port)) if (!port->queue_id || !team_port_enabled(port))
return; return;
__team_queue_override_port_del(team, port); __team_queue_override_port_del(team, port);
__team_queue_override_port_add(team, port); __team_queue_override_port_add(team, port);

View File

@ -335,6 +335,11 @@ int asix_read_phy_addr(struct usbnet *dev, bool internal)
offset = (internal ? 1 : 0); offset = (internal ? 1 : 0);
ret = buf[offset]; ret = buf[offset];
if (ret >= PHY_MAX_ADDR) {
netdev_err(dev->net, "invalid PHY address: %d\n", ret);
return -ENODEV;
}
netdev_dbg(dev->net, "%s PHY address 0x%x\n", netdev_dbg(dev->net, "%s PHY address 0x%x\n",
internal ? "internal" : "external", ret); internal ? "internal" : "external", ret);

View File

@ -210,11 +210,7 @@ static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
ret = asix_read_phy_addr(dev, priv->use_embdphy); ret = asix_read_phy_addr(dev, priv->use_embdphy);
if (ret < 0) if (ret < 0)
goto free; goto free;
if (ret >= PHY_MAX_ADDR) {
netdev_err(dev->net, "Invalid PHY address %#x\n", ret);
ret = -ENODEV;
goto free;
}
priv->phy_addr = ret; priv->phy_addr = ret;
ax88172a_reset_phy(dev, priv->use_embdphy); ax88172a_reset_phy(dev, priv->use_embdphy);

View File

@ -211,6 +211,8 @@ static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, u16 reg)
if (res == -ENODEV) if (res == -ENODEV)
netif_device_detach(dev->netdev); netif_device_detach(dev->netdev);
dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res); dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res);
kfree(req);
usb_free_urb(async_urb);
} }
return res; return res;
} }

View File

@ -52,7 +52,7 @@ static int sr_read_reg(struct usbnet *dev, u8 reg, u8 *value)
static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value) static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value)
{ {
return usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG, return usbnet_write_cmd(dev, SR_WR_REG, SR_REQ_WR_REG,
value, reg, NULL, 0); value, reg, NULL, 0);
} }
@ -65,7 +65,7 @@ static void sr_write_async(struct usbnet *dev, u8 reg, u16 length,
static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value) static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
{ {
usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG, usbnet_write_cmd_async(dev, SR_WR_REG, SR_REQ_WR_REG,
value, reg, NULL, 0); value, reg, NULL, 0);
} }
@ -539,6 +539,11 @@ static const struct usb_device_id products[] = {
USB_DEVICE(0x0fe6, 0x9700), /* SR9700 device */ USB_DEVICE(0x0fe6, 0x9700), /* SR9700 device */
.driver_info = (unsigned long)&sr9700_driver_info, .driver_info = (unsigned long)&sr9700_driver_info,
}, },
{
/* SR9700 with virtual driver CD-ROM - interface 0 is the CD-ROM device */
USB_DEVICE_INTERFACE_NUMBER(0x0fe6, 0x9702, 1),
.driver_info = (unsigned long)&sr9700_driver_info,
},
{}, /* END */ {}, /* END */
}; };

View File

@ -831,7 +831,6 @@ int usbnet_stop(struct net_device *net)
clear_bit(EVENT_DEV_OPEN, &dev->flags); clear_bit(EVENT_DEV_OPEN, &dev->flags);
netif_stop_queue(net); netif_stop_queue(net);
netdev_reset_queue(net);
netif_info(dev, ifdown, dev->net, netif_info(dev, ifdown, dev->net,
"stop stats: rx/tx %lu/%lu, errs %lu/%lu\n", "stop stats: rx/tx %lu/%lu, errs %lu/%lu\n",
@ -875,6 +874,8 @@ int usbnet_stop(struct net_device *net)
timer_delete_sync(&dev->delay); timer_delete_sync(&dev->delay);
cancel_work_sync(&dev->kevent); cancel_work_sync(&dev->kevent);
netdev_reset_queue(net);
if (!pm) if (!pm)
usb_autopm_put_interface(dev->intf); usb_autopm_put_interface(dev->intf);

View File

@ -1597,7 +1597,7 @@ static void _iwl_op_mode_stop(struct iwl_drv *drv)
*/ */
static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
{ {
unsigned int min_core, max_core, loaded_core; int min_core, max_core, loaded_core;
struct iwl_drv *drv = context; struct iwl_drv *drv = context;
struct iwl_fw *fw = &drv->fw; struct iwl_fw *fw = &drv->fw;
const struct iwl_ucode_header *ucode; const struct iwl_ucode_header *ucode;
@ -1676,7 +1676,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
if (loaded_core < min_core || loaded_core > max_core) { if (loaded_core < min_core || loaded_core > max_core) {
IWL_ERR(drv, IWL_ERR(drv,
"Driver unable to support your firmware API. " "Driver unable to support your firmware API. "
"Driver supports FW core %u..%u, firmware is %u.\n", "Driver supports FW core %d..%d, firmware is %d.\n",
min_core, max_core, loaded_core); min_core, max_core, loaded_core);
goto try_again; goto try_again;
} }

View File

@ -121,6 +121,12 @@ static int iwl_mld_ptp_gettime(struct ptp_clock_info *ptp,
return 0; return 0;
} }
static int iwl_mld_ptp_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts)
{
return -EOPNOTSUPP;
}
static int iwl_mld_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) static int iwl_mld_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{ {
struct iwl_mld *mld = container_of(ptp, struct iwl_mld, struct iwl_mld *mld = container_of(ptp, struct iwl_mld,
@ -279,6 +285,7 @@ void iwl_mld_ptp_init(struct iwl_mld *mld)
mld->ptp_data.ptp_clock_info.owner = THIS_MODULE; mld->ptp_data.ptp_clock_info.owner = THIS_MODULE;
mld->ptp_data.ptp_clock_info.gettime64 = iwl_mld_ptp_gettime; mld->ptp_data.ptp_clock_info.gettime64 = iwl_mld_ptp_gettime;
mld->ptp_data.ptp_clock_info.settime64 = iwl_mld_ptp_settime;
mld->ptp_data.ptp_clock_info.max_adj = 0x7fffffff; mld->ptp_data.ptp_clock_info.max_adj = 0x7fffffff;
mld->ptp_data.ptp_clock_info.adjtime = iwl_mld_ptp_adjtime; mld->ptp_data.ptp_clock_info.adjtime = iwl_mld_ptp_adjtime;
mld->ptp_data.ptp_clock_info.adjfine = iwl_mld_ptp_adjfine; mld->ptp_data.ptp_clock_info.adjfine = iwl_mld_ptp_adjfine;

View File

@ -220,6 +220,12 @@ static int iwl_mvm_ptp_gettime(struct ptp_clock_info *ptp,
return 0; return 0;
} }
static int iwl_mvm_ptp_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts)
{
return -EOPNOTSUPP;
}
static int iwl_mvm_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) static int iwl_mvm_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{ {
struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm, struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
@ -281,6 +287,7 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
mvm->ptp_data.ptp_clock_info.adjfine = iwl_mvm_ptp_adjfine; mvm->ptp_data.ptp_clock_info.adjfine = iwl_mvm_ptp_adjfine;
mvm->ptp_data.ptp_clock_info.adjtime = iwl_mvm_ptp_adjtime; mvm->ptp_data.ptp_clock_info.adjtime = iwl_mvm_ptp_adjtime;
mvm->ptp_data.ptp_clock_info.gettime64 = iwl_mvm_ptp_gettime; mvm->ptp_data.ptp_clock_info.gettime64 = iwl_mvm_ptp_gettime;
mvm->ptp_data.ptp_clock_info.settime64 = iwl_mvm_ptp_settime;
mvm->ptp_data.scaled_freq = SCALE_FACTOR; mvm->ptp_data.scaled_freq = SCALE_FACTOR;
/* Give a short 'friendly name' to identify the PHC clock */ /* Give a short 'friendly name' to identify the PHC clock */

View File

@ -511,7 +511,8 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
if (sta) { if (sta) {
sta_entry = (struct rtl_sta_info *)sta->drv_priv; sta_entry = (struct rtl_sta_info *)sta->drv_priv;
tid = ieee80211_get_tid(hdr); tid = ieee80211_get_tid(hdr);
agg_state = sta_entry->tids[tid].agg.agg_state; if (tid < MAX_TID_COUNT)
agg_state = sta_entry->tids[tid].agg.agg_state;
ampdu_density = sta->deflink.ht_cap.ampdu_density; ampdu_density = sta->deflink.ht_cap.ampdu_density;
} }

View File

@ -144,8 +144,10 @@ static u32 rtw_sdio_to_io_address(struct rtw_dev *rtwdev, u32 addr,
static bool rtw_sdio_use_direct_io(struct rtw_dev *rtwdev, u32 addr) static bool rtw_sdio_use_direct_io(struct rtw_dev *rtwdev, u32 addr)
{ {
bool might_indirect_under_power_off = rtwdev->chip->id == RTW_CHIP_TYPE_8822C;
if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags) && if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags) &&
!rtw_sdio_is_bus_addr(addr)) !rtw_sdio_is_bus_addr(addr) && might_indirect_under_power_off)
return false; return false;
return !rtw_sdio_is_sdio30_supported(rtwdev) || return !rtw_sdio_is_sdio30_supported(rtwdev) ||

View File

@ -965,8 +965,7 @@ static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
struct sk_buff *rx_skb; struct sk_buff *rx_skb;
int i; int i;
rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH | WQ_UNBOUND, rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH, 0);
0);
if (!rtwusb->rxwq) { if (!rtwusb->rxwq) {
rtw_err(rtwdev, "failed to create RX work queue\n"); rtw_err(rtwdev, "failed to create RX work queue\n");
return -ENOMEM; return -ENOMEM;

View File

@ -207,6 +207,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks); total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks);
if (total_blocks <= wl->tx_blocks_available) { if (total_blocks <= wl->tx_blocks_available) {
if (skb_headroom(skb) < (total_len - skb->len) &&
pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) {
wl1271_free_tx_id(wl, id);
return -EAGAIN;
}
desc = skb_push(skb, total_len - skb->len); desc = skb_push(skb, total_len - skb->len);
wlcore_hw_set_tx_desc_blocks(wl, desc, total_blocks, wlcore_hw_set_tx_desc_blocks(wl, desc, total_blocks,

View File

@ -302,6 +302,7 @@ struct dsa_port {
struct devlink_port devlink_port; struct devlink_port devlink_port;
struct phylink *pl; struct phylink *pl;
struct phylink_config pl_config; struct phylink_config pl_config;
netdevice_tracker conduit_tracker;
struct dsa_lag *lag; struct dsa_lag *lag;
struct net_device *hsr_dev; struct net_device *hsr_dev;

View File

@ -849,6 +849,12 @@ static u32 get_supported_settings(struct hci_dev *hdev)
if (cis_peripheral_capable(hdev)) if (cis_peripheral_capable(hdev))
settings |= MGMT_SETTING_CIS_PERIPHERAL; settings |= MGMT_SETTING_CIS_PERIPHERAL;
if (bis_capable(hdev))
settings |= MGMT_SETTING_ISO_BROADCASTER;
if (sync_recv_capable(hdev))
settings |= MGMT_SETTING_ISO_SYNC_RECEIVER;
if (ll_privacy_capable(hdev)) if (ll_privacy_capable(hdev))
settings |= MGMT_SETTING_LL_PRIVACY; settings |= MGMT_SETTING_LL_PRIVACY;

View File

@ -247,6 +247,7 @@ struct net_bridge_vlan {
* struct net_bridge_vlan_group * struct net_bridge_vlan_group
* *
* @vlan_hash: VLAN entry rhashtable * @vlan_hash: VLAN entry rhashtable
* @tunnel_hash: Hash table to map from tunnel key ID (e.g. VXLAN VNI) to VLAN
* @vlan_list: sorted VLAN entry list * @vlan_list: sorted VLAN entry list
* @num_vlans: number of total VLAN entries * @num_vlans: number of total VLAN entries
* @pvid: PVID VLAN id * @pvid: PVID VLAN id

View File

@ -4241,9 +4241,11 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
int count = 0; int count = 0;
llist_for_each_entry_safe(skb, next, ll_list, ll_node) { llist_for_each_entry_safe(skb, next, ll_list, ll_node) {
prefetch(next); if (next) {
prefetch(&next->priority); prefetch(next);
skb_mark_not_on_list(skb); prefetch(&next->priority);
skb_mark_not_on_list(skb);
}
rc = dev_qdisc_enqueue(skb, q, &to_free, txq); rc = dev_qdisc_enqueue(skb, q, &to_free, txq);
count++; count++;
} }

View File

@ -367,16 +367,10 @@ static struct dsa_port *dsa_tree_find_first_cpu(struct dsa_switch_tree *dst)
struct net_device *dsa_tree_find_first_conduit(struct dsa_switch_tree *dst) struct net_device *dsa_tree_find_first_conduit(struct dsa_switch_tree *dst)
{ {
struct device_node *ethernet;
struct net_device *conduit;
struct dsa_port *cpu_dp; struct dsa_port *cpu_dp;
cpu_dp = dsa_tree_find_first_cpu(dst); cpu_dp = dsa_tree_find_first_cpu(dst);
ethernet = of_parse_phandle(cpu_dp->dn, "ethernet", 0); return cpu_dp->conduit;
conduit = of_find_net_device_by_node(ethernet);
of_node_put(ethernet);
return conduit;
} }
/* Assign the default CPU port (the first one in the tree) to all ports of the /* Assign the default CPU port (the first one in the tree) to all ports of the
@ -1253,14 +1247,25 @@ static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn)
if (ethernet) { if (ethernet) {
struct net_device *conduit; struct net_device *conduit;
const char *user_protocol; const char *user_protocol;
int err;
rtnl_lock();
conduit = of_find_net_device_by_node(ethernet); conduit = of_find_net_device_by_node(ethernet);
of_node_put(ethernet); of_node_put(ethernet);
if (!conduit) if (!conduit) {
rtnl_unlock();
return -EPROBE_DEFER; return -EPROBE_DEFER;
}
netdev_hold(conduit, &dp->conduit_tracker, GFP_KERNEL);
put_device(&conduit->dev);
rtnl_unlock();
user_protocol = of_get_property(dn, "dsa-tag-protocol", NULL); user_protocol = of_get_property(dn, "dsa-tag-protocol", NULL);
return dsa_port_parse_cpu(dp, conduit, user_protocol); err = dsa_port_parse_cpu(dp, conduit, user_protocol);
if (err)
netdev_put(conduit, &dp->conduit_tracker);
return err;
} }
if (link) if (link)
@ -1393,37 +1398,30 @@ static struct device *dev_find_class(struct device *parent, char *class)
return device_find_child(parent, class, dev_is_class); return device_find_child(parent, class, dev_is_class);
} }
static struct net_device *dsa_dev_to_net_device(struct device *dev)
{
struct device *d;
d = dev_find_class(dev, "net");
if (d != NULL) {
struct net_device *nd;
nd = to_net_dev(d);
dev_hold(nd);
put_device(d);
return nd;
}
return NULL;
}
static int dsa_port_parse(struct dsa_port *dp, const char *name, static int dsa_port_parse(struct dsa_port *dp, const char *name,
struct device *dev) struct device *dev)
{ {
if (!strcmp(name, "cpu")) { if (!strcmp(name, "cpu")) {
struct net_device *conduit; struct net_device *conduit;
struct device *d;
int err;
conduit = dsa_dev_to_net_device(dev); rtnl_lock();
if (!conduit) d = dev_find_class(dev, "net");
if (!d) {
rtnl_unlock();
return -EPROBE_DEFER; return -EPROBE_DEFER;
}
dev_put(conduit); conduit = to_net_dev(d);
netdev_hold(conduit, &dp->conduit_tracker, GFP_KERNEL);
put_device(d);
rtnl_unlock();
return dsa_port_parse_cpu(dp, conduit, NULL); err = dsa_port_parse_cpu(dp, conduit, NULL);
if (err)
netdev_put(conduit, &dp->conduit_tracker);
return err;
} }
if (!strcmp(name, "dsa")) if (!strcmp(name, "dsa"))
@ -1491,6 +1489,9 @@ static void dsa_switch_release_ports(struct dsa_switch *ds)
struct dsa_vlan *v, *n; struct dsa_vlan *v, *n;
dsa_switch_for_each_port_safe(dp, next, ds) { dsa_switch_for_each_port_safe(dp, next, ds) {
if (dsa_port_is_cpu(dp) && dp->conduit)
netdev_put(dp->conduit, &dp->conduit_tracker);
/* These are either entries that upper layers lost track of /* These are either entries that upper layers lost track of
* (probably due to bugs), or installed through interfaces * (probably due to bugs), or installed through interfaces
* where one does not necessarily have to remove them, like * where one does not necessarily have to remove them, like
@ -1635,8 +1636,10 @@ void dsa_switch_shutdown(struct dsa_switch *ds)
/* Disconnect from further netdevice notifiers on the conduit, /* Disconnect from further netdevice notifiers on the conduit,
* since netdev_uses_dsa() will now return false. * since netdev_uses_dsa() will now return false.
*/ */
dsa_switch_for_each_cpu_port(dp, ds) dsa_switch_for_each_cpu_port(dp, ds) {
dp->conduit->dsa_ptr = NULL; dp->conduit->dsa_ptr = NULL;
netdev_put(dp->conduit, &dp->conduit_tracker);
}
rtnl_unlock(); rtnl_unlock();
out: out:

View File

@ -126,7 +126,8 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info)
} }
out_complete: out_complete:
handshake_complete(req, -EIO, NULL); if (req)
handshake_complete(req, -EIO, NULL);
out_status: out_status:
trace_handshake_cmd_accept_err(net, req, NULL, err); trace_handshake_cmd_accept_err(net, req, NULL, err);
return err; return err;

View File

@ -2167,8 +2167,8 @@ void fib_select_multipath(struct fib_result *res, int hash,
{ {
struct fib_info *fi = res->fi; struct fib_info *fi = res->fi;
struct net *net = fi->fib_net; struct net *net = fi->fib_net;
bool found = false;
bool use_neigh; bool use_neigh;
int score = -1;
__be32 saddr; __be32 saddr;
if (unlikely(res->fi->nh)) { if (unlikely(res->fi->nh)) {
@ -2180,7 +2180,7 @@ void fib_select_multipath(struct fib_result *res, int hash,
saddr = fl4 ? fl4->saddr : 0; saddr = fl4 ? fl4->saddr : 0;
change_nexthops(fi) { change_nexthops(fi) {
int nh_upper_bound; int nh_upper_bound, nh_score = 0;
/* Nexthops without a carrier are assigned an upper bound of /* Nexthops without a carrier are assigned an upper bound of
* minus one when "ignore_routes_with_linkdown" is set. * minus one when "ignore_routes_with_linkdown" is set.
@ -2190,24 +2190,18 @@ void fib_select_multipath(struct fib_result *res, int hash,
(use_neigh && !fib_good_nh(nexthop_nh))) (use_neigh && !fib_good_nh(nexthop_nh)))
continue; continue;
if (!found) { if (saddr && nexthop_nh->nh_saddr == saddr)
nh_score += 2;
if (hash <= nh_upper_bound)
nh_score++;
if (score < nh_score) {
res->nh_sel = nhsel; res->nh_sel = nhsel;
res->nhc = &nexthop_nh->nh_common; res->nhc = &nexthop_nh->nh_common;
found = !saddr || nexthop_nh->nh_saddr == saddr; if (nh_score == 3 || (!saddr && nh_score == 1))
return;
score = nh_score;
} }
if (hash > nh_upper_bound)
continue;
if (!saddr || nexthop_nh->nh_saddr == saddr) {
res->nh_sel = nhsel;
res->nhc = &nexthop_nh->nh_common;
return;
}
if (found)
return;
} endfor_nexthops(fi); } endfor_nexthops(fi);
} }
#endif #endif

View File

@ -2053,10 +2053,11 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
continue; continue;
} }
/* Do not flush error routes if network namespace is /* When not flushing the entire table, skip error
* not being dismantled * routes that are not marked for deletion.
*/ */
if (!flush_all && fib_props[fa->fa_type].error) { if (!flush_all && fib_props[fa->fa_type].error &&
!(fi->fib_flags & RTNH_F_DEAD)) {
slen = fa->fa_slen; slen = fa->fa_slen;
continue; continue;
} }

View File

@ -330,6 +330,10 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
if (!tun_dst) if (!tun_dst)
return PACKET_REJECT; return PACKET_REJECT;
/* MUST set options_len before referencing options */
info = &tun_dst->u.tun_info;
info->options_len = sizeof(*md);
/* skb can be uncloned in __iptunnel_pull_header, so /* skb can be uncloned in __iptunnel_pull_header, so
* old pkt_md is no longer valid and we need to reset * old pkt_md is no longer valid and we need to reset
* it * it
@ -344,10 +348,8 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE : memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE :
ERSPAN_V2_MDSIZE); ERSPAN_V2_MDSIZE);
info = &tun_dst->u.tun_info;
__set_bit(IP_TUNNEL_ERSPAN_OPT_BIT, __set_bit(IP_TUNNEL_ERSPAN_OPT_BIT,
info->key.tun_flags); info->key.tun_flags);
info->options_len = sizeof(*md);
} }
skb_reset_mac_header(skb); skb_reset_mac_header(skb);

View File

@ -1342,7 +1342,8 @@ static int calipso_skbuff_setattr(struct sk_buff *skb,
/* At this point new_end aligns to 4n, so (new_end & 4) pads to 8n */ /* At this point new_end aligns to 4n, so (new_end & 4) pads to 8n */
pad = ((new_end & 4) + (end & 7)) & 7; pad = ((new_end & 4) + (end & 7)) & 7;
len_delta = new_end - (int)end + pad; len_delta = new_end - (int)end + pad;
ret_val = skb_cow(skb, skb_headroom(skb) + len_delta); ret_val = skb_cow(skb,
skb_headroom(skb) + (len_delta > 0 ? len_delta : 0));
if (ret_val < 0) if (ret_val < 0)
return ret_val; return ret_val;

View File

@ -535,6 +535,10 @@ static int ip6erspan_rcv(struct sk_buff *skb,
if (!tun_dst) if (!tun_dst)
return PACKET_REJECT; return PACKET_REJECT;
/* MUST set options_len before referencing options */
info = &tun_dst->u.tun_info;
info->options_len = sizeof(*md);
/* skb can be uncloned in __iptunnel_pull_header, so /* skb can be uncloned in __iptunnel_pull_header, so
* old pkt_md is no longer valid and we need to reset * old pkt_md is no longer valid and we need to reset
* it * it
@ -543,7 +547,6 @@ static int ip6erspan_rcv(struct sk_buff *skb,
skb_network_header_len(skb); skb_network_header_len(skb);
pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len + pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
sizeof(*ershdr)); sizeof(*ershdr));
info = &tun_dst->u.tun_info;
md = ip_tunnel_info_opts(info); md = ip_tunnel_info_opts(info);
md->version = ver; md->version = ver;
md2 = &md->u.md2; md2 = &md->u.md2;
@ -551,7 +554,6 @@ static int ip6erspan_rcv(struct sk_buff *skb,
ERSPAN_V2_MDSIZE); ERSPAN_V2_MDSIZE);
__set_bit(IP_TUNNEL_ERSPAN_OPT_BIT, __set_bit(IP_TUNNEL_ERSPAN_OPT_BIT,
info->key.tun_flags); info->key.tun_flags);
info->options_len = sizeof(*md);
ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
@ -1366,9 +1368,16 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev,
{ {
struct ip6_tnl *t = netdev_priv(dev); struct ip6_tnl *t = netdev_priv(dev);
struct ipv6hdr *ipv6h; struct ipv6hdr *ipv6h;
int needed;
__be16 *p; __be16 *p;
ipv6h = skb_push(skb, t->hlen + sizeof(*ipv6h)); needed = t->hlen + sizeof(*ipv6h);
if (skb_headroom(skb) < needed &&
pskb_expand_head(skb, HH_DATA_ALIGN(needed - skb_headroom(skb)),
0, GFP_ATOMIC))
return -needed;
ipv6h = skb_push(skb, needed);
ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb, ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb,
t->fl.u.ip6.flowlabel, t->fl.u.ip6.flowlabel,
true, &t->fl.u.ip6)); true, &t->fl.u.ip6));

View File

@ -1470,7 +1470,18 @@ static struct rt6_info *rt6_make_pcpu_route(struct net *net,
p = this_cpu_ptr(res->nh->rt6i_pcpu); p = this_cpu_ptr(res->nh->rt6i_pcpu);
prev = cmpxchg(p, NULL, pcpu_rt); prev = cmpxchg(p, NULL, pcpu_rt);
BUG_ON(prev); if (unlikely(prev)) {
/*
* Another task on this CPU already installed a pcpu_rt.
* This can happen on PREEMPT_RT where preemption is possible.
* Free our allocation and return the existing one.
*/
WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT_RT));
dst_dev_put(&pcpu_rt->dst);
dst_release(&pcpu_rt->dst);
return prev;
}
if (res->f6i->fib6_destroying) { if (res->f6i->fib6_destroying) {
struct fib6_info *from; struct fib6_info *from;

View File

@ -1345,7 +1345,6 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
size = sizeof(*new) + new_head_len + new_tail_len; size = sizeof(*new) + new_head_len + new_tail_len;
/* new or old multiple BSSID elements? */
if (params->mbssid_ies) { if (params->mbssid_ies) {
mbssid = params->mbssid_ies; mbssid = params->mbssid_ies;
size += struct_size(new->mbssid_ies, elem, mbssid->cnt); size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
@ -1355,15 +1354,6 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
} }
size += ieee80211_get_mbssid_beacon_len(mbssid, rnr, size += ieee80211_get_mbssid_beacon_len(mbssid, rnr,
mbssid->cnt); mbssid->cnt);
} else if (old && old->mbssid_ies) {
mbssid = old->mbssid_ies;
size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
if (old && old->rnr_ies) {
rnr = old->rnr_ies;
size += struct_size(new->rnr_ies, elem, rnr->cnt);
}
size += ieee80211_get_mbssid_beacon_len(mbssid, rnr,
mbssid->cnt);
} }
new = kzalloc(size, GFP_KERNEL); new = kzalloc(size, GFP_KERNEL);

View File

@ -1251,7 +1251,7 @@ configure_monitor:
if (!creator_sdata) { if (!creator_sdata) {
struct ieee80211_sub_if_data *other; struct ieee80211_sub_if_data *other;
list_for_each_entry(other, &local->mon_list, list) { list_for_each_entry_rcu(other, &local->mon_list, u.mntr.list) {
if (!other->vif.bss_conf.mu_mimo_owner) if (!other->vif.bss_conf.mu_mimo_owner)
continue; continue;

View File

@ -1126,7 +1126,10 @@ again:
while (!ieee80211_chandef_usable(sdata, &chanreq->oper, while (!ieee80211_chandef_usable(sdata, &chanreq->oper,
IEEE80211_CHAN_DISABLED)) { IEEE80211_CHAN_DISABLED)) {
if (WARN_ON(chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT)) { if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT) {
link_id_info(sdata, link_id,
"unusable channel (%d MHz) for connection\n",
chanreq->oper.chan->center_freq);
ret = -EINVAL; ret = -EINVAL;
goto free; goto free;
} }

View File

@ -47,6 +47,9 @@ void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta; struct sta_info *sta;
int band; int band;
if (!ifocb->joined)
return;
/* XXX: Consider removing the least recently used entry and /* XXX: Consider removing the least recently used entry and
* allow new one to be added. * allow new one to be added.
*/ */

View File

@ -3511,6 +3511,11 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
rx->skb->len < IEEE80211_MIN_ACTION_SIZE) rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
return RX_DROP_U_RUNT_ACTION; return RX_DROP_U_RUNT_ACTION;
/* Drop non-broadcast Beacon frames */
if (ieee80211_is_beacon(mgmt->frame_control) &&
!is_broadcast_ether_addr(mgmt->da))
return RX_DROP;
if (rx->sdata->vif.type == NL80211_IFTYPE_AP && if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
ieee80211_is_beacon(mgmt->frame_control) && ieee80211_is_beacon(mgmt->frame_control) &&
!(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {

View File

@ -408,6 +408,16 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
*/ */
subflow->snd_isn = TCP_SKB_CB(skb)->end_seq; subflow->snd_isn = TCP_SKB_CB(skb)->end_seq;
if (subflow->request_mptcp) { if (subflow->request_mptcp) {
if (unlikely(subflow_simultaneous_connect(sk))) {
WARN_ON_ONCE(!mptcp_try_fallback(sk, MPTCP_MIB_SIMULTCONNFALLBACK));
/* Ensure mptcp_finish_connect() will not process the
* MPC handshake.
*/
subflow->request_mptcp = 0;
return false;
}
opts->suboptions = OPTION_MPTCP_MPC_SYN; opts->suboptions = OPTION_MPTCP_MPC_SYN;
opts->csum_reqd = mptcp_is_checksum_enabled(sock_net(sk)); opts->csum_reqd = mptcp_is_checksum_enabled(sock_net(sk));
opts->allow_join_id0 = mptcp_allow_join_id0(sock_net(sk)); opts->allow_join_id0 = mptcp_allow_join_id0(sock_net(sk));

View File

@ -2467,10 +2467,10 @@ bool __mptcp_retransmit_pending_data(struct sock *sk)
*/ */
static void __mptcp_subflow_disconnect(struct sock *ssk, static void __mptcp_subflow_disconnect(struct sock *ssk,
struct mptcp_subflow_context *subflow, struct mptcp_subflow_context *subflow,
unsigned int flags) bool fastclosing)
{ {
if (((1 << ssk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) || if (((1 << ssk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
subflow->send_fastclose) { fastclosing) {
/* The MPTCP code never wait on the subflow sockets, TCP-level /* The MPTCP code never wait on the subflow sockets, TCP-level
* disconnect should never fail * disconnect should never fail
*/ */
@ -2538,7 +2538,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk); need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk);
if (!dispose_it) { if (!dispose_it) {
__mptcp_subflow_disconnect(ssk, subflow, flags); __mptcp_subflow_disconnect(ssk, subflow, msk->fastclosing);
release_sock(ssk); release_sock(ssk);
goto out; goto out;
@ -2884,6 +2884,7 @@ static void mptcp_do_fastclose(struct sock *sk)
mptcp_set_state(sk, TCP_CLOSE); mptcp_set_state(sk, TCP_CLOSE);
mptcp_backlog_purge(sk); mptcp_backlog_purge(sk);
msk->fastclosing = 1;
/* Explicitly send the fastclose reset as need */ /* Explicitly send the fastclose reset as need */
if (__mptcp_check_fallback(msk)) if (__mptcp_check_fallback(msk))
@ -3418,6 +3419,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)
msk->bytes_sent = 0; msk->bytes_sent = 0;
msk->bytes_retrans = 0; msk->bytes_retrans = 0;
msk->rcvspace_init = 0; msk->rcvspace_init = 0;
msk->fastclosing = 0;
/* for fallback's sake */ /* for fallback's sake */
WRITE_ONCE(msk->ack_seq, 0); WRITE_ONCE(msk->ack_seq, 0);

View File

@ -320,7 +320,8 @@ struct mptcp_sock {
fastopening:1, fastopening:1,
in_accept_queue:1, in_accept_queue:1,
free_first:1, free_first:1,
rcvspace_init:1; rcvspace_init:1,
fastclosing:1;
u32 notsent_lowat; u32 notsent_lowat;
int keepalive_cnt; int keepalive_cnt;
int keepalive_idle; int keepalive_idle;
@ -1337,10 +1338,8 @@ static inline bool subflow_simultaneous_connect(struct sock *sk)
{ {
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
return (1 << sk->sk_state) & /* Note that the sk state implies !subflow->conn_finished. */
(TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | TCPF_CLOSING) && return sk->sk_state == TCP_SYN_RECV && is_active_ssk(subflow);
is_active_ssk(subflow) &&
!subflow->conn_finished;
} }
#ifdef CONFIG_SYN_COOKIES #ifdef CONFIG_SYN_COOKIES

View File

@ -1878,12 +1878,6 @@ static void subflow_state_change(struct sock *sk)
__subflow_state_change(sk); __subflow_state_change(sk);
if (subflow_simultaneous_connect(sk)) {
WARN_ON_ONCE(!mptcp_try_fallback(sk, MPTCP_MIB_SIMULTCONNFALLBACK));
subflow->conn_finished = 1;
mptcp_propagate_state(parent, sk, subflow, NULL);
}
/* as recvmsg() does not acquire the subflow socket for ssk selection /* as recvmsg() does not acquire the subflow socket for ssk selection
* a fin packet carrying a DSS can be unnoticed if we don't trigger * a fin packet carrying a DSS can be unnoticed if we don't trigger
* the data available machinery here. * the data available machinery here.

View File

@ -1154,6 +1154,7 @@ EXPORT_SYMBOL(nfc_register_device);
void nfc_unregister_device(struct nfc_dev *dev) void nfc_unregister_device(struct nfc_dev *dev)
{ {
int rc; int rc;
struct rfkill *rfk = NULL;
pr_debug("dev_name=%s\n", dev_name(&dev->dev)); pr_debug("dev_name=%s\n", dev_name(&dev->dev));
@ -1164,13 +1165,17 @@ void nfc_unregister_device(struct nfc_dev *dev)
device_lock(&dev->dev); device_lock(&dev->dev);
if (dev->rfkill) { if (dev->rfkill) {
rfkill_unregister(dev->rfkill); rfk = dev->rfkill;
rfkill_destroy(dev->rfkill);
dev->rfkill = NULL; dev->rfkill = NULL;
} }
dev->shutting_down = true; dev->shutting_down = true;
device_unlock(&dev->dev); device_unlock(&dev->dev);
if (rfk) {
rfkill_unregister(rfk);
rfkill_destroy(rfk);
}
if (dev->ops->check_presence) { if (dev->ops->check_presence) {
timer_delete_sync(&dev->check_pres_timer); timer_delete_sync(&dev->check_pres_timer);
cancel_work_sync(&dev->check_pres_work); cancel_work_sync(&dev->check_pres_work);

View File

@ -160,10 +160,19 @@ void ovs_netdev_detach_dev(struct vport *vport)
static void netdev_destroy(struct vport *vport) static void netdev_destroy(struct vport *vport)
{ {
rtnl_lock(); /* When called from ovs_db_notify_wq() after a dp_device_event(), the
if (netif_is_ovs_port(vport->dev)) * port has already been detached, so we can avoid taking the RTNL by
ovs_netdev_detach_dev(vport); * checking this first.
rtnl_unlock(); */
if (netif_is_ovs_port(vport->dev)) {
rtnl_lock();
/* Check again while holding the lock to ensure we don't race
* with the netdev notifier and detach twice.
*/
if (netif_is_ovs_port(vport->dev))
ovs_netdev_detach_dev(vport);
rtnl_unlock();
}
call_rcu(&vport->rcu, vport_netdev_free); call_rcu(&vport->rcu, vport_netdev_free);
} }

View File

@ -205,7 +205,7 @@ start:
spin_unlock_bh(&rose_list_lock); spin_unlock_bh(&rose_list_lock);
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
sk = array[cnt]; sk = array[i];
rose = rose_sk(sk); rose = rose_sk(sk);
lock_sock(sk); lock_sock(sk);
spin_lock_bh(&rose_list_lock); spin_lock_bh(&rose_list_lock);

View File

@ -2904,6 +2904,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
unsigned int last_len; unsigned int last_len;
struct unix_sock *u; struct unix_sock *u;
int copied = 0; int copied = 0;
bool do_cmsg;
int err = 0; int err = 0;
long timeo; long timeo;
int target; int target;
@ -2929,6 +2930,9 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
u = unix_sk(sk); u = unix_sk(sk);
do_cmsg = READ_ONCE(u->recvmsg_inq);
if (do_cmsg)
msg->msg_get_inq = 1;
redo: redo:
/* Lock the socket to prevent queue disordering /* Lock the socket to prevent queue disordering
* while sleeps in memcpy_tomsg * while sleeps in memcpy_tomsg
@ -3088,10 +3092,11 @@ unlock:
if (msg) { if (msg) {
scm_recv_unix(sock, msg, &scm, flags); scm_recv_unix(sock, msg, &scm, flags);
if (READ_ONCE(u->recvmsg_inq) || msg->msg_get_inq) { if (msg->msg_get_inq && (copied ?: err) >= 0) {
msg->msg_inq = READ_ONCE(u->inq_len); msg->msg_inq = READ_ONCE(u->inq_len);
put_cmsg(msg, SOL_SOCKET, SCM_INQ, if (do_cmsg)
sizeof(msg->msg_inq), &msg->msg_inq); put_cmsg(msg, SOL_SOCKET, SCM_INQ,
sizeof(msg->msg_inq), &msg->msg_inq);
} }
} else { } else {
scm_destroy(&scm); scm_destroy(&scm);

View File

@ -910,7 +910,7 @@ void __cfg80211_connect_result(struct net_device *dev,
ssid_len = min(ssid->datalen, IEEE80211_MAX_SSID_LEN); ssid_len = min(ssid->datalen, IEEE80211_MAX_SSID_LEN);
memcpy(wdev->u.client.ssid, ssid->data, ssid_len); memcpy(wdev->u.client.ssid, ssid->data, ssid_len);
wdev->u.client.ssid_len = ssid->datalen; wdev->u.client.ssid_len = ssid_len;
break; break;
} }
rcu_read_unlock(); rcu_read_unlock();

View File

@ -573,8 +573,9 @@ def psp_ip_ver_test_builder(name, test_func, psp_ver, ipver):
"""Build test cases for each combo of PSP version and IP version""" """Build test cases for each combo of PSP version and IP version"""
def test_case(cfg): def test_case(cfg):
cfg.require_ipver(ipver) cfg.require_ipver(ipver)
test_case.__name__ = f"{name}_v{psp_ver}_ip{ipver}"
test_func(cfg, psp_ver, ipver) test_func(cfg, psp_ver, ipver)
test_case.__name__ = f"{name}_v{psp_ver}_ip{ipver}"
return test_case return test_case
@ -582,8 +583,9 @@ def ipver_test_builder(name, test_func, ipver):
"""Build test cases for each IP version""" """Build test cases for each IP version"""
def test_case(cfg): def test_case(cfg):
cfg.require_ipver(ipver) cfg.require_ipver(ipver)
test_case.__name__ = f"{name}_ip{ipver}"
test_func(cfg, ipver) test_func(cfg, ipver)
test_case.__name__ = f"{name}_ip{ipver}"
return test_case return test_case

View File

@ -800,6 +800,14 @@ ipv6_fcnal()
set +e set +e
check_nexthop "dev veth1" "" check_nexthop "dev veth1" ""
log_test $? 0 "Nexthops removed on admin down" log_test $? 0 "Nexthops removed on admin down"
# error routes should be deleted when their nexthop is deleted
run_cmd "$IP li set dev veth1 up"
run_cmd "$IP -6 nexthop add id 58 dev veth1"
run_cmd "$IP ro add blackhole 2001:db8:101::1/128 nhid 58"
run_cmd "$IP nexthop del id 58"
check_route6 "2001:db8:101::1" ""
log_test $? 0 "Error route removed on nexthop deletion"
} }
ipv6_grp_refs() ipv6_grp_refs()
@ -1459,6 +1467,13 @@ ipv4_fcnal()
run_cmd "$IP ro del 172.16.102.0/24" run_cmd "$IP ro del 172.16.102.0/24"
log_test $? 0 "Delete route when not specifying nexthop attributes" log_test $? 0 "Delete route when not specifying nexthop attributes"
# error routes should be deleted when their nexthop is deleted
run_cmd "$IP nexthop add id 23 dev veth1"
run_cmd "$IP ro add blackhole 172.16.102.100/32 nhid 23"
run_cmd "$IP nexthop del id 23"
check_route "172.16.102.100" ""
log_test $? 0 "Error route removed on nexthop deletion"
} }
ipv4_grp_fcnal() ipv4_grp_fcnal()

View File

@ -12,7 +12,7 @@ TESTS="unregister down carrier nexthop suppress ipv6_notify ipv4_notify \
ipv4_route_metrics ipv4_route_v6_gw rp_filter ipv4_del_addr \ ipv4_route_metrics ipv4_route_v6_gw rp_filter ipv4_del_addr \
ipv6_del_addr ipv4_mangle ipv6_mangle ipv4_bcast_neigh fib6_gc_test \ ipv6_del_addr ipv4_mangle ipv6_mangle ipv4_bcast_neigh fib6_gc_test \
ipv4_mpath_list ipv6_mpath_list ipv4_mpath_balance ipv6_mpath_balance \ ipv4_mpath_list ipv6_mpath_list ipv4_mpath_balance ipv6_mpath_balance \
fib6_ra_to_static" ipv4_mpath_balance_preferred fib6_ra_to_static"
VERBOSE=0 VERBOSE=0
PAUSE_ON_FAIL=no PAUSE_ON_FAIL=no
@ -2751,6 +2751,73 @@ ipv4_mpath_balance_test()
forwarding_cleanup forwarding_cleanup
} }
get_route_dev_src()
{
local pfx="$1"
local src="$2"
local out
if out=$($IP -j route get "$pfx" from "$src" | jq -re ".[0].dev"); then
echo "$out"
fi
}
ipv4_mpath_preferred()
{
local src_ip=$1
local pref_dev=$2
local dev routes
local route0=0
local route1=0
local pref_route=0
num_routes=254
for i in $(seq 1 $num_routes) ; do
dev=$(get_route_dev_src 172.16.105.$i $src_ip)
if [ "$dev" = "$pref_dev" ]; then
pref_route=$((pref_route+1))
elif [ "$dev" = "veth1" ]; then
route0=$((route0+1))
elif [ "$dev" = "veth3" ]; then
route1=$((route1+1))
fi
done
routes=$((route0+route1))
[ "$VERBOSE" = "1" ] && echo "multipath: routes seen: ($route0,$route1,$pref_route)"
if [ x"$pref_dev" = x"" ]; then
[[ $routes -ge $num_routes ]] && [[ $route0 -gt 0 ]] && [[ $route1 -gt 0 ]]
else
[[ $pref_route -ge $num_routes ]]
fi
}
ipv4_mpath_balance_preferred_test()
{
echo
echo "IPv4 multipath load balance preferred route"
forwarding_setup
$IP route add 172.16.105.0/24 \
nexthop via 172.16.101.2 \
nexthop via 172.16.103.2
ipv4_mpath_preferred 172.16.101.1 veth1
log_test $? 0 "IPv4 multipath loadbalance from veth1"
ipv4_mpath_preferred 172.16.103.1 veth3
log_test $? 0 "IPv4 multipath loadbalance from veth3"
ipv4_mpath_preferred 198.51.100.1
log_test $? 0 "IPv4 multipath loadbalance from dummy"
forwarding_cleanup
}
ipv6_mpath_balance_test() ipv6_mpath_balance_test()
{ {
echo echo
@ -2861,6 +2928,7 @@ do
ipv6_mpath_list) ipv6_mpath_list_test;; ipv6_mpath_list) ipv6_mpath_list_test;;
ipv4_mpath_balance) ipv4_mpath_balance_test;; ipv4_mpath_balance) ipv4_mpath_balance_test;;
ipv6_mpath_balance) ipv6_mpath_balance_test;; ipv6_mpath_balance) ipv6_mpath_balance_test;;
ipv4_mpath_balance_preferred) ipv4_mpath_balance_preferred_test;;
fib6_ra_to_static) fib6_ra_to_static;; fib6_ra_to_static) fib6_ra_to_static;;
help) echo "Test names: $TESTS"; exit 0;; help) echo "Test names: $TESTS"; exit 0;;

View File

@ -56,18 +56,12 @@ static void rtattr_end(struct nlmsghdr *nh, struct rtattr *attr)
static struct rtattr *rtattr_add_str(struct nlmsghdr *nh, unsigned short type, static struct rtattr *rtattr_add_str(struct nlmsghdr *nh, unsigned short type,
const char *s) const char *s)
{ {
struct rtattr *rta = rtattr_add(nh, type, strlen(s)); unsigned int strsz = strlen(s) + 1;
struct rtattr *rta;
memcpy(RTA_DATA(rta), s, strlen(s)); rta = rtattr_add(nh, type, strsz);
return rta;
}
static struct rtattr *rtattr_add_strsz(struct nlmsghdr *nh, unsigned short type, memcpy(RTA_DATA(rta), s, strsz);
const char *s)
{
struct rtattr *rta = rtattr_add(nh, type, strlen(s) + 1);
strcpy(RTA_DATA(rta), s);
return rta; return rta;
} }
@ -119,7 +113,7 @@ static int dev_create(const char *dev, const char *link_type,
link_info = rtattr_begin(&req.nh, IFLA_LINKINFO); link_info = rtattr_begin(&req.nh, IFLA_LINKINFO);
rtattr_add_strsz(&req.nh, IFLA_INFO_KIND, link_type); rtattr_add_str(&req.nh, IFLA_INFO_KIND, link_type);
if (fill_info_data) { if (fill_info_data) {
info_data = rtattr_begin(&req.nh, IFLA_INFO_DATA); info_data = rtattr_begin(&req.nh, IFLA_INFO_DATA);