mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 12:14:10 +08:00
Including fixes from bluetooth.
Current release - regressions: - eth: bnxt_en: fix memory out-of-bounds in bnxt_fill_hw_rss_tbl() on older chips Current release - new code bugs: - ethtool: fix off-by-one error / kdoc contradicting the code for max RSS context IDs - Bluetooth: hci_qca: - QCA6390: fix support on non-DT platforms - QCA6390: don't call pwrseq_power_off() twice - fix a NULL-pointer derefence at shutdown - eth: ice: fix incorrect assigns of FEC counters Previous releases - regressions: - mptcp: fix handling endpoints with both 'signal' and 'subflow' flags set - virtio-net: fix changing ring count when vq IRQ coalescing not supported - eth: gve: fix use of netif_carrier_ok() during reconfig / reset Previous releases - always broken: - eth: idpf: fix bugs in queue re-allocation on reconfig / reset - ethtool: fix context creation with no parameters Misc: - linkwatch: use system_unbound_wq to ease RTNL contention Signed-off-by: Jakub Kicinski <kuba@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAma0+MsACgkQMUZtbf5S Iru7UA//e+qaQ4yYQUZnilt4L+HdlMvFGnj6YV2rlXtG2o4leoKBtrvV4Ov5Hrj+ Lzc9Cz4DQBi3tWvaD8SR2wEPYVmUaQm2DLgxTv3NrwSwbL+yd87y6AqnrxyjLglX E/Lg0FKxJC3zVb4Jb6FOX9KwIP60u+kwL5pev7UbpzNU4aVpNovWKo1sICLFYC5L 2rlCWmd2UHDSxDYIqL3nI68IqmhP5etfJnnURxIzJZInKSLRx4Evkke/3Y+Ju8CE LS5HIsTzYmAmgI0+LLPd9fyL8puYuw+tFGMAKSRHLAlzno2Cpre5IEucfbFhQ81+ 7RfJO+lzTvqcIj17bK+QsgAgQUxlRexdct/0KfBG6O/Ll0ptRGl475X5K8hb471r m3WLtNkByYznKpr6ORvNoGqTSAVJpx0Xdl0YWt5G5ANWCMi2kA51K9JOHRNfOnvZ dq0WMu/kwBq8XJ/l0FjB2lT41bhkOzdbfHiqi60miuixzU3e8rQbs59zHr3wmio2 7NAVfmOPJTILHpyJ4c3DZrKNkxyXnIS04OyDo4SO6QwvJ/XbXi22/ir/3NyKgOTG NqIeA2Ap96n0NzqqUrRMGdSPoKW8Cbl7zNO1opHJj/l57XPMVz+g9qA5mbSCT5k1 fNu2lURKzRLcoq5OmwySLJR2ASMfpaLpmooFYBrtftPVwl4YQvo= =bKTC -----END PGP SIGNATURE----- Merge tag 'net-6.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Jakub Kicinski: "Including fixes from bluetooth. Current release - regressions: - eth: bnxt_en: fix memory out-of-bounds in bnxt_fill_hw_rss_tbl() on older chips Current release - new code bugs: - ethtool: fix off-by-one error / kdoc contradicting the code for max RSS context IDs - Bluetooth: hci_qca: - QCA6390: fix support on non-DT platforms - QCA6390: don't call pwrseq_power_off() twice - fix a NULL-pointer derefence at shutdown - eth: ice: fix incorrect assigns of FEC counters Previous releases - regressions: - mptcp: fix handling endpoints with both 'signal' and 'subflow' flags set - virtio-net: fix changing ring count when vq IRQ coalescing not supported - eth: gve: fix use of netif_carrier_ok() during reconfig / reset Previous releases - always broken: - eth: idpf: fix bugs in queue re-allocation on reconfig / reset - ethtool: fix context creation with no parameters Misc: - linkwatch: use system_unbound_wq to ease RTNL contention" * tag 'net-6.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (41 commits) net: dsa: microchip: disable EEE for KSZ8567/KSZ9567/KSZ9896/KSZ9897. ethtool: Fix context creation with no parameters net: ethtool: fix off-by-one error in max RSS context IDs net: pse-pd: tps23881: include missing bitfield.h header net: fec: Stop PPS on driver remove net: bcmgenet: Properly overlay PHY and MAC Wake-on-LAN capabilities l2tp: fix lockdep splat net: stmmac: dwmac4: fix PCS duplex mode decode idpf: fix UAFs when destroying the queues idpf: fix memleak in vport interrupt configuration idpf: fix memory leaks and crashes while performing a soft reset bnxt_en : Fix memory out-of-bounds in bnxt_fill_hw_rss_tbl() net: dsa: bcm_sf2: Fix a possible memory leak in bcm_sf2_mdio_register() net/smc: add the max value of fallback reason count Bluetooth: hci_sync: avoid dup filtering when passive scanning with adv monitor Bluetooth: l2cap: always unlock channel in l2cap_conless_channel() Bluetooth: hci_qca: fix a NULL-pointer derefence at shutdown Bluetooth: hci_qca: fix QCA6390 support on non-DT platforms Bluetooth: hci_qca: don't call pwrseq_power_off() twice for QCA6390 ice: Fix incorrect assigns of FEC counts ...
This commit is contained in:
commit
ee9a43b7cf
@ -13541,7 +13541,7 @@ MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
|
|||||||
M: Mirko Lindner <mlindner@marvell.com>
|
M: Mirko Lindner <mlindner@marvell.com>
|
||||||
M: Stephen Hemminger <stephen@networkplumber.org>
|
M: Stephen Hemminger <stephen@networkplumber.org>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Odd fixes
|
||||||
F: drivers/net/ethernet/marvell/sk*
|
F: drivers/net/ethernet/marvell/sk*
|
||||||
|
|
||||||
MARVELL LIBERTAS WIRELESS DRIVER
|
MARVELL LIBERTAS WIRELESS DRIVER
|
||||||
|
@ -2160,7 +2160,7 @@ static void qca_power_shutdown(struct hci_uart *hu)
|
|||||||
qcadev = serdev_device_get_drvdata(hu->serdev);
|
qcadev = serdev_device_get_drvdata(hu->serdev);
|
||||||
power = qcadev->bt_power;
|
power = qcadev->bt_power;
|
||||||
|
|
||||||
if (power->pwrseq) {
|
if (power && power->pwrseq) {
|
||||||
pwrseq_power_off(power->pwrseq);
|
pwrseq_power_off(power->pwrseq);
|
||||||
set_bit(QCA_BT_OFF, &qca->flags);
|
set_bit(QCA_BT_OFF, &qca->flags);
|
||||||
return;
|
return;
|
||||||
@ -2187,10 +2187,6 @@ static void qca_power_shutdown(struct hci_uart *hu)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QCA_QCA6390:
|
|
||||||
pwrseq_power_off(qcadev->bt_power->pwrseq);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
gpiod_set_value_cansleep(qcadev->bt_en, 0);
|
gpiod_set_value_cansleep(qcadev->bt_en, 0);
|
||||||
}
|
}
|
||||||
@ -2416,11 +2412,14 @@ static int qca_serdev_probe(struct serdev_device *serdev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QCA_QCA6390:
|
case QCA_QCA6390:
|
||||||
qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev,
|
if (dev_of_node(&serdev->dev)) {
|
||||||
"bluetooth");
|
qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev,
|
||||||
if (IS_ERR(qcadev->bt_power->pwrseq))
|
"bluetooth");
|
||||||
return PTR_ERR(qcadev->bt_power->pwrseq);
|
if (IS_ERR(qcadev->bt_power->pwrseq))
|
||||||
break;
|
return PTR_ERR(qcadev->bt_power->pwrseq);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fallthrough;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
|
qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
|
||||||
|
@ -675,8 +675,10 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
|
|||||||
of_remove_property(child, prop);
|
of_remove_property(child, prop);
|
||||||
|
|
||||||
phydev = of_phy_find_device(child);
|
phydev = of_phy_find_device(child);
|
||||||
if (phydev)
|
if (phydev) {
|
||||||
phy_device_remove(phydev);
|
phy_device_remove(phydev);
|
||||||
|
phy_device_free(phydev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mdiobus_register(priv->user_mii_bus);
|
err = mdiobus_register(priv->user_mii_bus);
|
||||||
|
@ -2578,7 +2578,11 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
|
|||||||
if (!port)
|
if (!port)
|
||||||
return MICREL_KSZ8_P1_ERRATA;
|
return MICREL_KSZ8_P1_ERRATA;
|
||||||
break;
|
break;
|
||||||
|
case KSZ8567_CHIP_ID:
|
||||||
case KSZ9477_CHIP_ID:
|
case KSZ9477_CHIP_ID:
|
||||||
|
case KSZ9567_CHIP_ID:
|
||||||
|
case KSZ9896_CHIP_ID:
|
||||||
|
case KSZ9897_CHIP_ID:
|
||||||
/* KSZ9477 Errata DS80000754C
|
/* KSZ9477 Errata DS80000754C
|
||||||
*
|
*
|
||||||
* Module 4: Energy Efficient Ethernet (EEE) feature select must
|
* Module 4: Energy Efficient Ethernet (EEE) feature select must
|
||||||
@ -2588,6 +2592,13 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
|
|||||||
* controls. If not disabled, the PHY ports can auto-negotiate
|
* controls. If not disabled, the PHY ports can auto-negotiate
|
||||||
* to enable EEE, and this feature can cause link drops when
|
* to enable EEE, and this feature can cause link drops when
|
||||||
* linked to another device supporting EEE.
|
* linked to another device supporting EEE.
|
||||||
|
*
|
||||||
|
* The same item appears in the errata for the KSZ9567, KSZ9896,
|
||||||
|
* and KSZ9897.
|
||||||
|
*
|
||||||
|
* A similar item appears in the errata for the KSZ8567, but
|
||||||
|
* provides an alternative workaround. For now, use the simple
|
||||||
|
* workaround of disabling the EEE feature for this device too.
|
||||||
*/
|
*/
|
||||||
return MICREL_NO_EEE;
|
return MICREL_NO_EEE;
|
||||||
}
|
}
|
||||||
@ -3764,6 +3775,11 @@ static int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Need to initialize variable as the code to fill in settings may
|
||||||
|
* not be executed.
|
||||||
|
*/
|
||||||
|
wol.wolopts = 0;
|
||||||
|
|
||||||
ksz_get_wol(ds, dp->index, &wol);
|
ksz_get_wol(ds, dp->index, &wol);
|
||||||
if (wol.wolopts & WAKE_MAGIC) {
|
if (wol.wolopts & WAKE_MAGIC) {
|
||||||
dev_err(ds->dev,
|
dev_err(ds->dev,
|
||||||
|
@ -7591,19 +7591,20 @@ static bool bnxt_need_reserve_rings(struct bnxt *bp)
|
|||||||
int rx = bp->rx_nr_rings, stat;
|
int rx = bp->rx_nr_rings, stat;
|
||||||
int vnic, grp = rx;
|
int vnic, grp = rx;
|
||||||
|
|
||||||
if (hw_resc->resv_tx_rings != bp->tx_nr_rings &&
|
|
||||||
bp->hwrm_spec_code >= 0x10601)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/* Old firmware does not need RX ring reservations but we still
|
/* Old firmware does not need RX ring reservations but we still
|
||||||
* need to setup a default RSS map when needed. With new firmware
|
* need to setup a default RSS map when needed. With new firmware
|
||||||
* we go through RX ring reservations first and then set up the
|
* we go through RX ring reservations first and then set up the
|
||||||
* RSS map for the successfully reserved RX rings when needed.
|
* RSS map for the successfully reserved RX rings when needed.
|
||||||
*/
|
*/
|
||||||
if (!BNXT_NEW_RM(bp)) {
|
if (!BNXT_NEW_RM(bp))
|
||||||
bnxt_check_rss_tbl_no_rmgr(bp);
|
bnxt_check_rss_tbl_no_rmgr(bp);
|
||||||
|
|
||||||
|
if (hw_resc->resv_tx_rings != bp->tx_nr_rings &&
|
||||||
|
bp->hwrm_spec_code >= 0x10601)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!BNXT_NEW_RM(bp))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
vnic = bnxt_get_total_vnics(bp, rx);
|
vnic = bnxt_get_total_vnics(bp, rx);
|
||||||
|
|
||||||
|
@ -5290,7 +5290,7 @@ void bnxt_ethtool_free(struct bnxt *bp)
|
|||||||
const struct ethtool_ops bnxt_ethtool_ops = {
|
const struct ethtool_ops bnxt_ethtool_ops = {
|
||||||
.cap_link_lanes_supported = 1,
|
.cap_link_lanes_supported = 1,
|
||||||
.cap_rss_ctx_supported = 1,
|
.cap_rss_ctx_supported = 1,
|
||||||
.rxfh_max_context_id = BNXT_MAX_ETH_RSS_CTX,
|
.rxfh_max_num_contexts = BNXT_MAX_ETH_RSS_CTX + 1,
|
||||||
.rxfh_indir_space = BNXT_MAX_RSS_TABLE_ENTRIES_P5,
|
.rxfh_indir_space = BNXT_MAX_RSS_TABLE_ENTRIES_P5,
|
||||||
.rxfh_priv_size = sizeof(struct bnxt_rss_ctx),
|
.rxfh_priv_size = sizeof(struct bnxt_rss_ctx),
|
||||||
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
|
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
|
||||||
|
@ -42,19 +42,15 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
|||||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||||
struct device *kdev = &priv->pdev->dev;
|
struct device *kdev = &priv->pdev->dev;
|
||||||
|
|
||||||
if (dev->phydev) {
|
if (dev->phydev)
|
||||||
phy_ethtool_get_wol(dev->phydev, wol);
|
phy_ethtool_get_wol(dev->phydev, wol);
|
||||||
if (wol->supported)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!device_can_wakeup(kdev)) {
|
/* MAC is not wake-up capable, return what the PHY does */
|
||||||
wol->supported = 0;
|
if (!device_can_wakeup(kdev))
|
||||||
wol->wolopts = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
|
/* Overlay MAC capabilities with that of the PHY queried before */
|
||||||
|
wol->supported |= WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
|
||||||
wol->wolopts = priv->wolopts;
|
wol->wolopts = priv->wolopts;
|
||||||
memset(wol->sopass, 0, sizeof(wol->sopass));
|
memset(wol->sopass, 0, sizeof(wol->sopass));
|
||||||
|
|
||||||
|
@ -775,6 +775,9 @@ void fec_ptp_stop(struct platform_device *pdev)
|
|||||||
struct net_device *ndev = platform_get_drvdata(pdev);
|
struct net_device *ndev = platform_get_drvdata(pdev);
|
||||||
struct fec_enet_private *fep = netdev_priv(ndev);
|
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||||
|
|
||||||
|
if (fep->pps_enable)
|
||||||
|
fec_ptp_enable_pps(fep, 0);
|
||||||
|
|
||||||
cancel_delayed_work_sync(&fep->time_keep);
|
cancel_delayed_work_sync(&fep->time_keep);
|
||||||
hrtimer_cancel(&fep->perout_timer);
|
hrtimer_cancel(&fep->perout_timer);
|
||||||
if (fep->ptp_clock)
|
if (fep->ptp_clock)
|
||||||
|
@ -495,7 +495,7 @@ static int gve_set_channels(struct net_device *netdev,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!netif_carrier_ok(netdev)) {
|
if (!netif_running(netdev)) {
|
||||||
priv->tx_cfg.num_queues = new_tx;
|
priv->tx_cfg.num_queues = new_tx;
|
||||||
priv->rx_cfg.num_queues = new_rx;
|
priv->rx_cfg.num_queues = new_rx;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1566,7 +1566,7 @@ static int gve_set_xdp(struct gve_priv *priv, struct bpf_prog *prog,
|
|||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
old_prog = READ_ONCE(priv->xdp_prog);
|
old_prog = READ_ONCE(priv->xdp_prog);
|
||||||
if (!netif_carrier_ok(priv->dev)) {
|
if (!netif_running(priv->dev)) {
|
||||||
WRITE_ONCE(priv->xdp_prog, prog);
|
WRITE_ONCE(priv->xdp_prog, prog);
|
||||||
if (old_prog)
|
if (old_prog)
|
||||||
bpf_prog_put(old_prog);
|
bpf_prog_put(old_prog);
|
||||||
@ -1847,7 +1847,7 @@ int gve_adjust_queues(struct gve_priv *priv,
|
|||||||
rx_alloc_cfg.qcfg = &new_rx_config;
|
rx_alloc_cfg.qcfg = &new_rx_config;
|
||||||
tx_alloc_cfg.num_rings = new_tx_config.num_queues;
|
tx_alloc_cfg.num_rings = new_tx_config.num_queues;
|
||||||
|
|
||||||
if (netif_carrier_ok(priv->dev)) {
|
if (netif_running(priv->dev)) {
|
||||||
err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
|
err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -2064,7 +2064,7 @@ static int gve_set_features(struct net_device *netdev,
|
|||||||
|
|
||||||
if ((netdev->features & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
|
if ((netdev->features & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
|
||||||
netdev->features ^= NETIF_F_LRO;
|
netdev->features ^= NETIF_F_LRO;
|
||||||
if (netif_carrier_ok(netdev)) {
|
if (netif_running(netdev)) {
|
||||||
err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
|
err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
|
||||||
if (err)
|
if (err)
|
||||||
goto revert_features;
|
goto revert_features;
|
||||||
@ -2359,7 +2359,7 @@ err:
|
|||||||
|
|
||||||
int gve_reset(struct gve_priv *priv, bool attempt_teardown)
|
int gve_reset(struct gve_priv *priv, bool attempt_teardown)
|
||||||
{
|
{
|
||||||
bool was_up = netif_carrier_ok(priv->dev);
|
bool was_up = netif_running(priv->dev);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
dev_info(&priv->pdev->dev, "Performing reset\n");
|
dev_info(&priv->pdev->dev, "Performing reset\n");
|
||||||
@ -2700,7 +2700,7 @@ static void gve_shutdown(struct pci_dev *pdev)
|
|||||||
{
|
{
|
||||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||||
struct gve_priv *priv = netdev_priv(netdev);
|
struct gve_priv *priv = netdev_priv(netdev);
|
||||||
bool was_up = netif_carrier_ok(priv->dev);
|
bool was_up = netif_running(priv->dev);
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
if (was_up && gve_close(priv->dev)) {
|
if (was_up && gve_close(priv->dev)) {
|
||||||
@ -2718,7 +2718,7 @@ static int gve_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||||||
{
|
{
|
||||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||||
struct gve_priv *priv = netdev_priv(netdev);
|
struct gve_priv *priv = netdev_priv(netdev);
|
||||||
bool was_up = netif_carrier_ok(priv->dev);
|
bool was_up = netif_running(priv->dev);
|
||||||
|
|
||||||
priv->suspend_cnt++;
|
priv->suspend_cnt++;
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
|
@ -4673,10 +4673,10 @@ static int ice_get_port_fec_stats(struct ice_hw *hw, u16 pcs_quad, u16 pcs_port,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
fec_stats->uncorrectable_blocks.total = (fec_corr_high_val << 16) +
|
fec_stats->corrected_blocks.total = (fec_corr_high_val << 16) +
|
||||||
fec_corr_low_val;
|
fec_corr_low_val;
|
||||||
fec_stats->corrected_blocks.total = (fec_uncorr_high_val << 16) +
|
fec_stats->uncorrectable_blocks.total = (fec_uncorr_high_val << 16) +
|
||||||
fec_uncorr_low_val;
|
fec_uncorr_low_val;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,6 +559,8 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
|
|||||||
if (test_bit(ICE_PREPARED_FOR_RESET, pf->state))
|
if (test_bit(ICE_PREPARED_FOR_RESET, pf->state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
synchronize_irq(pf->oicr_irq.virq);
|
||||||
|
|
||||||
ice_unplug_aux_dev(pf);
|
ice_unplug_aux_dev(pf);
|
||||||
|
|
||||||
/* Notify VFs of impending reset */
|
/* Notify VFs of impending reset */
|
||||||
|
@ -1477,6 +1477,10 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
|
|||||||
/* Update cached link status for this port immediately */
|
/* Update cached link status for this port immediately */
|
||||||
ptp_port->link_up = linkup;
|
ptp_port->link_up = linkup;
|
||||||
|
|
||||||
|
/* Skip HW writes if reset is in progress */
|
||||||
|
if (pf->hw.reset_ongoing)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (hw->ptp.phy_model) {
|
switch (hw->ptp.phy_model) {
|
||||||
case ICE_PHY_E810:
|
case ICE_PHY_E810:
|
||||||
/* Do not reconfigure E810 PHY */
|
/* Do not reconfigure E810 PHY */
|
||||||
|
@ -900,8 +900,8 @@ static void idpf_vport_stop(struct idpf_vport *vport)
|
|||||||
|
|
||||||
vport->link_up = false;
|
vport->link_up = false;
|
||||||
idpf_vport_intr_deinit(vport);
|
idpf_vport_intr_deinit(vport);
|
||||||
idpf_vport_intr_rel(vport);
|
|
||||||
idpf_vport_queues_rel(vport);
|
idpf_vport_queues_rel(vport);
|
||||||
|
idpf_vport_intr_rel(vport);
|
||||||
np->state = __IDPF_VPORT_DOWN;
|
np->state = __IDPF_VPORT_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1335,9 +1335,8 @@ static void idpf_rx_init_buf_tail(struct idpf_vport *vport)
|
|||||||
/**
|
/**
|
||||||
* idpf_vport_open - Bring up a vport
|
* idpf_vport_open - Bring up a vport
|
||||||
* @vport: vport to bring up
|
* @vport: vport to bring up
|
||||||
* @alloc_res: allocate queue resources
|
|
||||||
*/
|
*/
|
||||||
static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res)
|
static int idpf_vport_open(struct idpf_vport *vport)
|
||||||
{
|
{
|
||||||
struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
|
struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
|
||||||
struct idpf_adapter *adapter = vport->adapter;
|
struct idpf_adapter *adapter = vport->adapter;
|
||||||
@ -1350,45 +1349,43 @@ static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res)
|
|||||||
/* we do not allow interface up just yet */
|
/* we do not allow interface up just yet */
|
||||||
netif_carrier_off(vport->netdev);
|
netif_carrier_off(vport->netdev);
|
||||||
|
|
||||||
if (alloc_res) {
|
|
||||||
err = idpf_vport_queues_alloc(vport);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = idpf_vport_intr_alloc(vport);
|
err = idpf_vport_intr_alloc(vport);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&adapter->pdev->dev, "Failed to allocate interrupts for vport %u: %d\n",
|
dev_err(&adapter->pdev->dev, "Failed to allocate interrupts for vport %u: %d\n",
|
||||||
vport->vport_id, err);
|
vport->vport_id, err);
|
||||||
goto queues_rel;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = idpf_vport_queues_alloc(vport);
|
||||||
|
if (err)
|
||||||
|
goto intr_rel;
|
||||||
|
|
||||||
err = idpf_vport_queue_ids_init(vport);
|
err = idpf_vport_queue_ids_init(vport);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&adapter->pdev->dev, "Failed to initialize queue ids for vport %u: %d\n",
|
dev_err(&adapter->pdev->dev, "Failed to initialize queue ids for vport %u: %d\n",
|
||||||
vport->vport_id, err);
|
vport->vport_id, err);
|
||||||
goto intr_rel;
|
goto queues_rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = idpf_vport_intr_init(vport);
|
err = idpf_vport_intr_init(vport);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&adapter->pdev->dev, "Failed to initialize interrupts for vport %u: %d\n",
|
dev_err(&adapter->pdev->dev, "Failed to initialize interrupts for vport %u: %d\n",
|
||||||
vport->vport_id, err);
|
vport->vport_id, err);
|
||||||
goto intr_rel;
|
goto queues_rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = idpf_rx_bufs_init_all(vport);
|
err = idpf_rx_bufs_init_all(vport);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n",
|
dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n",
|
||||||
vport->vport_id, err);
|
vport->vport_id, err);
|
||||||
goto intr_rel;
|
goto queues_rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = idpf_queue_reg_init(vport);
|
err = idpf_queue_reg_init(vport);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n",
|
dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n",
|
||||||
vport->vport_id, err);
|
vport->vport_id, err);
|
||||||
goto intr_rel;
|
goto queues_rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
idpf_rx_init_buf_tail(vport);
|
idpf_rx_init_buf_tail(vport);
|
||||||
@ -1455,10 +1452,10 @@ unmap_queue_vectors:
|
|||||||
idpf_send_map_unmap_queue_vector_msg(vport, false);
|
idpf_send_map_unmap_queue_vector_msg(vport, false);
|
||||||
intr_deinit:
|
intr_deinit:
|
||||||
idpf_vport_intr_deinit(vport);
|
idpf_vport_intr_deinit(vport);
|
||||||
intr_rel:
|
|
||||||
idpf_vport_intr_rel(vport);
|
|
||||||
queues_rel:
|
queues_rel:
|
||||||
idpf_vport_queues_rel(vport);
|
idpf_vport_queues_rel(vport);
|
||||||
|
intr_rel:
|
||||||
|
idpf_vport_intr_rel(vport);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1539,7 +1536,7 @@ void idpf_init_task(struct work_struct *work)
|
|||||||
np = netdev_priv(vport->netdev);
|
np = netdev_priv(vport->netdev);
|
||||||
np->state = __IDPF_VPORT_DOWN;
|
np->state = __IDPF_VPORT_DOWN;
|
||||||
if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags))
|
if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags))
|
||||||
idpf_vport_open(vport, true);
|
idpf_vport_open(vport);
|
||||||
|
|
||||||
/* Spawn and return 'idpf_init_task' work queue until all the
|
/* Spawn and return 'idpf_init_task' work queue until all the
|
||||||
* default vports are created
|
* default vports are created
|
||||||
@ -1898,9 +1895,6 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
|
|||||||
goto free_vport;
|
goto free_vport;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = idpf_vport_queues_alloc(new_vport);
|
|
||||||
if (err)
|
|
||||||
goto free_vport;
|
|
||||||
if (current_state <= __IDPF_VPORT_DOWN) {
|
if (current_state <= __IDPF_VPORT_DOWN) {
|
||||||
idpf_send_delete_queues_msg(vport);
|
idpf_send_delete_queues_msg(vport);
|
||||||
} else {
|
} else {
|
||||||
@ -1932,17 +1926,23 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
|
|||||||
|
|
||||||
err = idpf_set_real_num_queues(vport);
|
err = idpf_set_real_num_queues(vport);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_reset;
|
goto err_open;
|
||||||
|
|
||||||
if (current_state == __IDPF_VPORT_UP)
|
if (current_state == __IDPF_VPORT_UP)
|
||||||
err = idpf_vport_open(vport, false);
|
err = idpf_vport_open(vport);
|
||||||
|
|
||||||
kfree(new_vport);
|
kfree(new_vport);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err_reset:
|
err_reset:
|
||||||
idpf_vport_queues_rel(new_vport);
|
idpf_send_add_queues_msg(vport, vport->num_txq, vport->num_complq,
|
||||||
|
vport->num_rxq, vport->num_bufq);
|
||||||
|
|
||||||
|
err_open:
|
||||||
|
if (current_state == __IDPF_VPORT_UP)
|
||||||
|
idpf_vport_open(vport);
|
||||||
|
|
||||||
free_vport:
|
free_vport:
|
||||||
kfree(new_vport);
|
kfree(new_vport);
|
||||||
|
|
||||||
@ -2171,7 +2171,7 @@ static int idpf_open(struct net_device *netdev)
|
|||||||
idpf_vport_ctrl_lock(netdev);
|
idpf_vport_ctrl_lock(netdev);
|
||||||
vport = idpf_netdev_to_vport(netdev);
|
vport = idpf_netdev_to_vport(netdev);
|
||||||
|
|
||||||
err = idpf_vport_open(vport, true);
|
err = idpf_vport_open(vport);
|
||||||
|
|
||||||
idpf_vport_ctrl_unlock(netdev);
|
idpf_vport_ctrl_unlock(netdev);
|
||||||
|
|
||||||
|
@ -3576,9 +3576,7 @@ static void idpf_vport_intr_napi_dis_all(struct idpf_vport *vport)
|
|||||||
*/
|
*/
|
||||||
void idpf_vport_intr_rel(struct idpf_vport *vport)
|
void idpf_vport_intr_rel(struct idpf_vport *vport)
|
||||||
{
|
{
|
||||||
int i, j, v_idx;
|
for (u32 v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) {
|
||||||
|
|
||||||
for (v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) {
|
|
||||||
struct idpf_q_vector *q_vector = &vport->q_vectors[v_idx];
|
struct idpf_q_vector *q_vector = &vport->q_vectors[v_idx];
|
||||||
|
|
||||||
kfree(q_vector->complq);
|
kfree(q_vector->complq);
|
||||||
@ -3593,26 +3591,6 @@ void idpf_vport_intr_rel(struct idpf_vport *vport)
|
|||||||
free_cpumask_var(q_vector->affinity_mask);
|
free_cpumask_var(q_vector->affinity_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up the mapping of queues to vectors */
|
|
||||||
for (i = 0; i < vport->num_rxq_grp; i++) {
|
|
||||||
struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];
|
|
||||||
|
|
||||||
if (idpf_is_queue_model_split(vport->rxq_model))
|
|
||||||
for (j = 0; j < rx_qgrp->splitq.num_rxq_sets; j++)
|
|
||||||
rx_qgrp->splitq.rxq_sets[j]->rxq.q_vector = NULL;
|
|
||||||
else
|
|
||||||
for (j = 0; j < rx_qgrp->singleq.num_rxq; j++)
|
|
||||||
rx_qgrp->singleq.rxqs[j]->q_vector = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idpf_is_queue_model_split(vport->txq_model))
|
|
||||||
for (i = 0; i < vport->num_txq_grp; i++)
|
|
||||||
vport->txq_grps[i].complq->q_vector = NULL;
|
|
||||||
else
|
|
||||||
for (i = 0; i < vport->num_txq_grp; i++)
|
|
||||||
for (j = 0; j < vport->txq_grps[i].num_txq; j++)
|
|
||||||
vport->txq_grps[i].txqs[j]->q_vector = NULL;
|
|
||||||
|
|
||||||
kfree(vport->q_vectors);
|
kfree(vport->q_vectors);
|
||||||
vport->q_vectors = NULL;
|
vport->q_vectors = NULL;
|
||||||
}
|
}
|
||||||
@ -3780,13 +3758,15 @@ void idpf_vport_intr_update_itr_ena_irq(struct idpf_q_vector *q_vector)
|
|||||||
/**
|
/**
|
||||||
* idpf_vport_intr_req_irq - get MSI-X vectors from the OS for the vport
|
* idpf_vport_intr_req_irq - get MSI-X vectors from the OS for the vport
|
||||||
* @vport: main vport structure
|
* @vport: main vport structure
|
||||||
* @basename: name for the vector
|
|
||||||
*/
|
*/
|
||||||
static int idpf_vport_intr_req_irq(struct idpf_vport *vport, char *basename)
|
static int idpf_vport_intr_req_irq(struct idpf_vport *vport)
|
||||||
{
|
{
|
||||||
struct idpf_adapter *adapter = vport->adapter;
|
struct idpf_adapter *adapter = vport->adapter;
|
||||||
|
const char *drv_name, *if_name, *vec_name;
|
||||||
int vector, err, irq_num, vidx;
|
int vector, err, irq_num, vidx;
|
||||||
const char *vec_name;
|
|
||||||
|
drv_name = dev_driver_string(&adapter->pdev->dev);
|
||||||
|
if_name = netdev_name(vport->netdev);
|
||||||
|
|
||||||
for (vector = 0; vector < vport->num_q_vectors; vector++) {
|
for (vector = 0; vector < vport->num_q_vectors; vector++) {
|
||||||
struct idpf_q_vector *q_vector = &vport->q_vectors[vector];
|
struct idpf_q_vector *q_vector = &vport->q_vectors[vector];
|
||||||
@ -3804,8 +3784,8 @@ static int idpf_vport_intr_req_irq(struct idpf_vport *vport, char *basename)
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
name = kasprintf(GFP_KERNEL, "%s-%s-%d", basename, vec_name,
|
name = kasprintf(GFP_KERNEL, "%s-%s-%s-%d", drv_name, if_name,
|
||||||
vidx);
|
vec_name, vidx);
|
||||||
|
|
||||||
err = request_irq(irq_num, idpf_vport_intr_clean_queues, 0,
|
err = request_irq(irq_num, idpf_vport_intr_clean_queues, 0,
|
||||||
name, q_vector);
|
name, q_vector);
|
||||||
@ -4326,7 +4306,6 @@ error:
|
|||||||
*/
|
*/
|
||||||
int idpf_vport_intr_init(struct idpf_vport *vport)
|
int idpf_vport_intr_init(struct idpf_vport *vport)
|
||||||
{
|
{
|
||||||
char *int_name;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = idpf_vport_intr_init_vec_idx(vport);
|
err = idpf_vport_intr_init_vec_idx(vport);
|
||||||
@ -4340,11 +4319,7 @@ int idpf_vport_intr_init(struct idpf_vport *vport)
|
|||||||
if (err)
|
if (err)
|
||||||
goto unroll_vectors_alloc;
|
goto unroll_vectors_alloc;
|
||||||
|
|
||||||
int_name = kasprintf(GFP_KERNEL, "%s-%s",
|
err = idpf_vport_intr_req_irq(vport);
|
||||||
dev_driver_string(&vport->adapter->pdev->dev),
|
|
||||||
vport->netdev->name);
|
|
||||||
|
|
||||||
err = idpf_vport_intr_req_irq(vport, int_name);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto unroll_vectors_alloc;
|
goto unroll_vectors_alloc;
|
||||||
|
|
||||||
|
@ -573,8 +573,6 @@ static inline u32 mtl_low_credx_base_addr(const struct dwmac4_addrs *addrs,
|
|||||||
#define GMAC_PHYIF_CTRLSTATUS_LNKSTS BIT(19)
|
#define GMAC_PHYIF_CTRLSTATUS_LNKSTS BIT(19)
|
||||||
#define GMAC_PHYIF_CTRLSTATUS_JABTO BIT(20)
|
#define GMAC_PHYIF_CTRLSTATUS_JABTO BIT(20)
|
||||||
#define GMAC_PHYIF_CTRLSTATUS_FALSECARDET BIT(21)
|
#define GMAC_PHYIF_CTRLSTATUS_FALSECARDET BIT(21)
|
||||||
/* LNKMOD */
|
|
||||||
#define GMAC_PHYIF_CTRLSTATUS_LNKMOD_MASK 0x1
|
|
||||||
/* LNKSPEED */
|
/* LNKSPEED */
|
||||||
#define GMAC_PHYIF_CTRLSTATUS_SPEED_125 0x2
|
#define GMAC_PHYIF_CTRLSTATUS_SPEED_125 0x2
|
||||||
#define GMAC_PHYIF_CTRLSTATUS_SPEED_25 0x1
|
#define GMAC_PHYIF_CTRLSTATUS_SPEED_25 0x1
|
||||||
|
@ -786,7 +786,7 @@ static void dwmac4_phystatus(void __iomem *ioaddr, struct stmmac_extra_stats *x)
|
|||||||
else
|
else
|
||||||
x->pcs_speed = SPEED_10;
|
x->pcs_speed = SPEED_10;
|
||||||
|
|
||||||
x->pcs_duplex = (status & GMAC_PHYIF_CTRLSTATUS_LNKMOD_MASK);
|
x->pcs_duplex = (status & GMAC_PHYIF_CTRLSTATUS_LNKMOD);
|
||||||
|
|
||||||
pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed,
|
pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed,
|
||||||
x->pcs_duplex ? "Full" : "Half");
|
x->pcs_duplex ? "Full" : "Half");
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Copyright (c) 2023 Bootlin, Kory Maincent <kory.maincent@bootlin.com>
|
* Copyright (c) 2023 Bootlin, Kory Maincent <kory.maincent@bootlin.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
@ -29,6 +30,8 @@
|
|||||||
#define TPS23881_REG_TPON BIT(0)
|
#define TPS23881_REG_TPON BIT(0)
|
||||||
#define TPS23881_REG_FWREV 0x41
|
#define TPS23881_REG_FWREV 0x41
|
||||||
#define TPS23881_REG_DEVID 0x43
|
#define TPS23881_REG_DEVID 0x43
|
||||||
|
#define TPS23881_REG_DEVID_MASK 0xF0
|
||||||
|
#define TPS23881_DEVICE_ID 0x02
|
||||||
#define TPS23881_REG_SRAM_CTRL 0x60
|
#define TPS23881_REG_SRAM_CTRL 0x60
|
||||||
#define TPS23881_REG_SRAM_DATA 0x61
|
#define TPS23881_REG_SRAM_DATA 0x61
|
||||||
|
|
||||||
@ -750,7 +753,7 @@ static int tps23881_i2c_probe(struct i2c_client *client)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (ret != 0x22) {
|
if (FIELD_GET(TPS23881_REG_DEVID_MASK, ret) != TPS23881_DEVICE_ID) {
|
||||||
dev_err(dev, "Wrong device ID\n");
|
dev_err(dev, "Wrong device ID\n");
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
@ -201,6 +201,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* not ip - do not know what to do */
|
/* not ip - do not know what to do */
|
||||||
|
kfree_skb(skbn);
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1431,6 +1432,7 @@ static const struct usb_device_id products[] = {
|
|||||||
{QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */
|
{QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */
|
||||||
{QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
|
{QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
|
||||||
{QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */
|
{QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */
|
||||||
|
{QMI_FIXED_INTF(0x2dee, 0x4d22, 5)}, /* MeiG Smart SRM825L */
|
||||||
|
|
||||||
/* 4. Gobi 1000 devices */
|
/* 4. Gobi 1000 devices */
|
||||||
{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
|
{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
|
||||||
|
@ -3658,6 +3658,9 @@ static int virtnet_send_rx_ctrl_coal_vq_cmd(struct virtnet_info *vi,
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_VQ_NOTF_COAL))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
err = virtnet_send_ctrl_coal_vq_cmd(vi, rxq2vq(queue),
|
err = virtnet_send_ctrl_coal_vq_cmd(vi, rxq2vq(queue),
|
||||||
max_usecs, max_packets);
|
max_usecs, max_packets);
|
||||||
if (err)
|
if (err)
|
||||||
@ -3675,6 +3678,9 @@ static int virtnet_send_tx_ctrl_coal_vq_cmd(struct virtnet_info *vi,
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_VQ_NOTF_COAL))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
err = virtnet_send_ctrl_coal_vq_cmd(vi, txq2vq(queue),
|
err = virtnet_send_ctrl_coal_vq_cmd(vi, txq2vq(queue),
|
||||||
max_usecs, max_packets);
|
max_usecs, max_packets);
|
||||||
if (err)
|
if (err)
|
||||||
@ -3743,7 +3749,11 @@ static int virtnet_set_ringparam(struct net_device *dev,
|
|||||||
err = virtnet_send_tx_ctrl_coal_vq_cmd(vi, i,
|
err = virtnet_send_tx_ctrl_coal_vq_cmd(vi, i,
|
||||||
vi->intr_coal_tx.max_usecs,
|
vi->intr_coal_tx.max_usecs,
|
||||||
vi->intr_coal_tx.max_packets);
|
vi->intr_coal_tx.max_packets);
|
||||||
if (err)
|
|
||||||
|
/* Don't break the tx resize action if the vq coalescing is not
|
||||||
|
* supported. The same is true for rx resize below.
|
||||||
|
*/
|
||||||
|
if (err && err != -EOPNOTSUPP)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3758,7 +3768,7 @@ static int virtnet_set_ringparam(struct net_device *dev,
|
|||||||
vi->intr_coal_rx.max_usecs,
|
vi->intr_coal_rx.max_usecs,
|
||||||
vi->intr_coal_rx.max_packets);
|
vi->intr_coal_rx.max_packets);
|
||||||
mutex_unlock(&vi->rq[i].dim_lock);
|
mutex_unlock(&vi->rq[i].dim_lock);
|
||||||
if (err)
|
if (err && err != -EOPNOTSUPP)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -736,10 +736,10 @@ struct kernel_ethtool_ts_info {
|
|||||||
* @rxfh_key_space: same as @rxfh_indir_space, but for the key.
|
* @rxfh_key_space: same as @rxfh_indir_space, but for the key.
|
||||||
* @rxfh_priv_size: size of the driver private data area the core should
|
* @rxfh_priv_size: size of the driver private data area the core should
|
||||||
* allocate for an RSS context (in &struct ethtool_rxfh_context).
|
* allocate for an RSS context (in &struct ethtool_rxfh_context).
|
||||||
* @rxfh_max_context_id: maximum (exclusive) supported RSS context ID. If this
|
* @rxfh_max_num_contexts: maximum (exclusive) supported RSS context ID.
|
||||||
* is zero then the core may choose any (nonzero) ID, otherwise the core
|
* If this is zero then the core may choose any (nonzero) ID, otherwise
|
||||||
* will only use IDs strictly less than this value, as the @rss_context
|
* the core will only use IDs strictly less than this value, as the
|
||||||
* argument to @create_rxfh_context and friends.
|
* @rss_context argument to @create_rxfh_context and friends.
|
||||||
* @supported_coalesce_params: supported types of interrupt coalescing.
|
* @supported_coalesce_params: supported types of interrupt coalescing.
|
||||||
* @supported_ring_params: supported ring params.
|
* @supported_ring_params: supported ring params.
|
||||||
* @get_drvinfo: Report driver/device information. Modern drivers no
|
* @get_drvinfo: Report driver/device information. Modern drivers no
|
||||||
@ -954,7 +954,7 @@ struct ethtool_ops {
|
|||||||
u32 rxfh_indir_space;
|
u32 rxfh_indir_space;
|
||||||
u16 rxfh_key_space;
|
u16 rxfh_key_space;
|
||||||
u16 rxfh_priv_size;
|
u16 rxfh_priv_size;
|
||||||
u32 rxfh_max_context_id;
|
u32 rxfh_max_num_contexts;
|
||||||
u32 supported_coalesce_params;
|
u32 supported_coalesce_params;
|
||||||
u32 supported_ring_params;
|
u32 supported_ring_params;
|
||||||
void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
|
void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
|
||||||
|
@ -3019,6 +3019,20 @@ static int hci_passive_scan_sync(struct hci_dev *hdev)
|
|||||||
} else if (hci_is_adv_monitoring(hdev)) {
|
} else if (hci_is_adv_monitoring(hdev)) {
|
||||||
window = hdev->le_scan_window_adv_monitor;
|
window = hdev->le_scan_window_adv_monitor;
|
||||||
interval = hdev->le_scan_int_adv_monitor;
|
interval = hdev->le_scan_int_adv_monitor;
|
||||||
|
|
||||||
|
/* Disable duplicates filter when scanning for advertisement
|
||||||
|
* monitor for the following reasons.
|
||||||
|
*
|
||||||
|
* For HW pattern filtering (ex. MSFT), Realtek and Qualcomm
|
||||||
|
* controllers ignore RSSI_Sampling_Period when the duplicates
|
||||||
|
* filter is enabled.
|
||||||
|
*
|
||||||
|
* For SW pattern filtering, when we're not doing interleaved
|
||||||
|
* scanning, it is necessary to disable duplicates filter,
|
||||||
|
* otherwise hosts can only receive one advertisement and it's
|
||||||
|
* impossible to know if a peer is still in range.
|
||||||
|
*/
|
||||||
|
filter_dups = LE_SCAN_FILTER_DUP_DISABLE;
|
||||||
} else {
|
} else {
|
||||||
window = hdev->le_scan_window;
|
window = hdev->le_scan_window;
|
||||||
interval = hdev->le_scan_interval;
|
interval = hdev->le_scan_interval;
|
||||||
|
@ -6774,6 +6774,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
|
|||||||
bt_cb(skb)->l2cap.psm = psm;
|
bt_cb(skb)->l2cap.psm = psm;
|
||||||
|
|
||||||
if (!chan->ops->recv(chan, skb)) {
|
if (!chan->ops->recv(chan, skb)) {
|
||||||
|
l2cap_chan_unlock(chan);
|
||||||
l2cap_chan_put(chan);
|
l2cap_chan_put(chan);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2045,16 +2045,14 @@ void br_multicast_del_port(struct net_bridge_port *port)
|
|||||||
{
|
{
|
||||||
struct net_bridge *br = port->br;
|
struct net_bridge *br = port->br;
|
||||||
struct net_bridge_port_group *pg;
|
struct net_bridge_port_group *pg;
|
||||||
HLIST_HEAD(deleted_head);
|
|
||||||
struct hlist_node *n;
|
struct hlist_node *n;
|
||||||
|
|
||||||
/* Take care of the remaining groups, only perm ones should be left */
|
/* Take care of the remaining groups, only perm ones should be left */
|
||||||
spin_lock_bh(&br->multicast_lock);
|
spin_lock_bh(&br->multicast_lock);
|
||||||
hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
|
hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
|
||||||
br_multicast_find_del_pg(br, pg);
|
br_multicast_find_del_pg(br, pg);
|
||||||
hlist_move_list(&br->mcast_gc_list, &deleted_head);
|
|
||||||
spin_unlock_bh(&br->multicast_lock);
|
spin_unlock_bh(&br->multicast_lock);
|
||||||
br_multicast_gc(&deleted_head);
|
flush_work(&br->mcast_gc_work);
|
||||||
br_multicast_port_ctx_deinit(&port->multicast_ctx);
|
br_multicast_port_ctx_deinit(&port->multicast_ctx);
|
||||||
free_percpu(port->mcast_stats);
|
free_percpu(port->mcast_stats);
|
||||||
}
|
}
|
||||||
|
@ -148,9 +148,9 @@ static void linkwatch_schedule_work(int urgent)
|
|||||||
* override the existing timer.
|
* override the existing timer.
|
||||||
*/
|
*/
|
||||||
if (test_bit(LW_URGENT, &linkwatch_flags))
|
if (test_bit(LW_URGENT, &linkwatch_flags))
|
||||||
mod_delayed_work(system_wq, &linkwatch_work, 0);
|
mod_delayed_work(system_unbound_wq, &linkwatch_work, 0);
|
||||||
else
|
else
|
||||||
schedule_delayed_work(&linkwatch_work, delay);
|
queue_delayed_work(system_unbound_wq, &linkwatch_work, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1369,14 +1369,17 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
create = rxfh.rss_context == ETH_RXFH_CONTEXT_ALLOC;
|
create = rxfh.rss_context == ETH_RXFH_CONTEXT_ALLOC;
|
||||||
|
|
||||||
/* If either indir, hash key or function is valid, proceed further.
|
|
||||||
* Must request at least one change: indir size, hash key, function
|
|
||||||
* or input transformation.
|
|
||||||
*/
|
|
||||||
if ((rxfh.indir_size &&
|
if ((rxfh.indir_size &&
|
||||||
rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE &&
|
rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE &&
|
||||||
rxfh.indir_size != dev_indir_size) ||
|
rxfh.indir_size != dev_indir_size) ||
|
||||||
(rxfh.key_size && (rxfh.key_size != dev_key_size)) ||
|
(rxfh.key_size && rxfh.key_size != dev_key_size))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Must request at least one change: indir size, hash key, function
|
||||||
|
* or input transformation.
|
||||||
|
* There's no need for any of it in case of context creation.
|
||||||
|
*/
|
||||||
|
if (!create &&
|
||||||
(rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE &&
|
(rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE &&
|
||||||
rxfh.key_size == 0 && rxfh.hfunc == ETH_RSS_HASH_NO_CHANGE &&
|
rxfh.key_size == 0 && rxfh.hfunc == ETH_RSS_HASH_NO_CHANGE &&
|
||||||
rxfh.input_xfrm == RXH_XFRM_NO_CHANGE))
|
rxfh.input_xfrm == RXH_XFRM_NO_CHANGE))
|
||||||
@ -1449,12 +1452,13 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ops->create_rxfh_context) {
|
if (ops->create_rxfh_context) {
|
||||||
u32 limit = ops->rxfh_max_context_id ?: U32_MAX;
|
u32 limit = ops->rxfh_max_num_contexts ?: U32_MAX;
|
||||||
u32 ctx_id;
|
u32 ctx_id;
|
||||||
|
|
||||||
/* driver uses new API, core allocates ID */
|
/* driver uses new API, core allocates ID */
|
||||||
ret = xa_alloc(&dev->ethtool->rss_ctx, &ctx_id, ctx,
|
ret = xa_alloc(&dev->ethtool->rss_ctx, &ctx_id, ctx,
|
||||||
XA_LIMIT(1, limit), GFP_KERNEL_ACCOUNT);
|
XA_LIMIT(1, limit - 1),
|
||||||
|
GFP_KERNEL_ACCOUNT);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -267,32 +267,49 @@ static void tcp_ao_key_free_rcu(struct rcu_head *head)
|
|||||||
kfree_sensitive(key);
|
kfree_sensitive(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_ao_destroy_sock(struct sock *sk, bool twsk)
|
static void tcp_ao_info_free_rcu(struct rcu_head *head)
|
||||||
{
|
{
|
||||||
struct tcp_ao_info *ao;
|
struct tcp_ao_info *ao = container_of(head, struct tcp_ao_info, rcu);
|
||||||
struct tcp_ao_key *key;
|
struct tcp_ao_key *key;
|
||||||
struct hlist_node *n;
|
struct hlist_node *n;
|
||||||
|
|
||||||
|
hlist_for_each_entry_safe(key, n, &ao->head, node) {
|
||||||
|
hlist_del(&key->node);
|
||||||
|
tcp_sigpool_release(key->tcp_sigpool_id);
|
||||||
|
kfree_sensitive(key);
|
||||||
|
}
|
||||||
|
kfree(ao);
|
||||||
|
static_branch_slow_dec_deferred(&tcp_ao_needed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcp_ao_sk_omem_free(struct sock *sk, struct tcp_ao_info *ao)
|
||||||
|
{
|
||||||
|
size_t total_ao_sk_mem = 0;
|
||||||
|
struct tcp_ao_key *key;
|
||||||
|
|
||||||
|
hlist_for_each_entry(key, &ao->head, node)
|
||||||
|
total_ao_sk_mem += tcp_ao_sizeof_key(key);
|
||||||
|
atomic_sub(total_ao_sk_mem, &sk->sk_omem_alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_ao_destroy_sock(struct sock *sk, bool twsk)
|
||||||
|
{
|
||||||
|
struct tcp_ao_info *ao;
|
||||||
|
|
||||||
if (twsk) {
|
if (twsk) {
|
||||||
ao = rcu_dereference_protected(tcp_twsk(sk)->ao_info, 1);
|
ao = rcu_dereference_protected(tcp_twsk(sk)->ao_info, 1);
|
||||||
tcp_twsk(sk)->ao_info = NULL;
|
rcu_assign_pointer(tcp_twsk(sk)->ao_info, NULL);
|
||||||
} else {
|
} else {
|
||||||
ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, 1);
|
ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, 1);
|
||||||
tcp_sk(sk)->ao_info = NULL;
|
rcu_assign_pointer(tcp_sk(sk)->ao_info, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ao || !refcount_dec_and_test(&ao->refcnt))
|
if (!ao || !refcount_dec_and_test(&ao->refcnt))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hlist_for_each_entry_safe(key, n, &ao->head, node) {
|
if (!twsk)
|
||||||
hlist_del_rcu(&key->node);
|
tcp_ao_sk_omem_free(sk, ao);
|
||||||
if (!twsk)
|
call_rcu(&ao->rcu, tcp_ao_info_free_rcu);
|
||||||
atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc);
|
|
||||||
call_rcu(&key->rcu, tcp_ao_key_free_rcu);
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree_rcu(ao, rcu);
|
|
||||||
static_branch_slow_dec_deferred(&tcp_ao_needed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw, struct tcp_sock *tp)
|
void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw, struct tcp_sock *tp)
|
||||||
|
@ -86,6 +86,11 @@
|
|||||||
/* Default trace flags */
|
/* Default trace flags */
|
||||||
#define L2TP_DEFAULT_DEBUG_FLAGS 0
|
#define L2TP_DEFAULT_DEBUG_FLAGS 0
|
||||||
|
|
||||||
|
#define L2TP_DEPTH_NESTING 2
|
||||||
|
#if L2TP_DEPTH_NESTING == SINGLE_DEPTH_NESTING
|
||||||
|
#error "L2TP requires its own lockdep subclass"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Private data stored for received packets in the skb.
|
/* Private data stored for received packets in the skb.
|
||||||
*/
|
*/
|
||||||
struct l2tp_skb_cb {
|
struct l2tp_skb_cb {
|
||||||
@ -1124,7 +1129,13 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
|
|||||||
IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
|
IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
|
||||||
nf_reset_ct(skb);
|
nf_reset_ct(skb);
|
||||||
|
|
||||||
bh_lock_sock_nested(sk);
|
/* L2TP uses its own lockdep subclass to avoid lockdep splats caused by
|
||||||
|
* nested socket calls on the same lockdep socket class. This can
|
||||||
|
* happen when data from a user socket is routed over l2tp, which uses
|
||||||
|
* another userspace socket.
|
||||||
|
*/
|
||||||
|
spin_lock_nested(&sk->sk_lock.slock, L2TP_DEPTH_NESTING);
|
||||||
|
|
||||||
if (sock_owned_by_user(sk)) {
|
if (sock_owned_by_user(sk)) {
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
ret = NET_XMIT_DROP;
|
ret = NET_XMIT_DROP;
|
||||||
@ -1176,7 +1187,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
|
|||||||
ret = l2tp_xmit_queue(tunnel, skb, &inet->cork.fl);
|
ret = l2tp_xmit_queue(tunnel, skb, &inet->cork.fl);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
bh_unlock_sock(sk);
|
spin_unlock(&sk->sk_lock.slock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -958,7 +958,8 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
|
|||||||
|
|
||||||
if (subflow->remote_key_valid &&
|
if (subflow->remote_key_valid &&
|
||||||
(((mp_opt->suboptions & OPTION_MPTCP_DSS) && mp_opt->use_ack) ||
|
(((mp_opt->suboptions & OPTION_MPTCP_DSS) && mp_opt->use_ack) ||
|
||||||
((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) && !mp_opt->echo))) {
|
((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) &&
|
||||||
|
(!mp_opt->echo || subflow->mp_join)))) {
|
||||||
/* subflows are fully established as soon as we get any
|
/* subflows are fully established as soon as we get any
|
||||||
* additional ack, including ADD_ADDR.
|
* additional ack, including ADD_ADDR.
|
||||||
*/
|
*/
|
||||||
|
@ -348,7 +348,7 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
|
|||||||
add_entry = mptcp_lookup_anno_list_by_saddr(msk, addr);
|
add_entry = mptcp_lookup_anno_list_by_saddr(msk, addr);
|
||||||
|
|
||||||
if (add_entry) {
|
if (add_entry) {
|
||||||
if (mptcp_pm_is_kernel(msk))
|
if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sk_reset_timer(sk, &add_entry->add_timer,
|
sk_reset_timer(sk, &add_entry->add_timer,
|
||||||
@ -512,8 +512,8 @@ __lookup_addr(struct pm_nl_pernet *pernet, const struct mptcp_addr_info *info)
|
|||||||
|
|
||||||
static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
|
static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
|
||||||
{
|
{
|
||||||
|
struct mptcp_pm_addr_entry *local, *signal_and_subflow = NULL;
|
||||||
struct sock *sk = (struct sock *)msk;
|
struct sock *sk = (struct sock *)msk;
|
||||||
struct mptcp_pm_addr_entry *local;
|
|
||||||
unsigned int add_addr_signal_max;
|
unsigned int add_addr_signal_max;
|
||||||
unsigned int local_addr_max;
|
unsigned int local_addr_max;
|
||||||
struct pm_nl_pernet *pernet;
|
struct pm_nl_pernet *pernet;
|
||||||
@ -555,8 +555,6 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
|
|||||||
|
|
||||||
/* check first for announce */
|
/* check first for announce */
|
||||||
if (msk->pm.add_addr_signaled < add_addr_signal_max) {
|
if (msk->pm.add_addr_signaled < add_addr_signal_max) {
|
||||||
local = select_signal_address(pernet, msk);
|
|
||||||
|
|
||||||
/* due to racing events on both ends we can reach here while
|
/* due to racing events on both ends we can reach here while
|
||||||
* previous add address is still running: if we invoke now
|
* previous add address is still running: if we invoke now
|
||||||
* mptcp_pm_announce_addr(), that will fail and the
|
* mptcp_pm_announce_addr(), that will fail and the
|
||||||
@ -567,16 +565,26 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
|
|||||||
if (msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL))
|
if (msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (local) {
|
local = select_signal_address(pernet, msk);
|
||||||
if (mptcp_pm_alloc_anno_list(msk, &local->addr)) {
|
if (!local)
|
||||||
__clear_bit(local->addr.id, msk->pm.id_avail_bitmap);
|
goto subflow;
|
||||||
msk->pm.add_addr_signaled++;
|
|
||||||
mptcp_pm_announce_addr(msk, &local->addr, false);
|
/* If the alloc fails, we are on memory pressure, not worth
|
||||||
mptcp_pm_nl_addr_send_ack(msk);
|
* continuing, and trying to create subflows.
|
||||||
}
|
*/
|
||||||
}
|
if (!mptcp_pm_alloc_anno_list(msk, &local->addr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
__clear_bit(local->addr.id, msk->pm.id_avail_bitmap);
|
||||||
|
msk->pm.add_addr_signaled++;
|
||||||
|
mptcp_pm_announce_addr(msk, &local->addr, false);
|
||||||
|
mptcp_pm_nl_addr_send_ack(msk);
|
||||||
|
|
||||||
|
if (local->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW)
|
||||||
|
signal_and_subflow = local;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subflow:
|
||||||
/* check if should create a new subflow */
|
/* check if should create a new subflow */
|
||||||
while (msk->pm.local_addr_used < local_addr_max &&
|
while (msk->pm.local_addr_used < local_addr_max &&
|
||||||
msk->pm.subflows < subflows_max) {
|
msk->pm.subflows < subflows_max) {
|
||||||
@ -584,9 +592,14 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
|
|||||||
bool fullmesh;
|
bool fullmesh;
|
||||||
int i, nr;
|
int i, nr;
|
||||||
|
|
||||||
local = select_local_address(pernet, msk);
|
if (signal_and_subflow) {
|
||||||
if (!local)
|
local = signal_and_subflow;
|
||||||
break;
|
signal_and_subflow = NULL;
|
||||||
|
} else {
|
||||||
|
local = select_local_address(pernet, msk);
|
||||||
|
if (!local)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
fullmesh = !!(local->flags & MPTCP_PM_ADDR_FLAG_FULLMESH);
|
fullmesh = !!(local->flags & MPTCP_PM_ADDR_FLAG_FULLMESH);
|
||||||
|
|
||||||
@ -1328,8 +1341,8 @@ int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (addr.addr.port && !(addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) {
|
if (addr.addr.port && !address_use_port(&addr)) {
|
||||||
GENL_SET_ERR_MSG(info, "flags must have signal when using port");
|
GENL_SET_ERR_MSG(info, "flags must have signal and not subflow when using port");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,15 +735,19 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep)
|
|||||||
struct sock *sk = ep->base.sk;
|
struct sock *sk = ep->base.sk;
|
||||||
struct net *net = sock_net(sk);
|
struct net *net = sock_net(sk);
|
||||||
struct sctp_hashbucket *head;
|
struct sctp_hashbucket *head;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
ep->hashent = sctp_ep_hashfn(net, ep->base.bind_addr.port);
|
ep->hashent = sctp_ep_hashfn(net, ep->base.bind_addr.port);
|
||||||
head = &sctp_ep_hashtable[ep->hashent];
|
head = &sctp_ep_hashtable[ep->hashent];
|
||||||
|
|
||||||
|
write_lock(&head->lock);
|
||||||
if (sk->sk_reuseport) {
|
if (sk->sk_reuseport) {
|
||||||
bool any = sctp_is_ep_boundall(sk);
|
bool any = sctp_is_ep_boundall(sk);
|
||||||
struct sctp_endpoint *ep2;
|
struct sctp_endpoint *ep2;
|
||||||
struct list_head *list;
|
struct list_head *list;
|
||||||
int cnt = 0, err = 1;
|
int cnt = 0;
|
||||||
|
|
||||||
|
err = 1;
|
||||||
|
|
||||||
list_for_each(list, &ep->base.bind_addr.address_list)
|
list_for_each(list, &ep->base.bind_addr.address_list)
|
||||||
cnt++;
|
cnt++;
|
||||||
@ -761,24 +765,24 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep)
|
|||||||
if (!err) {
|
if (!err) {
|
||||||
err = reuseport_add_sock(sk, sk2, any);
|
err = reuseport_add_sock(sk, sk2, any);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
break;
|
break;
|
||||||
} else if (err < 0) {
|
} else if (err < 0) {
|
||||||
return err;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
err = reuseport_alloc(sk, any);
|
err = reuseport_alloc(sk, any);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write_lock(&head->lock);
|
|
||||||
hlist_add_head(&ep->node, &head->chain);
|
hlist_add_head(&ep->node, &head->chain);
|
||||||
|
out:
|
||||||
write_unlock(&head->lock);
|
write_unlock(&head->lock);
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add an endpoint to the hash. Local BH-safe. */
|
/* Add an endpoint to the hash. Local BH-safe. */
|
||||||
@ -803,10 +807,9 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
|
|||||||
|
|
||||||
head = &sctp_ep_hashtable[ep->hashent];
|
head = &sctp_ep_hashtable[ep->hashent];
|
||||||
|
|
||||||
|
write_lock(&head->lock);
|
||||||
if (rcu_access_pointer(sk->sk_reuseport_cb))
|
if (rcu_access_pointer(sk->sk_reuseport_cb))
|
||||||
reuseport_detach_sock(sk);
|
reuseport_detach_sock(sk);
|
||||||
|
|
||||||
write_lock(&head->lock);
|
|
||||||
hlist_del_init(&ep->node);
|
hlist_del_init(&ep->node);
|
||||||
write_unlock(&head->lock);
|
write_unlock(&head->lock);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "smc_clc.h"
|
#include "smc_clc.h"
|
||||||
|
|
||||||
#define SMC_MAX_FBACK_RSN_CNT 30
|
#define SMC_MAX_FBACK_RSN_CNT 36
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SMC_BUF_8K,
|
SMC_BUF_8K,
|
||||||
|
@ -1415,18 +1415,28 @@ chk_add_nr()
|
|||||||
local add_nr=$1
|
local add_nr=$1
|
||||||
local echo_nr=$2
|
local echo_nr=$2
|
||||||
local port_nr=${3:-0}
|
local port_nr=${3:-0}
|
||||||
local syn_nr=${4:-$port_nr}
|
local ns_invert=${4:-""}
|
||||||
local syn_ack_nr=${5:-$port_nr}
|
local syn_nr=$port_nr
|
||||||
local ack_nr=${6:-$port_nr}
|
local syn_ack_nr=$port_nr
|
||||||
local mis_syn_nr=${7:-0}
|
local ack_nr=$port_nr
|
||||||
local mis_ack_nr=${8:-0}
|
local mis_syn_nr=0
|
||||||
|
local mis_ack_nr=0
|
||||||
|
local ns_tx=$ns1
|
||||||
|
local ns_rx=$ns2
|
||||||
|
local extra_msg=""
|
||||||
local count
|
local count
|
||||||
local timeout
|
local timeout
|
||||||
|
|
||||||
timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout)
|
if [[ $ns_invert = "invert" ]]; then
|
||||||
|
ns_tx=$ns2
|
||||||
|
ns_rx=$ns1
|
||||||
|
extra_msg="invert"
|
||||||
|
fi
|
||||||
|
|
||||||
|
timeout=$(ip netns exec ${ns_tx} sysctl -n net.mptcp.add_addr_timeout)
|
||||||
|
|
||||||
print_check "add"
|
print_check "add"
|
||||||
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtAddAddr")
|
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtAddAddr")
|
||||||
if [ -z "$count" ]; then
|
if [ -z "$count" ]; then
|
||||||
print_skip
|
print_skip
|
||||||
# if the test configured a short timeout tolerate greater then expected
|
# if the test configured a short timeout tolerate greater then expected
|
||||||
@ -1438,7 +1448,7 @@ chk_add_nr()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_check "echo"
|
print_check "echo"
|
||||||
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtEchoAdd")
|
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtEchoAdd")
|
||||||
if [ -z "$count" ]; then
|
if [ -z "$count" ]; then
|
||||||
print_skip
|
print_skip
|
||||||
elif [ "$count" != "$echo_nr" ]; then
|
elif [ "$count" != "$echo_nr" ]; then
|
||||||
@ -1449,7 +1459,7 @@ chk_add_nr()
|
|||||||
|
|
||||||
if [ $port_nr -gt 0 ]; then
|
if [ $port_nr -gt 0 ]; then
|
||||||
print_check "pt"
|
print_check "pt"
|
||||||
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtPortAdd")
|
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtPortAdd")
|
||||||
if [ -z "$count" ]; then
|
if [ -z "$count" ]; then
|
||||||
print_skip
|
print_skip
|
||||||
elif [ "$count" != "$port_nr" ]; then
|
elif [ "$count" != "$port_nr" ]; then
|
||||||
@ -1459,7 +1469,7 @@ chk_add_nr()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_check "syn"
|
print_check "syn"
|
||||||
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortSynRx")
|
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortSynRx")
|
||||||
if [ -z "$count" ]; then
|
if [ -z "$count" ]; then
|
||||||
print_skip
|
print_skip
|
||||||
elif [ "$count" != "$syn_nr" ]; then
|
elif [ "$count" != "$syn_nr" ]; then
|
||||||
@ -1470,7 +1480,7 @@ chk_add_nr()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_check "synack"
|
print_check "synack"
|
||||||
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx")
|
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPJoinPortSynAckRx")
|
||||||
if [ -z "$count" ]; then
|
if [ -z "$count" ]; then
|
||||||
print_skip
|
print_skip
|
||||||
elif [ "$count" != "$syn_ack_nr" ]; then
|
elif [ "$count" != "$syn_ack_nr" ]; then
|
||||||
@ -1481,7 +1491,7 @@ chk_add_nr()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_check "ack"
|
print_check "ack"
|
||||||
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortAckRx")
|
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortAckRx")
|
||||||
if [ -z "$count" ]; then
|
if [ -z "$count" ]; then
|
||||||
print_skip
|
print_skip
|
||||||
elif [ "$count" != "$ack_nr" ]; then
|
elif [ "$count" != "$ack_nr" ]; then
|
||||||
@ -1492,7 +1502,7 @@ chk_add_nr()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_check "syn"
|
print_check "syn"
|
||||||
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortSynRx")
|
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortSynRx")
|
||||||
if [ -z "$count" ]; then
|
if [ -z "$count" ]; then
|
||||||
print_skip
|
print_skip
|
||||||
elif [ "$count" != "$mis_syn_nr" ]; then
|
elif [ "$count" != "$mis_syn_nr" ]; then
|
||||||
@ -1503,7 +1513,7 @@ chk_add_nr()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_check "ack"
|
print_check "ack"
|
||||||
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortAckRx")
|
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortAckRx")
|
||||||
if [ -z "$count" ]; then
|
if [ -z "$count" ]; then
|
||||||
print_skip
|
print_skip
|
||||||
elif [ "$count" != "$mis_ack_nr" ]; then
|
elif [ "$count" != "$mis_ack_nr" ]; then
|
||||||
@ -1513,6 +1523,8 @@ chk_add_nr()
|
|||||||
print_ok
|
print_ok
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
print_info "$extra_msg"
|
||||||
}
|
}
|
||||||
|
|
||||||
chk_add_tx_nr()
|
chk_add_tx_nr()
|
||||||
@ -1977,6 +1989,21 @@ signal_address_tests()
|
|||||||
chk_add_nr 1 1
|
chk_add_nr 1 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# uncommon: subflow and signal flags on the same endpoint
|
||||||
|
# or because the user wrongly picked both, but still expects the client
|
||||||
|
# to create additional subflows
|
||||||
|
if reset "subflow and signal together"; then
|
||||||
|
pm_nl_set_limits $ns1 0 2
|
||||||
|
pm_nl_set_limits $ns2 0 2
|
||||||
|
pm_nl_add_endpoint $ns2 10.0.3.2 flags signal,subflow
|
||||||
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
|
chk_join_nr 1 1 1
|
||||||
|
chk_add_nr 1 1 0 invert # only initiated by ns2
|
||||||
|
chk_add_nr 0 0 0 # none initiated by ns1
|
||||||
|
chk_rst_nr 0 0 invert # no RST sent by the client
|
||||||
|
chk_rst_nr 0 0 # no RST sent by the server
|
||||||
|
fi
|
||||||
|
|
||||||
# accept and use add_addr with additional subflows
|
# accept and use add_addr with additional subflows
|
||||||
if reset "multiple subflows and signal"; then
|
if reset "multiple subflows and signal"; then
|
||||||
pm_nl_set_limits $ns1 0 3
|
pm_nl_set_limits $ns1 0 3
|
||||||
|
Loading…
Reference in New Issue
Block a user