Including fixes from Bluetooth, CAN and Netfilter.

Current release - regressions:
 
  - 2 fixes for the netdev per-instance locking
 
  - batman-adv: fix double-hold of meshif when getting enabled
 
 Current release - new code bugs:
 
  - Bluetooth: increment TX timestamping tskey always for stream sockets
 
  - wifi: static analysis and build fixes for the new Intel sub-driver
 
 Previous releases - regressions:
 
  - net: fib_rules: fix iif / oif matching on L3 master (VRF) device
 
  - ipv6: add exception routes to GC list in rt6_insert_exception()
 
  - netfilter: conntrack: fix erroneous removal of offload bit
 
  - Bluetooth:
   - fix sending MGMT_EV_DEVICE_FOUND for invalid address
   - l2cap: process valid commands in too long frame
   - btnxpuart: Revert baudrate change in nxp_shutdown
 
 Previous releases - always broken:
 
  - ethtool: fix memory corruption during SFP FW flashing
 
  - eth: hibmcge: fixes for link and MTU handling, pause frames etc.
 
  - eth: igc: fixes for PTM (PCIe timestamping)
 
  - dsa: b53: enable BPDU reception for management port
 
 Misc:
 
  - fixes for Netlink protocol schemas
 
 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmgBMWAACgkQMUZtbf5S
 Irv3kw//enBPRBMhTdXop2g9Rlw8zQEwuMinq9ytgiNbWxshd7wXHNDYKICaX8qK
 KkN4InxF4ieESHGNUy9/UvZLAEHYV8BqugdUGurwCnEg9QJlThsDmRCYTxI37Sdx
 8uUYoSYWvPcHUsw3s/qBzunAZ8R/5hbP99L1M8W+3DqnJUm6qjUYjWCmm+8sn6FW
 abZ8JiazJhGKfTtIGxxN3oOJBzKcdeTK+z29ujQBWegnau8uj92QKkuoTZTtHaYL
 MU5pRyDQS5vo/wLBizTGQQ7PrcIpKgM1mi5Oayl5WbvTUF1pJ8pvT1iT7jnGOt4c
 lWPImtdQwsNwAwFNU7/S+YkBvrYBsCUPDErQ82HtxRsNXcCzKvuM4SqkvzYS5SZd
 Qz0ZuKqXbxxSgRgasvikWP6qAI8vz4zT8pjXu/a3eE5xnsSqhwXVbEwez8KqRF79
 Cxm/iYz/m/NhYW59YSobssNHjGM4QgOu/dFr37EPCgf8BK//RLFckwQVA1qBogO/
 HEwkWhQFYNJY0BDXuzO8rCPFQbs/NBiuNU0xRbKqPGkGcqKRwTd/KLOeTe/NJvtE
 mQx5R+VNVEyNdlQtXh5muEJHhN2nLYzQUTM5gkt6jwIzcLt7HVE+ZF3nkAKf1EQB
 1nYN8gxCO1convTNT84Eldpp2At8zazz+ltnC9gWIEZhdTct46Q=
 =EObk
 -----END PGP SIGNATURE-----

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

Pull networking fixes from Jakub Kicinski:
 "Including fixes from Bluetooth, CAN and Netfilter.

  Current release - regressions:

   - two fixes for the netdev per-instance locking

   - batman-adv: fix double-hold of meshif when getting enabled

  Current release - new code bugs:

   - Bluetooth: increment TX timestamping tskey always for stream
     sockets

   - wifi: static analysis and build fixes for the new Intel sub-driver

  Previous releases - regressions:

   - net: fib_rules: fix iif / oif matching on L3 master (VRF) device

   - ipv6: add exception routes to GC list in rt6_insert_exception()

   - netfilter: conntrack: fix erroneous removal of offload bit

   - Bluetooth:
       - fix sending MGMT_EV_DEVICE_FOUND for invalid address
       - l2cap: process valid commands in too long frame
       - btnxpuart: Revert baudrate change in nxp_shutdown

  Previous releases - always broken:

   - ethtool: fix memory corruption during SFP FW flashing

   - eth:
       - hibmcge: fixes for link and MTU handling, pause frames etc
       - igc: fixes for PTM (PCIe timestamping)

   - dsa: b53: enable BPDU reception for management port

  Misc:

   - fixes for Netlink protocol schemas"

* tag 'net-6.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (81 commits)
  net: ethernet: mtk_eth_soc: revise QDMA packet scheduler settings
  net: ethernet: mtk_eth_soc: correct the max weight of the queue limit for 100Mbps
  net: ethernet: mtk_eth_soc: reapply mdc divider on reset
  net: ti: icss-iep: Fix possible NULL pointer dereference for perout request
  net: ti: icssg-prueth: Fix possible NULL pointer dereference inside emac_xmit_xdp_frame()
  net: ti: icssg-prueth: Fix kernel warning while bringing down network interface
  netfilter: conntrack: fix erronous removal of offload bit
  net: don't try to ops lock uninitialized devs
  ptp: ocp: fix start time alignment in ptp_ocp_signal_set
  net: dsa: avoid refcount warnings when ds->ops->tag_8021q_vlan_del() fails
  net: dsa: free routing table on probe failure
  net: dsa: clean up FDB, MDB, VLAN entries on unbind
  net: dsa: mv88e6xxx: fix -ENOENT when deleting VLANs and MST is unsupported
  net: dsa: mv88e6xxx: avoid unregistering devlink regions which were never registered
  net: txgbe: fix memory leak in txgbe_probe() error path
  net: bridge: switchdev: do not notify new brentries as changed
  net: b53: enable BPDU reception for management port
  netlink: specs: rt-neigh: prefix struct nfmsg members with ndm
  netlink: specs: rt-link: adjust mctp attribute naming
  netlink: specs: rtnetlink: attribute naming corrections
  ...
This commit is contained in:
Linus Torvalds 2025-04-17 11:45:30 -07:00
commit b5c6891b2c
72 changed files with 684 additions and 276 deletions

View File

@ -123,12 +123,12 @@ attribute-sets:
operations:
name-prefix: ovs-vport-cmd-
fixed-header: ovs-header
list:
-
name: new
doc: Create a new OVS vport
attribute-set: vport
fixed-header: ovs-header
do:
request:
attributes:
@ -141,7 +141,6 @@ operations:
name: del
doc: Delete existing OVS vport from a data path
attribute-set: vport
fixed-header: ovs-header
do:
request:
attributes:
@ -152,7 +151,6 @@ operations:
name: get
doc: Get / dump OVS vport configuration and state
attribute-set: vport
fixed-header: ovs-header
do: &vport-get-op
request:
attributes:

View File

@ -1113,11 +1113,10 @@ attribute-sets:
-
name: prop-list
type: nest
nested-attributes: link-attrs
nested-attributes: prop-list-link-attrs
-
name: alt-ifname
type: string
multi-attr: true
-
name: perm-address
type: binary
@ -1163,6 +1162,13 @@ attribute-sets:
-
name: netns-immutable
type: u8
-
name: prop-list-link-attrs
subset-of: link-attrs
attributes:
-
name: alt-ifname
multi-attr: true
-
name: af-spec-attrs
attributes:
@ -1585,7 +1591,7 @@ attribute-sets:
name: nf-call-iptables
type: u8
-
name: nf-call-ip6-tables
name: nf-call-ip6tables
type: u8
-
name: nf-call-arptables
@ -2077,7 +2083,7 @@ attribute-sets:
name: id
type: u16
-
name: flag
name: flags
type: binary
struct: ifla-vlan-flags
-
@ -2165,7 +2171,7 @@ attribute-sets:
type: binary
struct: ifla-cacheinfo
-
name: icmp6-stats
name: icmp6stats
type: binary
struct: ifla-icmp6-stats
-
@ -2179,9 +2185,10 @@ attribute-sets:
type: u32
-
name: mctp-attrs
name-prefix: ifla-mctp-
attributes:
-
name: mctp-net
name: net
type: u32
-
name: phys-binding
@ -2453,7 +2460,6 @@ operations:
- min-mtu
- max-mtu
- prop-list
- alt-ifname
- perm-address
- proto-down-reason
- parent-dev-name

View File

@ -13,25 +13,25 @@ definitions:
type: struct
members:
-
name: family
name: ndm-family
type: u8
-
name: pad
name: ndm-pad
type: pad
len: 3
-
name: ifindex
name: ndm-ifindex
type: s32
-
name: state
name: ndm-state
type: u16
enum: nud-state
-
name: flags
name: ndm-flags
type: u8
enum: ntf-flags
-
name: type
name: ndm-type
type: u8
enum: rtm-type
-
@ -189,7 +189,7 @@ attribute-sets:
type: binary
display-hint: ipv4
-
name: lladr
name: lladdr
type: binary
display-hint: mac
-

View File

@ -6335,6 +6335,7 @@ F: Documentation/process/cve.rst
CW1200 WLAN driver
S: Orphan
L: linux-wireless@vger.kernel.org
F: drivers/net/wireless/st/
F: include/linux/platform_data/net-cw1200.h
@ -14289,6 +14290,7 @@ S: Odd fixes
F: drivers/net/ethernet/marvell/sk*
MARVELL LIBERTAS WIRELESS DRIVER
L: linux-wireless@vger.kernel.org
L: libertas-dev@lists.infradead.org
S: Orphan
F: drivers/net/wireless/marvell/libertas/
@ -19752,6 +19754,7 @@ F: drivers/media/tuners/qt1010*
QUALCOMM ATH12K WIRELESS DRIVER
M: Jeff Johnson <jjohnson@kernel.org>
L: linux-wireless@vger.kernel.org
L: ath12k@lists.infradead.org
S: Supported
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath12k
@ -19761,6 +19764,7 @@ N: ath12k
QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
M: Jeff Johnson <jjohnson@kernel.org>
L: linux-wireless@vger.kernel.org
L: ath10k@lists.infradead.org
S: Supported
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
@ -19770,6 +19774,7 @@ N: ath10k
QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
M: Jeff Johnson <jjohnson@kernel.org>
L: linux-wireless@vger.kernel.org
L: ath11k@lists.infradead.org
S: Supported
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath11k
@ -22143,6 +22148,7 @@ F: drivers/platform/x86/touchscreen_dmi.c
SILICON LABS WIRELESS DRIVERS (for WFxxx series)
M: Jérôme Pouiller <jerome.pouiller@silabs.com>
L: linux-wireless@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml
F: drivers/net/wireless/silabs/

View File

@ -1286,7 +1286,9 @@ static void nxp_coredump(struct hci_dev *hdev)
u8 pcmd = 2;
skb = nxp_drv_send_cmd(hdev, HCI_NXP_TRIGGER_DUMP, 1, &pcmd);
if (!IS_ERR(skb))
if (IS_ERR(skb))
bt_dev_err(hdev, "Failed to trigger FW Dump. (%ld)", PTR_ERR(skb));
else
kfree_skb(skb);
}
@ -1445,9 +1447,6 @@ static int nxp_shutdown(struct hci_dev *hdev)
/* HCI_NXP_IND_RESET command may not returns any response */
if (!IS_ERR(skb))
kfree_skb(skb);
} else if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
nxp_set_baudrate_cmd(hdev, NULL);
}
return 0;
@ -1799,13 +1798,15 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
wake_up_interruptible(&nxpdev->check_boot_sign_wait_q);
wake_up_interruptible(&nxpdev->fw_dnld_done_wait_q);
}
if (test_bit(HCI_RUNNING, &hdev->flags)) {
/* Ensure shutdown callback is executed before unregistering, so
* that baudrate is reset to initial value.
} else {
/* Restore FW baudrate to fw_init_baudrate if changed.
* This will ensure FW baudrate is in sync with
* driver baudrate in case this driver is re-inserted.
*/
nxp_shutdown(hdev);
if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
nxp_set_baudrate_cmd(hdev, NULL);
}
}
ps_cleanup(nxpdev);

View File

@ -889,7 +889,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
if (le32_to_cpu(ver.soc_id) == QCA_WCN3950_SOC_ID_T)
variant = "t";
else if (le32_to_cpu(ver.soc_id) == QCA_WCN3950_SOC_ID_S)
variant = "u";
variant = "s";
snprintf(config.fwname, sizeof(config.fwname),
"qca/cmnv%02x%s.bin", rom_ver, variant);

View File

@ -1215,6 +1215,8 @@ next:
rtl_dev_err(hdev, "mandatory config file %s not found",
btrtl_dev->ic_info->cfg_name);
ret = btrtl_dev->cfg_len;
if (!ret)
ret = -EINVAL;
goto err_free;
}
}

View File

@ -289,18 +289,18 @@ static void vhci_coredump(struct hci_dev *hdev)
static void vhci_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
{
char buf[80];
const char *buf;
snprintf(buf, sizeof(buf), "Controller Name: vhci_ctrl\n");
buf = "Controller Name: vhci_ctrl\n";
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Firmware Version: vhci_fw\n");
buf = "Firmware Version: vhci_fw\n";
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Driver: vhci_drv\n");
buf = "Driver: vhci_drv\n";
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Vendor: vhci\n");
buf = "Vendor: vhci\n";
skb_put_data(skb, buf, strlen(buf));
}

View File

@ -850,8 +850,9 @@ static int bond_check_dev_link(struct bonding *bond,
struct net_device *slave_dev, int reporting)
{
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
struct ifreq ifr;
struct mii_ioctl_data *mii;
struct ifreq ifr;
int ret;
if (!reporting && !netif_running(slave_dev))
return 0;
@ -860,9 +861,13 @@ static int bond_check_dev_link(struct bonding *bond,
return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
/* Try to get link status using Ethtool first. */
if (slave_dev->ethtool_ops->get_link)
return slave_dev->ethtool_ops->get_link(slave_dev) ?
BMSR_LSTATUS : 0;
if (slave_dev->ethtool_ops->get_link) {
netdev_lock_ops(slave_dev);
ret = slave_dev->ethtool_ops->get_link(slave_dev);
netdev_unlock_ops(slave_dev);
return ret ? BMSR_LSTATUS : 0;
}
/* Ethtool can't be used, fallback to MII ioctls. */
if (slave_ops->ndo_eth_ioctl) {

View File

@ -902,15 +902,16 @@ static int rkcanfd_probe(struct platform_device *pdev)
priv->can.data_bittiming_const = &rkcanfd_data_bittiming_const;
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_BERR_REPORTING;
if (!(priv->devtype_data.quirks & RKCANFD_QUIRK_CANFD_BROKEN))
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
priv->can.do_set_mode = rkcanfd_set_mode;
priv->can.do_get_berr_counter = rkcanfd_get_berr_counter;
priv->ndev = ndev;
match = device_get_match_data(&pdev->dev);
if (match)
if (match) {
priv->devtype_data = *(struct rkcanfd_devtype_data *)match;
if (!(priv->devtype_data.quirks & RKCANFD_QUIRK_CANFD_BROKEN))
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
}
err = can_rx_offload_add_manual(ndev, &priv->offload,
RKCANFD_NAPI_WEIGHT);

View File

@ -737,6 +737,15 @@ static void b53_enable_mib(struct b53_device *dev)
b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc);
}
static void b53_enable_stp(struct b53_device *dev)
{
u8 gc;
b53_read8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, &gc);
gc |= GC_RX_BPDU_EN;
b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc);
}
static u16 b53_default_pvid(struct b53_device *dev)
{
if (is5325(dev) || is5365(dev))
@ -876,6 +885,7 @@ static int b53_switch_reset(struct b53_device *dev)
}
b53_enable_mib(dev);
b53_enable_stp(dev);
return b53_flush_arl(dev, FAST_AGE_STATIC);
}

View File

@ -1852,6 +1852,8 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
if (!chip->info->ops->vtu_getnext)
return -EOPNOTSUPP;
memset(entry, 0, sizeof(*entry));
entry->vid = vid ? vid - 1 : mv88e6xxx_max_vid(chip);
entry->valid = false;
@ -1960,7 +1962,16 @@ static int mv88e6xxx_mst_put(struct mv88e6xxx_chip *chip, u8 sid)
struct mv88e6xxx_mst *mst, *tmp;
int err;
if (!sid)
/* If the SID is zero, it is for a VLAN mapped to the default MSTI,
* and mv88e6xxx_stu_setup() made sure it is always present, and thus,
* should not be removed here.
*
* If the chip lacks STU support, numerically the "sid" variable will
* happen to also be zero, but we don't want to rely on that fact, so
* we explicitly test that first. In that case, there is also nothing
* to do here.
*/
if (!mv88e6xxx_has_stu(chip) || !sid)
return 0;
list_for_each_entry_safe(mst, tmp, &chip->msts, node) {

View File

@ -736,7 +736,8 @@ void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds)
int i;
for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++)
dsa_devlink_region_destroy(chip->regions[i]);
if (chip->regions[i])
dsa_devlink_region_destroy(chip->regions[i]);
}
void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port)

View File

@ -154,8 +154,9 @@ void pdsc_debugfs_add_qcq(struct pdsc *pdsc, struct pdsc_qcq *qcq)
debugfs_create_u32("index", 0400, intr_dentry, &intr->index);
debugfs_create_u32("vector", 0400, intr_dentry, &intr->vector);
intr_ctrl_regset = kzalloc(sizeof(*intr_ctrl_regset),
GFP_KERNEL);
intr_ctrl_regset = devm_kzalloc(pdsc->dev,
sizeof(*intr_ctrl_regset),
GFP_KERNEL);
if (!intr_ctrl_regset)
return;
intr_ctrl_regset->regs = intr_ctrl_regs;

View File

@ -787,7 +787,7 @@ tx_free:
dev_kfree_skb_any(skb);
tx_kick_pending:
if (BNXT_TX_PTP_IS_SET(lflags)) {
txr->tx_buf_ring[txr->tx_prod].is_ts_pkt = 0;
txr->tx_buf_ring[RING_TX(bp, txr->tx_prod)].is_ts_pkt = 0;
atomic64_inc(&bp->ptp_cfg->stats.ts_err);
if (!(bp->fw_cap & BNXT_FW_CAP_TX_TS_CMP))
/* set SKB to err so PTP worker will clean up */
@ -795,7 +795,7 @@ tx_kick_pending:
}
if (txr->kick_pending)
bnxt_txr_db_kick(bp, txr, txr->tx_prod);
txr->tx_buf_ring[txr->tx_prod].skb = NULL;
txr->tx_buf_ring[RING_TX(bp, txr->tx_prod)].skb = NULL;
dev_core_stats_tx_dropped_inc(dev);
return NETDEV_TX_OK;
}

View File

@ -2270,6 +2270,7 @@ int cxgb4_init_ethtool_filters(struct adapter *adap)
eth_filter->port[i].bmap = bitmap_zalloc(nentries, GFP_KERNEL);
if (!eth_filter->port[i].bmap) {
ret = -ENOMEM;
kvfree(eth_filter->port[i].loc_array);
goto free_eth_finfo;
}
}

View File

@ -108,14 +108,16 @@ struct hbg_irq_info {
bool re_enable;
bool need_print;
bool need_reset;
u64 count;
void (*irq_handle)(struct hbg_priv *priv, struct hbg_irq_info *info);
void (*irq_handle)(struct hbg_priv *priv,
const struct hbg_irq_info *info);
};
struct hbg_vector {
char name[HBG_VECTOR_NUM][32];
struct hbg_irq_info *info_array;
u64 *stats_array;
const struct hbg_irq_info *info_array;
u32 info_array_len;
};

View File

@ -61,7 +61,7 @@ static int hbg_dbg_irq_info(struct seq_file *s, void *unused)
{
struct net_device *netdev = dev_get_drvdata(s->private);
struct hbg_priv *priv = netdev_priv(netdev);
struct hbg_irq_info *info;
const struct hbg_irq_info *info;
u32 i;
for (i = 0; i < priv->vectors.info_array_len; i++) {
@ -73,7 +73,7 @@ static int hbg_dbg_irq_info(struct seq_file *s, void *unused)
info->mask)),
str_true_false(info->need_reset),
str_true_false(info->need_print),
info->count);
priv->vectors.stats_array[i]);
}
return 0;
@ -106,6 +106,7 @@ static int hbg_dbg_nic_state(struct seq_file *s, void *unused)
{
struct net_device *netdev = dev_get_drvdata(s->private);
struct hbg_priv *priv = netdev_priv(netdev);
bool np_link_fail;
seq_printf(s, "event handling state: %s\n",
state_str_true_false(priv, HBG_NIC_STATE_EVENT_HANDLING));
@ -117,8 +118,10 @@ static int hbg_dbg_nic_state(struct seq_file *s, void *unused)
reset_type_str[priv->reset_type]);
seq_printf(s, "need reset state: %s\n",
state_str_true_false(priv, HBG_NIC_STATE_NEED_RESET));
seq_printf(s, "np_link fail state: %s\n",
state_str_true_false(priv, HBG_NIC_STATE_NP_LINK_FAIL));
np_link_fail = !hbg_reg_read_field(priv, HBG_REG_AN_NEG_STATE_ADDR,
HBG_REG_AN_NEG_STATE_NP_LINK_OK_B);
seq_printf(s, "np_link fail state: %s\n", str_true_false(np_link_fail));
return 0;
}

View File

@ -234,7 +234,7 @@ static u64 hbg_get_irq_stats(struct hbg_vector *vectors, u32 mask)
for (i = 0; i < vectors->info_array_len; i++)
if (vectors->info_array[i].mask == mask)
return vectors->info_array[i].count;
return vectors->stats_array[i];
return 0;
}

View File

@ -26,12 +26,15 @@ static void hbg_restore_mac_table(struct hbg_priv *priv)
static void hbg_restore_user_def_settings(struct hbg_priv *priv)
{
/* The index of host mac is always 0. */
u64 rx_pause_addr = ether_addr_to_u64(priv->filter.mac_table[0].addr);
struct ethtool_pauseparam *pause_param = &priv->user_def.pause_param;
hbg_restore_mac_table(priv);
hbg_hw_set_mtu(priv, priv->netdev->mtu);
hbg_hw_set_pause_enable(priv, pause_param->tx_pause,
pause_param->rx_pause);
hbg_hw_set_rx_pause_mac_addr(priv, rx_pause_addr);
}
int hbg_rebuild(struct hbg_priv *priv)

View File

@ -234,6 +234,10 @@ void hbg_hw_set_mac_filter_enable(struct hbg_priv *priv, u32 enable)
{
hbg_reg_write_field(priv, HBG_REG_REC_FILT_CTRL_ADDR,
HBG_REG_REC_FILT_CTRL_UC_MATCH_EN_B, enable);
/* only uc filter is supported, so set all bits of mc mask reg to 1 */
hbg_reg_write64(priv, HBG_REG_STATION_ADDR_LOW_MSK_0, U64_MAX);
hbg_reg_write64(priv, HBG_REG_STATION_ADDR_LOW_MSK_1, U64_MAX);
}
void hbg_hw_set_pause_enable(struct hbg_priv *priv, u32 tx_en, u32 rx_en)
@ -242,6 +246,9 @@ void hbg_hw_set_pause_enable(struct hbg_priv *priv, u32 tx_en, u32 rx_en)
HBG_REG_PAUSE_ENABLE_TX_B, tx_en);
hbg_reg_write_field(priv, HBG_REG_PAUSE_ENABLE_ADDR,
HBG_REG_PAUSE_ENABLE_RX_B, rx_en);
hbg_reg_write_field(priv, HBG_REG_REC_FILT_CTRL_ADDR,
HBG_REG_REC_FILT_CTRL_PAUSE_FRM_PASS_B, rx_en);
}
void hbg_hw_get_pause_enable(struct hbg_priv *priv, u32 *tx_en, u32 *rx_en)

View File

@ -6,7 +6,7 @@
#include "hbg_hw.h"
static void hbg_irq_handle_err(struct hbg_priv *priv,
struct hbg_irq_info *irq_info)
const struct hbg_irq_info *irq_info)
{
if (irq_info->need_print)
dev_err(&priv->pdev->dev,
@ -17,30 +17,30 @@ static void hbg_irq_handle_err(struct hbg_priv *priv,
}
static void hbg_irq_handle_tx(struct hbg_priv *priv,
struct hbg_irq_info *irq_info)
const struct hbg_irq_info *irq_info)
{
napi_schedule(&priv->tx_ring.napi);
}
static void hbg_irq_handle_rx(struct hbg_priv *priv,
struct hbg_irq_info *irq_info)
const struct hbg_irq_info *irq_info)
{
napi_schedule(&priv->rx_ring.napi);
}
static void hbg_irq_handle_rx_buf_val(struct hbg_priv *priv,
struct hbg_irq_info *irq_info)
const struct hbg_irq_info *irq_info)
{
priv->stats.rx_fifo_less_empty_thrsld_cnt++;
}
#define HBG_IRQ_I(name, handle) \
{#name, HBG_INT_MSK_##name##_B, false, false, false, 0, handle}
{#name, HBG_INT_MSK_##name##_B, false, false, false, handle}
#define HBG_ERR_IRQ_I(name, need_print, ndde_reset) \
{#name, HBG_INT_MSK_##name##_B, true, need_print, \
ndde_reset, 0, hbg_irq_handle_err}
ndde_reset, hbg_irq_handle_err}
static struct hbg_irq_info hbg_irqs[] = {
static const struct hbg_irq_info hbg_irqs[] = {
HBG_IRQ_I(RX, hbg_irq_handle_rx),
HBG_IRQ_I(TX, hbg_irq_handle_tx),
HBG_ERR_IRQ_I(TX_PKT_CPL, true, true),
@ -64,7 +64,7 @@ static struct hbg_irq_info hbg_irqs[] = {
static irqreturn_t hbg_irq_handle(int irq_num, void *p)
{
struct hbg_irq_info *info;
const struct hbg_irq_info *info;
struct hbg_priv *priv = p;
u32 status;
u32 i;
@ -79,7 +79,7 @@ static irqreturn_t hbg_irq_handle(int irq_num, void *p)
hbg_hw_irq_enable(priv, info->mask, false);
hbg_hw_irq_clear(priv, info->mask);
info->count++;
priv->vectors.stats_array[i]++;
if (info->irq_handle)
info->irq_handle(priv, info);
@ -132,6 +132,12 @@ int hbg_irq_init(struct hbg_priv *priv)
irq_names_map[i]);
}
vectors->stats_array = devm_kcalloc(&priv->pdev->dev,
ARRAY_SIZE(hbg_irqs),
sizeof(u64), GFP_KERNEL);
if (!vectors->stats_array)
return -ENOMEM;
vectors->info_array = hbg_irqs;
vectors->info_array_len = ARRAY_SIZE(hbg_irqs);
return 0;

View File

@ -21,7 +21,7 @@
static void hbg_all_irq_enable(struct hbg_priv *priv, bool enabled)
{
struct hbg_irq_info *info;
const struct hbg_irq_info *info;
u32 i;
for (i = 0; i < priv->vectors.info_array_len; i++) {
@ -203,12 +203,12 @@ static int hbg_net_change_mtu(struct net_device *netdev, int new_mtu)
if (netif_running(netdev))
return -EBUSY;
hbg_hw_set_mtu(priv, new_mtu);
WRITE_ONCE(netdev->mtu, new_mtu);
dev_dbg(&priv->pdev->dev,
"change mtu from %u to %u\n", netdev->mtu, new_mtu);
hbg_hw_set_mtu(priv, new_mtu);
WRITE_ONCE(netdev->mtu, new_mtu);
return 0;
}

View File

@ -2,6 +2,7 @@
// Copyright (c) 2024 Hisilicon Limited.
#include <linux/phy.h>
#include <linux/rtnetlink.h>
#include "hbg_common.h"
#include "hbg_hw.h"
#include "hbg_mdio.h"
@ -133,12 +134,17 @@ void hbg_fix_np_link_fail(struct hbg_priv *priv)
{
struct device *dev = &priv->pdev->dev;
rtnl_lock();
if (priv->stats.np_link_fail_cnt >= HBG_NP_LINK_FAIL_RETRY_TIMES) {
dev_err(dev, "failed to fix the MAC link status\n");
priv->stats.np_link_fail_cnt = 0;
return;
goto unlock;
}
if (!priv->mac.phydev->link)
goto unlock;
priv->stats.np_link_fail_cnt++;
dev_err(dev, "failed to link between MAC and PHY, try to fix...\n");
@ -147,6 +153,9 @@ void hbg_fix_np_link_fail(struct hbg_priv *priv)
*/
hbg_phy_stop(priv);
hbg_phy_start(priv);
unlock:
rtnl_unlock();
}
static void hbg_phy_adjust_link(struct net_device *netdev)

View File

@ -68,6 +68,7 @@
#define HBG_REG_TRANSMIT_CTRL_AN_EN_B BIT(5)
#define HBG_REG_REC_FILT_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x0064)
#define HBG_REG_REC_FILT_CTRL_UC_MATCH_EN_B BIT(0)
#define HBG_REG_REC_FILT_CTRL_PAUSE_FRM_PASS_B BIT(4)
#define HBG_REG_RX_OCTETS_TOTAL_OK_ADDR (HBG_REG_SGMII_BASE + 0x0080)
#define HBG_REG_RX_OCTETS_BAD_ADDR (HBG_REG_SGMII_BASE + 0x0084)
#define HBG_REG_RX_UC_PKTS_ADDR (HBG_REG_SGMII_BASE + 0x0088)
@ -134,6 +135,8 @@
#define HBG_REG_STATION_ADDR_HIGH_4_ADDR (HBG_REG_SGMII_BASE + 0x0224)
#define HBG_REG_STATION_ADDR_LOW_5_ADDR (HBG_REG_SGMII_BASE + 0x0228)
#define HBG_REG_STATION_ADDR_HIGH_5_ADDR (HBG_REG_SGMII_BASE + 0x022C)
#define HBG_REG_STATION_ADDR_LOW_MSK_0 (HBG_REG_SGMII_BASE + 0x0230)
#define HBG_REG_STATION_ADDR_LOW_MSK_1 (HBG_REG_SGMII_BASE + 0x0238)
/* PCU */
#define HBG_REG_TX_FIFO_THRSLD_ADDR (HBG_REG_SGMII_BASE + 0x0420)

View File

@ -319,6 +319,7 @@ struct igc_adapter {
struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
ktime_t ptp_reset_start; /* Reset time in clock mono */
struct system_time_snapshot snapshot;
struct mutex ptm_lock; /* Only allow one PTM transaction at a time */
char fw_version[32];

View File

@ -574,7 +574,10 @@
#define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x3f) << 2)
#define IGC_PTM_CTRL_PTM_TO(usec) (((usec) & 0xff) << 8)
#define IGC_PTM_SHORT_CYC_DEFAULT 1 /* Default short cycle interval */
/* A short cycle time of 1us theoretically should work, but appears to be too
* short in practice.
*/
#define IGC_PTM_SHORT_CYC_DEFAULT 4 /* Default short cycle interval */
#define IGC_PTM_CYC_TIME_DEFAULT 5 /* Default PTM cycle time */
#define IGC_PTM_TIMEOUT_DEFAULT 255 /* Default timeout for PTM errors */
@ -593,6 +596,7 @@
#define IGC_PTM_STAT_T4M1_OVFL BIT(3) /* T4 minus T1 overflow */
#define IGC_PTM_STAT_ADJUST_1ST BIT(4) /* 1588 timer adjusted during 1st PTM cycle */
#define IGC_PTM_STAT_ADJUST_CYC BIT(5) /* 1588 timer adjusted during non-1st PTM cycle */
#define IGC_PTM_STAT_ALL GENMASK(5, 0) /* Used to clear all status */
/* PCIe PTM Cycle Control */
#define IGC_PTM_CYCLE_CTRL_CYC_TIME(msec) ((msec) & 0x3ff) /* PTM Cycle Time (msec) */

View File

@ -7231,6 +7231,7 @@ static int igc_probe(struct pci_dev *pdev,
err_register:
igc_release_hw_control(adapter);
igc_ptp_stop(adapter);
err_eeprom:
if (!igc_check_reset_block(hw))
igc_reset_phy(hw);

View File

@ -974,45 +974,62 @@ static void igc_ptm_log_error(struct igc_adapter *adapter, u32 ptm_stat)
}
}
/* The PTM lock: adapter->ptm_lock must be held when calling igc_ptm_trigger() */
static void igc_ptm_trigger(struct igc_hw *hw)
{
u32 ctrl;
/* To "manually" start the PTM cycle we need to set the
* trigger (TRIG) bit
*/
ctrl = rd32(IGC_PTM_CTRL);
ctrl |= IGC_PTM_CTRL_TRIG;
wr32(IGC_PTM_CTRL, ctrl);
/* Perform flush after write to CTRL register otherwise
* transaction may not start
*/
wrfl();
}
/* The PTM lock: adapter->ptm_lock must be held when calling igc_ptm_reset() */
static void igc_ptm_reset(struct igc_hw *hw)
{
u32 ctrl;
ctrl = rd32(IGC_PTM_CTRL);
ctrl &= ~IGC_PTM_CTRL_TRIG;
wr32(IGC_PTM_CTRL, ctrl);
/* Write to clear all status */
wr32(IGC_PTM_STAT, IGC_PTM_STAT_ALL);
}
static int igc_phc_get_syncdevicetime(ktime_t *device,
struct system_counterval_t *system,
void *ctx)
{
u32 stat, t2_curr_h, t2_curr_l, ctrl;
struct igc_adapter *adapter = ctx;
struct igc_hw *hw = &adapter->hw;
u32 stat, t2_curr_h, t2_curr_l;
int err, count = 100;
ktime_t t1, t2_curr;
/* Get a snapshot of system clocks to use as historic value. */
ktime_get_snapshot(&adapter->snapshot);
/* Doing this in a loop because in the event of a
* badly timed (ha!) system clock adjustment, we may
* get PTM errors from the PCI root, but these errors
* are transitory. Repeating the process returns valid
* data eventually.
*/
do {
/* Doing this in a loop because in the event of a
* badly timed (ha!) system clock adjustment, we may
* get PTM errors from the PCI root, but these errors
* are transitory. Repeating the process returns valid
* data eventually.
*/
/* Get a snapshot of system clocks to use as historic value. */
ktime_get_snapshot(&adapter->snapshot);
/* To "manually" start the PTM cycle we need to clear and
* then set again the TRIG bit.
*/
ctrl = rd32(IGC_PTM_CTRL);
ctrl &= ~IGC_PTM_CTRL_TRIG;
wr32(IGC_PTM_CTRL, ctrl);
ctrl |= IGC_PTM_CTRL_TRIG;
wr32(IGC_PTM_CTRL, ctrl);
/* The cycle only starts "for real" when software notifies
* that it has read the registers, this is done by setting
* VALID bit.
*/
wr32(IGC_PTM_STAT, IGC_PTM_STAT_VALID);
igc_ptm_trigger(hw);
err = readx_poll_timeout(rd32, IGC_PTM_STAT, stat,
stat, IGC_PTM_STAT_SLEEP,
IGC_PTM_STAT_TIMEOUT);
igc_ptm_reset(hw);
if (err < 0) {
netdev_err(adapter->netdev, "Timeout reading IGC_PTM_STAT register\n");
return err;
@ -1021,15 +1038,7 @@ static int igc_phc_get_syncdevicetime(ktime_t *device,
if ((stat & IGC_PTM_STAT_VALID) == IGC_PTM_STAT_VALID)
break;
if (stat & ~IGC_PTM_STAT_VALID) {
/* An error occurred, log it. */
igc_ptm_log_error(adapter, stat);
/* The STAT register is write-1-to-clear (W1C),
* so write the previous error status to clear it.
*/
wr32(IGC_PTM_STAT, stat);
continue;
}
igc_ptm_log_error(adapter, stat);
} while (--count);
if (!count) {
@ -1061,9 +1070,16 @@ static int igc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
{
struct igc_adapter *adapter = container_of(ptp, struct igc_adapter,
ptp_caps);
int ret;
return get_device_system_crosststamp(igc_phc_get_syncdevicetime,
adapter, &adapter->snapshot, cts);
/* This blocks until any in progress PTM transactions complete */
mutex_lock(&adapter->ptm_lock);
ret = get_device_system_crosststamp(igc_phc_get_syncdevicetime,
adapter, &adapter->snapshot, cts);
mutex_unlock(&adapter->ptm_lock);
return ret;
}
static int igc_ptp_getcyclesx64(struct ptp_clock_info *ptp,
@ -1162,6 +1178,7 @@ void igc_ptp_init(struct igc_adapter *adapter)
spin_lock_init(&adapter->ptp_tx_lock);
spin_lock_init(&adapter->free_timer_lock);
spin_lock_init(&adapter->tmreg_lock);
mutex_init(&adapter->ptm_lock);
adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
@ -1174,6 +1191,7 @@ void igc_ptp_init(struct igc_adapter *adapter)
if (IS_ERR(adapter->ptp_clock)) {
adapter->ptp_clock = NULL;
netdev_err(netdev, "ptp_clock_register failed\n");
mutex_destroy(&adapter->ptm_lock);
} else if (adapter->ptp_clock) {
netdev_info(netdev, "PHC added\n");
adapter->ptp_flags |= IGC_PTP_ENABLED;
@ -1203,10 +1221,12 @@ static void igc_ptm_stop(struct igc_adapter *adapter)
struct igc_hw *hw = &adapter->hw;
u32 ctrl;
mutex_lock(&adapter->ptm_lock);
ctrl = rd32(IGC_PTM_CTRL);
ctrl &= ~IGC_PTM_CTRL_EN;
wr32(IGC_PTM_CTRL, ctrl);
mutex_unlock(&adapter->ptm_lock);
}
/**
@ -1237,13 +1257,18 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
**/
void igc_ptp_stop(struct igc_adapter *adapter)
{
if (!(adapter->ptp_flags & IGC_PTP_ENABLED))
return;
igc_ptp_suspend(adapter);
adapter->ptp_flags &= ~IGC_PTP_ENABLED;
if (adapter->ptp_clock) {
ptp_clock_unregister(adapter->ptp_clock);
netdev_info(adapter->netdev, "PHC removed\n");
adapter->ptp_flags &= ~IGC_PTP_ENABLED;
}
mutex_destroy(&adapter->ptm_lock);
}
/**
@ -1255,10 +1280,13 @@ void igc_ptp_stop(struct igc_adapter *adapter)
void igc_ptp_reset(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
u32 cycle_ctrl, ctrl;
u32 cycle_ctrl, ctrl, stat;
unsigned long flags;
u32 timadj;
if (!(adapter->ptp_flags & IGC_PTP_ENABLED))
return;
/* reset the tstamp_config */
igc_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config);
@ -1280,6 +1308,7 @@ void igc_ptp_reset(struct igc_adapter *adapter)
if (!igc_is_crosststamp_supported(adapter))
break;
mutex_lock(&adapter->ptm_lock);
wr32(IGC_PCIE_DIG_DELAY, IGC_PCIE_DIG_DELAY_DEFAULT);
wr32(IGC_PCIE_PHY_DELAY, IGC_PCIE_PHY_DELAY_DEFAULT);
@ -1290,14 +1319,20 @@ void igc_ptp_reset(struct igc_adapter *adapter)
ctrl = IGC_PTM_CTRL_EN |
IGC_PTM_CTRL_START_NOW |
IGC_PTM_CTRL_SHRT_CYC(IGC_PTM_SHORT_CYC_DEFAULT) |
IGC_PTM_CTRL_PTM_TO(IGC_PTM_TIMEOUT_DEFAULT) |
IGC_PTM_CTRL_TRIG;
IGC_PTM_CTRL_PTM_TO(IGC_PTM_TIMEOUT_DEFAULT);
wr32(IGC_PTM_CTRL, ctrl);
/* Force the first cycle to run. */
wr32(IGC_PTM_STAT, IGC_PTM_STAT_VALID);
igc_ptm_trigger(hw);
if (readx_poll_timeout_atomic(rd32, IGC_PTM_STAT, stat,
stat, IGC_PTM_STAT_SLEEP,
IGC_PTM_STAT_TIMEOUT))
netdev_err(adapter->netdev, "Timeout reading IGC_PTM_STAT register\n");
igc_ptm_reset(hw);
mutex_unlock(&adapter->ptm_lock);
break;
default:
/* No work to do. */

View File

@ -67,6 +67,8 @@ static int rvu_rep_mcam_flow_init(struct rep_dev *rep)
rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
(&priv->mbox.mbox, 0, &req->hdr);
if (IS_ERR(rsp))
goto exit;
for (ent = 0; ent < rsp->count; ent++)
rep->flow_cfg->flow_ent[ent + allocated] = rsp->entry_list[ent];

View File

@ -734,7 +734,7 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
case SPEED_100:
val |= MTK_QTX_SCH_MAX_RATE_EN |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3);
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3) |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
break;
case SPEED_1000:
@ -757,13 +757,13 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
case SPEED_100:
val |= MTK_QTX_SCH_MAX_RATE_EN |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5);
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
break;
case SPEED_1000:
val |= MTK_QTX_SCH_MAX_RATE_EN |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 10) |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 6) |
FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10);
break;
default:
@ -871,9 +871,25 @@ static const struct phylink_mac_ops mtk_phylink_ops = {
.mac_enable_tx_lpi = mtk_mac_enable_tx_lpi,
};
static void mtk_mdio_config(struct mtk_eth *eth)
{
u32 val;
/* Configure MDC Divider */
val = FIELD_PREP(PPSC_MDC_CFG, eth->mdc_divider);
/* Configure MDC Turbo Mode */
if (mtk_is_netsys_v3_or_greater(eth))
mtk_m32(eth, 0, MISC_MDC_TURBO, MTK_MAC_MISC_V3);
else
val |= PPSC_MDC_TURBO;
mtk_m32(eth, PPSC_MDC_CFG, val, MTK_PPSC);
}
static int mtk_mdio_init(struct mtk_eth *eth)
{
unsigned int max_clk = 2500000, divider;
unsigned int max_clk = 2500000;
struct device_node *mii_np;
int ret;
u32 val;
@ -908,20 +924,9 @@ static int mtk_mdio_init(struct mtk_eth *eth)
}
max_clk = val;
}
divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63);
/* Configure MDC Turbo Mode */
if (mtk_is_netsys_v3_or_greater(eth))
mtk_m32(eth, 0, MISC_MDC_TURBO, MTK_MAC_MISC_V3);
/* Configure MDC Divider */
val = FIELD_PREP(PPSC_MDC_CFG, divider);
if (!mtk_is_netsys_v3_or_greater(eth))
val |= PPSC_MDC_TURBO;
mtk_m32(eth, PPSC_MDC_CFG, val, MTK_PPSC);
dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider);
eth->mdc_divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63);
mtk_mdio_config(eth);
dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / eth->mdc_divider);
ret = of_mdiobus_register(eth->mii_bus, mii_np);
err_put_node:
@ -3315,7 +3320,7 @@ static int mtk_start_dma(struct mtk_eth *eth)
if (mtk_is_netsys_v2_or_greater(eth))
val |= MTK_MUTLI_CNT | MTK_RESV_BUF |
MTK_WCOMP_EN | MTK_DMAD_WR_WDONE |
MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN;
MTK_CHK_DDONE_EN;
else
val |= MTK_RX_BT_32DWORDS;
mtk_w32(eth, val, reg_map->qdma.glo_cfg);
@ -3974,6 +3979,10 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset)
else
mtk_hw_reset(eth);
/* No MT7628/88 support yet */
if (reset && !MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
mtk_mdio_config(eth);
if (mtk_is_netsys_v3_or_greater(eth)) {
/* Set FE to PDMAv2 if necessary */
val = mtk_r32(eth, MTK_FE_GLO_MISC);

View File

@ -1271,6 +1271,7 @@ struct mtk_eth {
struct clk *clks[MTK_CLK_MAX];
struct mii_bus *mii_bus;
unsigned int mdc_divider;
struct work_struct pending_work;
unsigned long state;

View File

@ -2666,7 +2666,7 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
of_property_read_bool(port_np, "ti,mac-only");
/* get phy/link info */
port->slave.port_np = port_np;
port->slave.port_np = of_node_get(port_np);
ret = of_get_phy_mode(port_np, &port->slave.phy_if);
if (ret) {
dev_err(dev, "%pOF read phy-mode err %d\n",
@ -2720,6 +2720,17 @@ static void am65_cpsw_nuss_phylink_cleanup(struct am65_cpsw_common *common)
}
}
static void am65_cpsw_remove_dt(struct am65_cpsw_common *common)
{
struct am65_cpsw_port *port;
int i;
for (i = 0; i < common->port_num; i++) {
port = &common->ports[i];
of_node_put(port->slave.port_np);
}
}
static int
am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
{
@ -3622,6 +3633,7 @@ err_ndevs_clear:
am65_cpsw_nuss_cleanup_ndev(common);
am65_cpsw_nuss_phylink_cleanup(common);
am65_cpts_release(common->cpts);
am65_cpsw_remove_dt(common);
err_of_clear:
if (common->mdio_dev)
of_platform_device_destroy(common->mdio_dev, NULL);
@ -3661,6 +3673,7 @@ static void am65_cpsw_nuss_remove(struct platform_device *pdev)
am65_cpsw_nuss_phylink_cleanup(common);
am65_cpts_release(common->cpts);
am65_cpsw_disable_serdes_phy(common);
am65_cpsw_remove_dt(common);
if (common->mdio_dev)
of_platform_device_destroy(common->mdio_dev, NULL);

View File

@ -412,6 +412,22 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
int ret;
u64 cmp;
if (!on) {
/* Disable CMP 1 */
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
IEP_CMP_CFG_CMP_EN(1), 0);
/* clear CMP regs */
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);
/* Disable sync */
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0);
return 0;
}
/* Calculate width of the signal for PPS/PEROUT handling */
ts.tv_sec = req->on.sec;
ts.tv_nsec = req->on.nsec;
@ -430,64 +446,39 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
if (ret)
return ret;
if (on) {
/* Configure CMP */
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp));
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp));
/* Configure SYNC, based on req on width */
regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
div_u64(ns_width, iep->def_inc));
regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
div_u64(ns_start, iep->def_inc));
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
/* Enable CMP 1 */
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
} else {
/* Disable CMP 1 */
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
IEP_CMP_CFG_CMP_EN(1), 0);
/* clear regs */
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);
}
/* Configure CMP */
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp));
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp));
/* Configure SYNC, based on req on width */
regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
div_u64(ns_width, iep->def_inc));
regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
div_u64(ns_start, iep->def_inc));
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
/* Enable CMP 1 */
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
} else {
if (on) {
u64 start_ns;
u64 start_ns;
iep->period = ((u64)req->period.sec * NSEC_PER_SEC) +
req->period.nsec;
start_ns = ((u64)req->period.sec * NSEC_PER_SEC)
+ req->period.nsec;
icss_iep_update_to_next_boundary(iep, start_ns);
iep->period = ((u64)req->period.sec * NSEC_PER_SEC) +
req->period.nsec;
start_ns = ((u64)req->period.sec * NSEC_PER_SEC)
+ req->period.nsec;
icss_iep_update_to_next_boundary(iep, start_ns);
regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
div_u64(ns_width, iep->def_inc));
regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
div_u64(ns_start, iep->def_inc));
/* Enable Sync in single shot mode */
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
/* Enable CMP 1 */
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
} else {
/* Disable CMP 1 */
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
IEP_CMP_CFG_CMP_EN(1), 0);
/* clear CMP regs */
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);
/* Disable sync */
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0);
}
regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
div_u64(ns_width, iep->def_inc));
regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
div_u64(ns_start, iep->def_inc));
/* Enable Sync in single shot mode */
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
/* Enable CMP 1 */
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
}
return 0;
@ -498,11 +489,21 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
{
int ret = 0;
if (!on)
goto disable;
/* Reject requests with unsupported flags */
if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE |
PTP_PEROUT_PHASE))
return -EOPNOTSUPP;
/* Set default "on" time (1ms) for the signal if not passed by the app */
if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
req->on.sec = 0;
req->on.nsec = NSEC_PER_MSEC;
}
disable:
mutex_lock(&iep->ptp_clk_mutex);
if (iep->pps_enabled) {
@ -513,12 +514,6 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
if (iep->perout_enabled == !!on)
goto exit;
/* Set default "on" time (1ms) for the signal if not passed by the app */
if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
req->on.sec = 0;
req->on.nsec = NSEC_PER_MSEC;
}
ret = icss_iep_perout_enable_hw(iep, req, on);
if (!ret)
iep->perout_enabled = !!on;

View File

@ -583,7 +583,7 @@ u32 emac_xmit_xdp_frame(struct prueth_emac *emac,
first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
if (!first_desc) {
netdev_dbg(ndev, "xdp tx: failed to allocate descriptor\n");
goto drop_free_descs; /* drop */
return ICSSG_XDP_CONSUMED; /* drop */
}
if (page) { /* already DMA mapped by page_pool */
@ -671,8 +671,10 @@ static u32 emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
q_idx = smp_processor_id() % emac->tx_ch_num;
result = emac_xmit_xdp_frame(emac, xdpf, page, q_idx);
if (result == ICSSG_XDP_CONSUMED)
if (result == ICSSG_XDP_CONSUMED) {
ndev->stats.tx_dropped++;
goto drop;
}
dev_sw_netstats_rx_add(ndev, xdpf->len);
return result;
@ -1215,9 +1217,6 @@ void prueth_reset_rx_chan(struct prueth_rx_chn *chn,
prueth_rx_cleanup);
if (disable)
k3_udma_glue_disable_rx_chn(chn->rx_chn);
page_pool_destroy(chn->pg_pool);
chn->pg_pool = NULL;
}
EXPORT_SYMBOL_GPL(prueth_reset_rx_chan);

View File

@ -625,7 +625,7 @@ static int ngbe_probe(struct pci_dev *pdev,
/* setup the private structure */
err = ngbe_sw_init(wx);
if (err)
goto err_free_mac_table;
goto err_pci_release_regions;
/* check if flash load is done after hw power up */
err = wx_check_flash_load(wx, NGBE_SPI_ILDR_STATUS_PERST);
@ -719,6 +719,7 @@ err_register:
err_clear_interrupt_scheme:
wx_clear_interrupt_scheme(wx);
err_free_mac_table:
kfree(wx->rss_key);
kfree(wx->mac_table);
err_pci_release_regions:
pci_release_selected_regions(pdev,

View File

@ -611,7 +611,7 @@ static int txgbe_probe(struct pci_dev *pdev,
/* setup the private structure */
err = txgbe_sw_init(wx);
if (err)
goto err_free_mac_table;
goto err_pci_release_regions;
/* check if flash load is done after hw power up */
err = wx_check_flash_load(wx, TXGBE_SPI_ILDR_STATUS_PERST);
@ -769,6 +769,7 @@ err_release_hw:
wx_clear_interrupt_scheme(wx);
wx_control_hw(wx, false);
err_free_mac_table:
kfree(wx->rss_key);
kfree(wx->mac_table);
err_pci_release_regions:
pci_release_selected_regions(pdev,

View File

@ -2552,7 +2552,7 @@ static void at76_disconnect(struct usb_interface *interface)
wiphy_info(priv->hw->wiphy, "disconnecting\n");
at76_delete_device(priv);
usb_put_dev(priv->udev);
usb_put_dev(interface_to_usbdev(interface));
dev_info(&interface->dev, "disconnected\n");
}

View File

@ -561,8 +561,10 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
if (!found) {
/* No platform data for this device, try OF and DMI data */
brcmf_dmi_probe(settings, chip, chiprev);
if (brcmf_of_probe(dev, bus_type, settings) == -EPROBE_DEFER)
if (brcmf_of_probe(dev, bus_type, settings) == -EPROBE_DEFER) {
kfree(settings);
return ERR_PTR(-EPROBE_DEFER);
}
brcmf_acpi_probe(dev, bus_type, settings);
}
return settings;

View File

@ -1895,7 +1895,6 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld)
int link_id;
int ret;
bool fw_err = false;
bool keep_connection;
lockdep_assert_wiphy(mld->wiphy);
@ -1965,7 +1964,7 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld)
iwl_mld_process_netdetect_res(mld, bss_vif, &resume_data);
mld->netdetect = false;
} else {
keep_connection =
bool keep_connection =
iwl_mld_process_wowlan_status(mld, bss_vif,
resume_data.wowlan_status);
@ -1973,11 +1972,10 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld)
if (keep_connection)
iwl_mld_unblock_emlsr(mld, bss_vif,
IWL_MLD_EMLSR_BLOCKED_WOWLAN);
else
ieee80211_resume_disconnect(bss_vif);
}
if (!mld->netdetect && !keep_connection)
ieee80211_resume_disconnect(bss_vif);
goto out;
err:

View File

@ -396,8 +396,8 @@ static ssize_t iwl_dbgfs_tas_get_status_read(struct iwl_mld *mld, char *buf,
.data[0] = &cmd,
};
struct iwl_dhc_tas_status_resp *resp = NULL;
u32 resp_len = 0;
ssize_t pos = 0;
u32 resp_len;
u32 status;
int ret;

View File

@ -166,7 +166,7 @@ struct iwl_mld_vif {
struct iwl_mld_emlsr emlsr;
#if CONFIG_PM_SLEEP
#ifdef CONFIG_PM_SLEEP
struct iwl_mld_wowlan_data wowlan_data;
#endif
#ifdef CONFIG_IWLWIFI_DEBUGFS

View File

@ -475,8 +475,8 @@ static
int iwl_mld_mac80211_start(struct ieee80211_hw *hw)
{
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
int ret;
bool in_d3 = false;
int ret = 0;
lockdep_assert_wiphy(mld->wiphy);
@ -537,7 +537,8 @@ void iwl_mld_mac80211_stop(struct ieee80211_hw *hw, bool suspend)
/* if the suspend flow fails the fw is in error. Stop it here, and it
* will be started upon wakeup
*/
if (!suspend || iwl_mld_no_wowlan_suspend(mld))
if (!suspend ||
(IS_ENABLED(CONFIG_PM_SLEEP) && iwl_mld_no_wowlan_suspend(mld)))
iwl_mld_stop_fw(mld);
/* HW is stopped, no more coming RX. OTOH, the worker can't run as the
@ -1943,6 +1944,7 @@ static void iwl_mld_sta_rc_update(struct ieee80211_hw *hw,
}
}
#ifdef CONFIG_PM_SLEEP
static void iwl_mld_set_wakeup(struct ieee80211_hw *hw, bool enabled)
{
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
@ -1994,6 +1996,7 @@ static int iwl_mld_resume(struct ieee80211_hw *hw)
return 0;
}
#endif
static int iwl_mld_alloc_ptk_pn(struct iwl_mld *mld,
struct iwl_mld_sta *mld_sta,

View File

@ -147,8 +147,14 @@ static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
return;
if (trans->state >= IWL_TRANS_FW_STARTED &&
trans_pcie->fw_reset_handshake)
trans_pcie->fw_reset_handshake) {
/*
* Reset handshake can dump firmware on timeout, but that
* should assume that the firmware is already dead.
*/
trans->state = IWL_TRANS_NO_FW;
iwl_trans_pcie_fw_reset_handshake(trans);
}
trans_pcie->is_down = true;

View File

@ -342,8 +342,10 @@ void wl1251_tx_work(struct work_struct *work)
while ((skb = skb_dequeue(&wl->tx_queue))) {
if (!woken_up) {
ret = wl1251_ps_elp_wakeup(wl);
if (ret < 0)
if (ret < 0) {
skb_queue_head(&wl->tx_queue, skb);
goto out;
}
woken_up = true;
}

View File

@ -2067,6 +2067,7 @@ ptp_ocp_signal_set(struct ptp_ocp *bp, int gen, struct ptp_ocp_signal *s)
if (!s->start) {
/* roundup() does not work on 32-bit systems */
s->start = DIV64_U64_ROUND_UP(start_ns, s->period);
s->start *= s->period;
s->start = ktime_add(s->start, s->phase);
}

View File

@ -45,6 +45,8 @@ struct fib_rule {
struct fib_rule_port_range dport_range;
u16 sport_mask;
u16 dport_mask;
u8 iif_is_l3_master;
u8 oif_is_l3_master;
struct rcu_head rcu;
};

View File

@ -38,6 +38,7 @@ struct flowi_common {
__u8 flowic_flags;
#define FLOWI_FLAG_ANYSRC 0x01
#define FLOWI_FLAG_KNOWN_NH 0x02
#define FLOWI_FLAG_L3MDEV_OIF 0x04
__u32 flowic_secid;
kuid_t flowic_uid;
__u32 flowic_multipath_hash;

View File

@ -59,6 +59,20 @@ int l3mdev_ifindex_lookup_by_table_id(enum l3mdev_type l3type, struct net *net,
int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
struct fib_lookup_arg *arg);
static inline
bool l3mdev_fib_rule_iif_match(const struct flowi *fl, int iifindex)
{
return !(fl->flowi_flags & FLOWI_FLAG_L3MDEV_OIF) &&
fl->flowi_l3mdev == iifindex;
}
static inline
bool l3mdev_fib_rule_oif_match(const struct flowi *fl, int oifindex)
{
return fl->flowi_flags & FLOWI_FLAG_L3MDEV_OIF &&
fl->flowi_l3mdev == oifindex;
}
void l3mdev_update_flow(struct net *net, struct flowi *fl);
int l3mdev_master_ifindex_rcu(const struct net_device *dev);
@ -327,6 +341,19 @@ int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
{
return 1;
}
static inline
bool l3mdev_fib_rule_iif_match(const struct flowi *fl, int iifindex)
{
return false;
}
static inline
bool l3mdev_fib_rule_oif_match(const struct flowi *fl, int oifindex)
{
return false;
}
static inline
void l3mdev_update_flow(struct net *net, struct flowi *fl)
{

View File

@ -725,7 +725,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
kref_get(&hard_iface->refcount);
dev_hold(mesh_iface);
netdev_hold(mesh_iface, &hard_iface->meshif_dev_tracker, GFP_ATOMIC);
hard_iface->mesh_iface = mesh_iface;
bat_priv = netdev_priv(hard_iface->mesh_iface);

View File

@ -3072,6 +3072,7 @@ void hci_setup_tx_timestamp(struct sk_buff *skb, size_t key_offset,
const struct sockcm_cookie *sockc)
{
struct sock *sk = skb ? skb->sk : NULL;
int key;
/* This shall be called on a single skb of those generated by user
* sendmsg(), and only when the sendmsg() does not return error to
@ -3087,13 +3088,16 @@ void hci_setup_tx_timestamp(struct sk_buff *skb, size_t key_offset,
sock_tx_timestamp(sk, sockc, &skb_shinfo(skb)->tx_flags);
if (sk->sk_type == SOCK_STREAM)
key = atomic_add_return(key_offset, &sk->sk_tskey);
if (sockc->tsflags & SOF_TIMESTAMPING_OPT_ID &&
sockc->tsflags & SOF_TIMESTAMPING_TX_RECORD_MASK) {
if (sockc->tsflags & SOCKCM_FLAG_TS_OPT_ID) {
skb_shinfo(skb)->tskey = sockc->ts_opt_id;
} else {
int key = atomic_add_return(key_offset, &sk->sk_tskey);
if (sk->sk_type != SOCK_STREAM)
key = atomic_inc_return(&sk->sk_tskey);
skb_shinfo(skb)->tskey = key - 1;
}
}

View File

@ -6160,11 +6160,12 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
* event or send an immediate device found event if the data
* should not be stored for later.
*/
if (!ext_adv && !has_pending_adv_report(hdev)) {
if (!has_pending_adv_report(hdev)) {
/* If the report will trigger a SCAN_REQ store it for
* later merging.
*/
if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
if (!ext_adv && (type == LE_ADV_IND ||
type == LE_ADV_SCAN_IND)) {
store_pending_adv_report(hdev, bdaddr, bdaddr_type,
rssi, flags, data, len);
return;

View File

@ -3991,7 +3991,8 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
/* Check if the ACL is secure enough (if not SDP) */
if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
!hci_conn_check_link_mode(conn->hcon)) {
(!hci_conn_check_link_mode(conn->hcon) ||
!l2cap_check_enc_key_size(conn->hcon))) {
conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
result = L2CAP_CR_SEC_BLOCK;
goto response;
@ -7538,8 +7539,24 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
if (skb->len > len) {
BT_ERR("Frame is too long (len %u, expected len %d)",
skb->len, len);
/* PTS test cases L2CAP/COS/CED/BI-14-C and BI-15-C
* (Multiple Signaling Command in one PDU, Data
* Truncated, BR/EDR) send a C-frame to the IUT with
* PDU Length set to 8 and Channel ID set to the
* correct signaling channel for the logical link.
* The Information payload contains one L2CAP_ECHO_REQ
* packet with Data Length set to 0 with 0 octets of
* echo data and one invalid command packet due to
* data truncated in PDU but present in HCI packet.
*
* Shorter the socket buffer to the PDU length to
* allow to process valid commands from the PDU before
* setting the socket unreliable.
*/
skb->len = len;
l2cap_recv_frame(conn, skb);
l2cap_conn_unreliable(conn, ECOMM);
goto drop;
goto unlock;
}
/* Append fragment into frame (with header) */

View File

@ -715,8 +715,8 @@ static int br_vlan_add_existing(struct net_bridge *br,
u16 flags, bool *changed,
struct netlink_ext_ack *extack)
{
bool would_change = __vlan_flags_would_change(vlan, flags);
bool becomes_brentry = false;
bool would_change = false;
int err;
if (!br_vlan_is_brentry(vlan)) {
@ -725,6 +725,8 @@ static int br_vlan_add_existing(struct net_bridge *br,
return -EINVAL;
becomes_brentry = true;
} else {
would_change = __vlan_flags_would_change(vlan, flags);
}
/* Master VLANs that aren't brentries weren't notified before,

View File

@ -655,6 +655,7 @@ static int j1939_sk_release(struct socket *sock)
sock->sk = NULL;
release_sock(sk);
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
sock_put(sk);
return 0;

View File

@ -1520,6 +1520,8 @@ EXPORT_SYMBOL(netdev_features_change);
void netif_state_change(struct net_device *dev)
{
netdev_ops_assert_locked_or_invisible(dev);
if (dev->flags & IFF_UP) {
struct netdev_notifier_change_info change_info = {
.info.dev = dev,
@ -11932,15 +11934,24 @@ void unregister_netdevice_many_notify(struct list_head *head,
BUG_ON(dev->reg_state != NETREG_REGISTERED);
}
/* If device is running, close it first. */
/* If device is running, close it first. Start with ops locked... */
list_for_each_entry(dev, head, unreg_list) {
list_add_tail(&dev->close_list, &close_head);
netdev_lock_ops(dev);
if (netdev_need_ops_lock(dev)) {
list_add_tail(&dev->close_list, &close_head);
netdev_lock(dev);
}
}
dev_close_many(&close_head, true);
/* ... now unlock them and go over the rest. */
list_for_each_entry(dev, head, unreg_list) {
if (netdev_need_ops_lock(dev))
netdev_unlock(dev);
else
list_add_tail(&dev->close_list, &close_head);
}
dev_close_many(&close_head, true);
list_for_each_entry(dev, head, unreg_list) {
netdev_unlock_ops(dev);
/* And unlink it from device chain. */
unlist_netdevice(dev);
netdev_lock(dev);

View File

@ -257,6 +257,24 @@ static int nla_put_port_range(struct sk_buff *skb, int attrtype,
return nla_put(skb, attrtype, sizeof(*range), range);
}
static bool fib_rule_iif_match(const struct fib_rule *rule, int iifindex,
const struct flowi *fl)
{
u8 iif_is_l3_master = READ_ONCE(rule->iif_is_l3_master);
return iif_is_l3_master ? l3mdev_fib_rule_iif_match(fl, iifindex) :
fl->flowi_iif == iifindex;
}
static bool fib_rule_oif_match(const struct fib_rule *rule, int oifindex,
const struct flowi *fl)
{
u8 oif_is_l3_master = READ_ONCE(rule->oif_is_l3_master);
return oif_is_l3_master ? l3mdev_fib_rule_oif_match(fl, oifindex) :
fl->flowi_oif == oifindex;
}
static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
struct flowi *fl, int flags,
struct fib_lookup_arg *arg)
@ -264,11 +282,11 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
int iifindex, oifindex, ret = 0;
iifindex = READ_ONCE(rule->iifindex);
if (iifindex && (iifindex != fl->flowi_iif))
if (iifindex && !fib_rule_iif_match(rule, iifindex, fl))
goto out;
oifindex = READ_ONCE(rule->oifindex);
if (oifindex && (oifindex != fl->flowi_oif))
if (oifindex && !fib_rule_oif_match(rule, oifindex, fl))
goto out;
if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask)
@ -736,16 +754,20 @@ static int fib_nl2rule_rtnl(struct fib_rule *nlrule,
struct net_device *dev;
dev = __dev_get_by_name(nlrule->fr_net, nlrule->iifname);
if (dev)
if (dev) {
nlrule->iifindex = dev->ifindex;
nlrule->iif_is_l3_master = netif_is_l3_master(dev);
}
}
if (tb[FRA_OIFNAME]) {
struct net_device *dev;
dev = __dev_get_by_name(nlrule->fr_net, nlrule->oifname);
if (dev)
if (dev) {
nlrule->oifindex = dev->ifindex;
nlrule->oif_is_l3_master = netif_is_l3_master(dev);
}
}
return 0;
@ -1336,11 +1358,17 @@ static void attach_rules(struct list_head *rules, struct net_device *dev)
list_for_each_entry(rule, rules, list) {
if (rule->iifindex == -1 &&
strcmp(dev->name, rule->iifname) == 0)
strcmp(dev->name, rule->iifname) == 0) {
WRITE_ONCE(rule->iifindex, dev->ifindex);
WRITE_ONCE(rule->iif_is_l3_master,
netif_is_l3_master(dev));
}
if (rule->oifindex == -1 &&
strcmp(dev->name, rule->oifname) == 0)
strcmp(dev->name, rule->oifname) == 0) {
WRITE_ONCE(rule->oifindex, dev->ifindex);
WRITE_ONCE(rule->oif_is_l3_master,
netif_is_l3_master(dev));
}
}
}
@ -1349,10 +1377,14 @@ static void detach_rules(struct list_head *rules, struct net_device *dev)
struct fib_rule *rule;
list_for_each_entry(rule, rules, list) {
if (rule->iifindex == dev->ifindex)
if (rule->iifindex == dev->ifindex) {
WRITE_ONCE(rule->iifindex, -1);
if (rule->oifindex == dev->ifindex)
WRITE_ONCE(rule->iif_is_l3_master, false);
}
if (rule->oifindex == dev->ifindex) {
WRITE_ONCE(rule->oifindex, -1);
WRITE_ONCE(rule->oif_is_l3_master, false);
}
}
}

View File

@ -3676,11 +3676,8 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
nla_len(tb[IFLA_BROADCAST]));
if (tb[IFLA_TXQLEN])
dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
if (tb[IFLA_OPERSTATE]) {
netdev_lock_ops(dev);
if (tb[IFLA_OPERSTATE])
set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
netdev_unlock_ops(dev);
}
if (tb[IFLA_LINKMODE])
dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
if (tb[IFLA_GROUP])

View File

@ -862,6 +862,16 @@ static void dsa_tree_teardown_lags(struct dsa_switch_tree *dst)
kfree(dst->lags);
}
static void dsa_tree_teardown_routing_table(struct dsa_switch_tree *dst)
{
struct dsa_link *dl, *next;
list_for_each_entry_safe(dl, next, &dst->rtable, list) {
list_del(&dl->list);
kfree(dl);
}
}
static int dsa_tree_setup(struct dsa_switch_tree *dst)
{
bool complete;
@ -879,7 +889,7 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
err = dsa_tree_setup_cpu_ports(dst);
if (err)
return err;
goto teardown_rtable;
err = dsa_tree_setup_switches(dst);
if (err)
@ -911,14 +921,14 @@ teardown_switches:
dsa_tree_teardown_switches(dst);
teardown_cpu_ports:
dsa_tree_teardown_cpu_ports(dst);
teardown_rtable:
dsa_tree_teardown_routing_table(dst);
return err;
}
static void dsa_tree_teardown(struct dsa_switch_tree *dst)
{
struct dsa_link *dl, *next;
if (!dst->setup)
return;
@ -932,10 +942,7 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst)
dsa_tree_teardown_cpu_ports(dst);
list_for_each_entry_safe(dl, next, &dst->rtable, list) {
list_del(&dl->list);
kfree(dl);
}
dsa_tree_teardown_routing_table(dst);
pr_info("DSA: tree %d torn down\n", dst->index);
@ -1478,12 +1485,44 @@ static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd)
static void dsa_switch_release_ports(struct dsa_switch *ds)
{
struct dsa_mac_addr *a, *tmp;
struct dsa_port *dp, *next;
struct dsa_vlan *v, *n;
dsa_switch_for_each_port_safe(dp, next, ds) {
WARN_ON(!list_empty(&dp->fdbs));
WARN_ON(!list_empty(&dp->mdbs));
WARN_ON(!list_empty(&dp->vlans));
/* These are either entries that upper layers lost track of
* (probably due to bugs), or installed through interfaces
* where one does not necessarily have to remove them, like
* ndo_dflt_fdb_add().
*/
list_for_each_entry_safe(a, tmp, &dp->fdbs, list) {
dev_info(ds->dev,
"Cleaning up unicast address %pM vid %u from port %d\n",
a->addr, a->vid, dp->index);
list_del(&a->list);
kfree(a);
}
list_for_each_entry_safe(a, tmp, &dp->mdbs, list) {
dev_info(ds->dev,
"Cleaning up multicast address %pM vid %u from port %d\n",
a->addr, a->vid, dp->index);
list_del(&a->list);
kfree(a);
}
/* These are entries that upper layers have lost track of,
* probably due to bugs, but also due to dsa_port_do_vlan_del()
* having failed and the VLAN entry still lingering on.
*/
list_for_each_entry_safe(v, n, &dp->vlans, list) {
dev_info(ds->dev,
"Cleaning up vid %u from port %d\n",
v->vid, dp->index);
list_del(&v->list);
kfree(v);
}
list_del(&dp->list);
kfree(dp);
}

View File

@ -197,7 +197,7 @@ static int dsa_port_do_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid)
err = ds->ops->tag_8021q_vlan_del(ds, port, vid);
if (err) {
refcount_inc(&v->refcount);
refcount_set(&v->refcount, 1);
return err;
}

View File

@ -351,7 +351,7 @@ ethtool_cmis_module_poll(struct net_device *dev,
struct netlink_ext_ack extack = {};
int err;
ethtool_cmis_page_init(&page_data, 0, offset, sizeof(rpl));
ethtool_cmis_page_init(&page_data, 0, offset, sizeof(*rpl));
page_data.data = (u8 *)rpl;
err = ops->get_module_eeprom_by_page(dev, &page_data, &extack);

View File

@ -1771,6 +1771,7 @@ out:
if (!err) {
spin_lock_bh(&f6i->fib6_table->tb6_lock);
fib6_update_sernum(net, f6i);
fib6_add_gc_list(f6i);
spin_unlock_bh(&f6i->fib6_table->tb6_lock);
fib6_force_start_gc(net);
}

View File

@ -277,8 +277,10 @@ void l3mdev_update_flow(struct net *net, struct flowi *fl)
if (fl->flowi_oif) {
dev = dev_get_by_index_rcu(net, fl->flowi_oif);
if (dev) {
if (!fl->flowi_l3mdev)
if (!fl->flowi_l3mdev) {
fl->flowi_l3mdev = l3mdev_master_ifindex_rcu(dev);
fl->flowi_flags |= FLOWI_FLAG_L3MDEV_OIF;
}
/* oif set to L3mdev directs lookup to its table;
* reset to avoid oif match in fib_lookup

View File

@ -659,6 +659,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
ieee80211_txq_remove_vlan(local, sdata);
if (sdata->vif.txq)
ieee80211_txq_purge(sdata->local, to_txq_info(sdata->vif.txq));
sdata->bss = NULL;
if (local->open_count == 0)

View File

@ -630,6 +630,9 @@ static int mctp_sk_hash(struct sock *sk)
{
struct net *net = sock_net(sk);
/* Bind lookup runs under RCU, remain live during that. */
sock_set_flag(sk, SOCK_RCU_FREE);
mutex_lock(&net->mctp.bind_lock);
sk_add_node_rcu(sk, &net->mctp.binds);
mutex_unlock(&net->mctp.bind_lock);

View File

@ -383,8 +383,8 @@ static void flow_offload_del(struct nf_flowtable *flow_table,
void flow_offload_teardown(struct flow_offload *flow)
{
clear_bit(IPS_OFFLOAD_BIT, &flow->ct->status);
set_bit(NF_FLOW_TEARDOWN, &flow->flags);
flow_offload_fixup_ct(flow);
if (!test_and_set_bit(NF_FLOW_TEARDOWN, &flow->flags))
flow_offload_fixup_ct(flow);
}
EXPORT_SYMBOL_GPL(flow_offload_teardown);
@ -558,10 +558,12 @@ static void nf_flow_offload_gc_step(struct nf_flowtable *flow_table,
if (nf_flow_has_expired(flow) ||
nf_ct_is_dying(flow->ct) ||
nf_flow_custom_gc(flow_table, flow))
nf_flow_custom_gc(flow_table, flow)) {
flow_offload_teardown(flow);
else if (!teardown)
teardown = true;
} else if (!teardown) {
nf_flow_table_extend_ct_timeout(flow->ct);
}
if (teardown) {
if (test_bit(NF_FLOW_HW, &flow->flags)) {

View File

@ -2876,7 +2876,8 @@ static int validate_set(const struct nlattr *a,
size_t key_len;
/* There can be only one key in a action */
if (nla_total_size(nla_len(ovs_key)) != nla_len(a))
if (!nla_ok(ovs_key, nla_len(a)) ||
nla_total_size(nla_len(ovs_key)) != nla_len(a))
return -EINVAL;
key_len = nla_len(ovs_key);

View File

@ -362,6 +362,9 @@ static void smc_destruct(struct sock *sk)
return;
}
static struct lock_class_key smc_key;
static struct lock_class_key smc_slock_key;
void smc_sk_init(struct net *net, struct sock *sk, int protocol)
{
struct smc_sock *smc = smc_sk(sk);
@ -375,6 +378,8 @@ void smc_sk_init(struct net *net, struct sock *sk, int protocol)
INIT_WORK(&smc->connect_work, smc_connect_work);
INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work);
INIT_LIST_HEAD(&smc->accept_q);
sock_lock_init_class_and_name(sk, "slock-AF_SMC", &smc_slock_key,
"sk_lock-AF_SMC", &smc_key);
spin_lock_init(&smc->accept_q_lock);
spin_lock_init(&smc->conn.send_lock);
sk->sk_prot->hash(sk);

View File

@ -162,9 +162,15 @@ class Type(SpecAttr):
def free_needs_iter(self):
return False
def free(self, ri, var, ref):
def _free_lines(self, ri, var, ref):
if self.is_multi_val() or self.presence_type() == 'len':
ri.cw.p(f'free({var}->{ref}{self.c_name});')
return [f'free({var}->{ref}{self.c_name});']
return []
def free(self, ri, var, ref):
lines = self._free_lines(ri, var, ref)
for line in lines:
ri.cw.p(line)
def arg_member(self, ri):
member = self._complex_member_type(ri)
@ -263,6 +269,10 @@ class Type(SpecAttr):
var = "req"
member = f"{var}->{'.'.join(ref)}"
local_vars = []
if self.free_needs_iter():
local_vars += ['unsigned int i;']
code = []
presence = ''
for i in range(0, len(ref)):
@ -272,6 +282,10 @@ class Type(SpecAttr):
if i == len(ref) - 1 and self.presence_type() != 'bit':
continue
code.append(presence + ' = 1;')
ref_path = '.'.join(ref[:-1])
if ref_path:
ref_path += '.'
code += self._free_lines(ri, var, ref_path)
code += self._setter_lines(ri, member, presence)
func_name = f"{op_prefix(ri, direction, deref=deref)}_set_{'_'.join(ref)}"
@ -279,7 +293,8 @@ class Type(SpecAttr):
alloc = bool([x for x in code if 'alloc(' in x])
if free and not alloc:
func_name = '__' + func_name
ri.cw.write_func('static inline void', func_name, body=code,
ri.cw.write_func('static inline void', func_name, local_vars=local_vars,
body=code,
args=[f'{type_name(ri, direction, deref=deref)} *{var}'] + self.arg_member(ri))
@ -482,8 +497,7 @@ class TypeString(Type):
['unsigned int len;']
def _setter_lines(self, ri, member, presence):
return [f"free({member});",
f"{presence}_len = strlen({self.c_name});",
return [f"{presence}_len = strlen({self.c_name});",
f"{member} = malloc({presence}_len + 1);",
f'memcpy({member}, {self.c_name}, {presence}_len);',
f'{member}[{presence}_len] = 0;']
@ -536,8 +550,7 @@ class TypeBinary(Type):
['unsigned int len;']
def _setter_lines(self, ri, member, presence):
return [f"free({member});",
f"{presence}_len = len;",
return [f"{presence}_len = len;",
f"{member} = malloc({presence}_len);",
f'memcpy({member}, {self.c_name}, {presence}_len);']
@ -574,12 +587,14 @@ class TypeNest(Type):
def _complex_member_type(self, ri):
return self.nested_struct_type
def free(self, ri, var, ref):
def _free_lines(self, ri, var, ref):
lines = []
at = '&'
if self.is_recursive_for_op(ri):
at = ''
ri.cw.p(f'if ({var}->{ref}{self.c_name})')
ri.cw.p(f'{self.nested_render_name}_free({at}{var}->{ref}{self.c_name});')
lines += [f'if ({var}->{ref}{self.c_name})']
lines += [f'{self.nested_render_name}_free({at}{var}->{ref}{self.c_name});']
return lines
def _attr_typol(self):
return f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, '
@ -632,15 +647,19 @@ class TypeMultiAttr(Type):
def free_needs_iter(self):
return 'type' not in self.attr or self.attr['type'] == 'nest'
def free(self, ri, var, ref):
def _free_lines(self, ri, var, ref):
lines = []
if self.attr['type'] in scalars:
ri.cw.p(f"free({var}->{ref}{self.c_name});")
lines += [f"free({var}->{ref}{self.c_name});"]
elif 'type' not in self.attr or self.attr['type'] == 'nest':
ri.cw.p(f"for (i = 0; i < {var}->{ref}n_{self.c_name}; i++)")
ri.cw.p(f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name}[i]);')
ri.cw.p(f"free({var}->{ref}{self.c_name});")
lines += [
f"for (i = 0; i < {var}->{ref}n_{self.c_name}; i++)",
f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name}[i]);',
f"free({var}->{ref}{self.c_name});",
]
else:
raise Exception(f"Free of MultiAttr sub-type {self.attr['type']} not supported yet")
return lines
def _attr_policy(self, policy):
return self.base_type._attr_policy(policy)
@ -654,10 +673,10 @@ class TypeMultiAttr(Type):
def attr_put(self, ri, var):
if self.attr['type'] in scalars:
put_type = self.type
ri.cw.p(f"for (unsigned int i = 0; i < {var}->n_{self.c_name}; i++)")
ri.cw.p(f"for (i = 0; i < {var}->n_{self.c_name}; i++)")
ri.cw.p(f"ynl_attr_put_{put_type}(nlh, {self.enum_name}, {var}->{self.c_name}[i]);")
elif 'type' not in self.attr or self.attr['type'] == 'nest':
ri.cw.p(f"for (unsigned int i = 0; i < {var}->n_{self.c_name}; i++)")
ri.cw.p(f"for (i = 0; i < {var}->n_{self.c_name}; i++)")
self._attr_put_line(ri, var, f"{self.nested_render_name}_put(nlh, " +
f"{self.enum_name}, &{var}->{self.c_name}[i])")
else:
@ -666,8 +685,7 @@ class TypeMultiAttr(Type):
def _setter_lines(self, ri, member, presence):
# For multi-attr we have a count, not presence, hack up the presence
presence = presence[:-(len('_present.') + len(self.c_name))] + "n_" + self.c_name
return [f"free({member});",
f"{member} = {self.c_name};",
return [f"{member} = {self.c_name};",
f"{presence} = n_{self.c_name};"]
@ -696,8 +714,11 @@ class TypeArrayNest(Type):
def _attr_get(self, ri, var):
local_vars = ['const struct nlattr *attr2;']
get_lines = [f'attr_{self.c_name} = attr;',
'ynl_attr_for_each_nested(attr2, attr)',
f'\t{var}->n_{self.c_name}++;']
'ynl_attr_for_each_nested(attr2, attr) {',
'\tif (ynl_attr_validate(yarg, attr2))',
'\t\treturn YNL_PARSE_CB_ERROR;',
f'\t{var}->n_{self.c_name}++;',
'}']
return get_lines, None, local_vars
@ -755,6 +776,7 @@ class Struct:
self.request = False
self.reply = False
self.recursive = False
self.in_multi_val = False # used by a MultiAttr or and legacy arrays
self.attr_list = []
self.attrs = dict()
@ -1122,6 +1144,10 @@ class Family(SpecFamily):
if attr in rs_members['reply']:
self.pure_nested_structs[nested].reply = True
if spec.is_multi_val():
child = self.pure_nested_structs.get(nested)
child.in_multi_val = True
self._sort_pure_types()
# Propagate the request / reply / recursive
@ -1136,6 +1162,8 @@ class Family(SpecFamily):
struct.child_nests.update(child.child_nests)
child.request |= struct.request
child.reply |= struct.reply
if spec.is_multi_val():
child.in_multi_val = True
if attr_set in struct.child_nests:
struct.recursive = True
@ -1399,9 +1427,9 @@ class CodeWriter:
def write_func(self, qual_ret, name, body, args=None, local_vars=None):
self.write_func_prot(qual_ret=qual_ret, name=name, args=args)
self.block_start()
self.write_func_lvar(local_vars=local_vars)
self.block_start()
for line in body:
self.p(line)
self.block_end()
@ -1644,11 +1672,23 @@ def put_req_nested_prototype(ri, struct, suffix=';'):
def put_req_nested(ri, struct):
local_vars = []
init_lines = []
local_vars.append('struct nlattr *nest;')
init_lines.append("nest = ynl_attr_nest_start(nlh, attr_type);")
for _, arg in struct.member_list():
if arg.presence_type() == 'count':
local_vars.append('unsigned int i;')
break
put_req_nested_prototype(ri, struct, suffix='')
ri.cw.block_start()
ri.cw.write_func_lvar('struct nlattr *nest;')
ri.cw.write_func_lvar(local_vars)
ri.cw.p("nest = ynl_attr_nest_start(nlh, attr_type);")
for line in init_lines:
ri.cw.p(line)
for _, arg in struct.member_list():
arg.attr_put(ri, "obj")
@ -1850,6 +1890,11 @@ def print_req(ri):
local_vars += ['size_t hdr_len;',
'void *hdr;']
for _, attr in ri.struct["request"].member_list():
if attr.presence_type() == 'count':
local_vars += ['unsigned int i;']
break
print_prototype(ri, direction, terminate=False)
ri.cw.block_start()
ri.cw.write_func_lvar(local_vars)
@ -2941,6 +2986,9 @@ def main():
for attr_set, struct in parsed.pure_nested_structs.items():
ri = RenderInfo(cw, parsed, args.mode, "", "", attr_set)
print_type_full(ri, struct)
if struct.request and struct.in_multi_val:
free_rsp_nested_prototype(ri)
cw.nl()
for op_name, op in parsed.ops.items():
cw.p(f"/* ============== {op.enum_name} ============== */")

View File

@ -35,6 +35,7 @@ def test_zcrx(cfg) -> None:
rx_ring = _get_rx_ring_entries(cfg)
try:
ethtool(f"-G {cfg.ifname} tcp-data-split on", host=cfg.remote)
ethtool(f"-G {cfg.ifname} rx 64", host=cfg.remote)
ethtool(f"-X {cfg.ifname} equal {combined_chans - 1}", host=cfg.remote)
flow_rule_id = _set_flow_rule(cfg, combined_chans - 1)
@ -48,6 +49,7 @@ def test_zcrx(cfg) -> None:
ethtool(f"-N {cfg.ifname} delete {flow_rule_id}", host=cfg.remote)
ethtool(f"-X {cfg.ifname} default", host=cfg.remote)
ethtool(f"-G {cfg.ifname} rx {rx_ring}", host=cfg.remote)
ethtool(f"-G {cfg.ifname} tcp-data-split auto", host=cfg.remote)
def test_zcrx_oneshot(cfg) -> None:
@ -59,6 +61,7 @@ def test_zcrx_oneshot(cfg) -> None:
rx_ring = _get_rx_ring_entries(cfg)
try:
ethtool(f"-G {cfg.ifname} tcp-data-split on", host=cfg.remote)
ethtool(f"-G {cfg.ifname} rx 64", host=cfg.remote)
ethtool(f"-X {cfg.ifname} equal {combined_chans - 1}", host=cfg.remote)
flow_rule_id = _set_flow_rule(cfg, combined_chans - 1)
@ -72,6 +75,7 @@ def test_zcrx_oneshot(cfg) -> None:
ethtool(f"-N {cfg.ifname} delete {flow_rule_id}", host=cfg.remote)
ethtool(f"-X {cfg.ifname} default", host=cfg.remote)
ethtool(f"-G {cfg.ifname} rx {rx_ring}", host=cfg.remote)
ethtool(f"-G {cfg.ifname} tcp-data-split auto", host=cfg.remote)
def main() -> None:

View File

@ -359,6 +359,23 @@ fib_rule6_test()
"$getnomatch" "iif flowlabel masked redirect to table" \
"iif flowlabel masked no redirect to table"
fi
$IP link show dev $DEV | grep -q vrf0
if [ $? -eq 0 ]; then
match="oif vrf0"
getmatch="oif $DEV"
getnomatch="oif lo"
fib_rule6_test_match_n_redirect "$match" "$getmatch" \
"$getnomatch" "VRF oif redirect to table" \
"VRF oif no redirect to table"
match="from $SRC_IP6 iif vrf0"
getmatch="from $SRC_IP6 iif $DEV"
getnomatch="from $SRC_IP6 iif lo"
fib_rule6_test_match_n_redirect "$match" "$getmatch" \
"$getnomatch" "VRF iif redirect to table" \
"VRF iif no redirect to table"
fi
}
fib_rule6_vrf_test()
@ -635,6 +652,23 @@ fib_rule4_test()
"$getnomatch" "iif dscp masked redirect to table" \
"iif dscp masked no redirect to table"
fi
$IP link show dev $DEV | grep -q vrf0
if [ $? -eq 0 ]; then
match="oif vrf0"
getmatch="oif $DEV"
getnomatch="oif lo"
fib_rule4_test_match_n_redirect "$match" "$getmatch" \
"$getnomatch" "VRF oif redirect to table" \
"VRF oif no redirect to table"
match="from $SRC_IP iif vrf0"
getmatch="from $SRC_IP iif $DEV"
getnomatch="from $SRC_IP iif lo"
fib_rule4_test_match_n_redirect "$match" "$getmatch" \
"$getnomatch" "VRF iif redirect to table" \
"VRF iif no redirect to table"
fi
}
fib_rule4_vrf_test()

View File

@ -412,5 +412,27 @@
"teardown": [
"$TC qdisc del dev $DUMMY ingress"
]
},
{
"id": "33f4",
"name": "Check echo of big filter command",
"category": [
"infra",
"u32"
],
"plugins": {
"requires": "nsPlugin"
},
"setup": [
"$TC qdisc add dev $DUMMY parent root handle 10: fq_codel"
],
"cmdUnderTest": "bash -c '$TC -echo filter add dev $DUMMY parent 10: u32 match u32 0 0 $(for i in $(seq 32); do echo action pedit munge ip dport set 22; done) | grep \"added filter\"'",
"verifyCmd": "",
"expExitCode": "0",
"matchCount": "0",
"matchPattern": "",
"teardown": [
"$TC qdisc del dev $DUMMY parent root fq_codel"
]
}
]