mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 14:21:47 +00:00
Including fixes from bpf, can and netfilter.
Current release - regressions: - phy: fix null-deref in phy_attach_direct - mac802154: fix possible double free upon parsing error Previous releases - regressions: - bpf: preserve reg parent/live fields when copying range info, prevent mis-verification of programs as safe - ip6: fix GRE tunnels not generating IPv6 link local addresses - phy: dp83822: fix null-deref on DP83825/DP83826 devices - sctp: do not check hb_timer.expires when resetting hb_timer - eth: mtk_sock: fix SGMII configuration after phylink conversion Previous releases - always broken: - eth: xdp: execute xdp_do_flush() before napi_complete_done() - skb: do not mix page pool and page referenced frags in GRO - bpf: - fix a possible task gone issue with bpf_send_signal[_thread]() - fix an off-by-one bug in bpf_mem_cache_idx() to select the right cache - add missing btf_put to register_btf_id_dtor_kfuncs - sockmap: fon't let sock_map_{close,destroy,unhash} call itself - gso: fix null-deref in skb_segment_list() - mctp: purge receive queues on sk destruction - fix UaF caused by accept on already connected socket in exotic socket families - tls: don't treat list head as an entry in tls_is_tx_ready() - netfilter: br_netfilter: disable sabotage_in hook after first suppression - wwan: t7xx: fix runtime PM implementation Misc: - MAINTAINERS: spring cleanup of networking maintainers Signed-off-by: Jakub Kicinski <kuba@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmPcKlkACgkQMUZtbf5S IrtHgxAAxvuXeN9kQ+/gDYbxTa4Fc3gwCAA7SdJiBdfxP9xJAUEBs9TNfh5MPynb iIWl9tTe1OOQtWJTnp5CKMuegUj4hlJVYuLu4MK36hW56Q41cbCFvhsDk/1xoFTF 2mtmEr5JiXZfgEdf9/tEITTGKgfANsbXOAzL4b5HcV9qtvwvEd2aFxll3VO9N2Xn k6o59Lr2mff7NnXQsrVkTLBxXRK9oir8VwyTnCs7j+T7E8Qe4hIkx2LDWcDiRC1e vSxfoWFoe+uOGTQMxlarMOAgAOt7nvOQngwCaaVpMBa/OLzGo51Clf98cpPm+cSi 18ZjmA8r5owGghd75p2PtxcND8U1vXeeRJW+FKK60K8qznMc0D4s7HX+wHBfevnV U649F0OHsNsX0Y75Z5sqA1eSmJbTR9QeyiRbuS6nfOnT7ZKDw6vPJrKGJRN789y0 erzG/JwrfnrCDavXfNNEgk0mMlP0squemffWjuH6FfL4Pt4/gUz63Nokr5vRFSns yskHZgXVs4gq++yrbZDZjKfQaPDkA1P/z6VADVRWh4Y5m1m6GtvDUy6vJxK7/hUs 5giqmhbAAQq0U+2L5RIaoYGfjk2UaDcunNpqTCgjdCdMXx9Yz41QBloFgBjRshp/ 3kg6ElYPzflXXCYK4pGRrzqO4Gqz1Hrvr9YuT+kka+wrpZPDtWc= =OGU7 -----END PGP SIGNATURE----- Merge tag 'net-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Jakub Kicinski: "Including fixes from bpf, can and netfilter. Current release - regressions: - phy: fix null-deref in phy_attach_direct - mac802154: fix possible double free upon parsing error Previous releases - regressions: - bpf: preserve reg parent/live fields when copying range info, prevent mis-verification of programs as safe - ip6: fix GRE tunnels not generating IPv6 link local addresses - phy: dp83822: fix null-deref on DP83825/DP83826 devices - sctp: do not check hb_timer.expires when resetting hb_timer - eth: mtk_sock: fix SGMII configuration after phylink conversion Previous releases - always broken: - eth: xdp: execute xdp_do_flush() before napi_complete_done() - skb: do not mix page pool and page referenced frags in GRO - bpf: - fix a possible task gone issue with bpf_send_signal[_thread]() - fix an off-by-one bug in bpf_mem_cache_idx() to select the right cache - add missing btf_put to register_btf_id_dtor_kfuncs - sockmap: fon't let sock_map_{close,destroy,unhash} call itself - gso: fix null-deref in skb_segment_list() - mctp: purge receive queues on sk destruction - fix UaF caused by accept on already connected socket in exotic socket families - tls: don't treat list head as an entry in tls_is_tx_ready() - netfilter: br_netfilter: disable sabotage_in hook after first suppression - wwan: t7xx: fix runtime PM implementation Misc: - MAINTAINERS: spring cleanup of networking maintainers" * tag 'net-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (65 commits) mtk_sgmii: enable PCS polling to allow SFP work net: mediatek: sgmii: fix duplex configuration net: mediatek: sgmii: ensure the SGMII PHY is powered down on configuration MAINTAINERS: update SCTP maintainers MAINTAINERS: ipv6: retire Hideaki Yoshifuji mailmap: add John Crispin's entry MAINTAINERS: bonding: move Veaceslav Falico to CREDITS net: openvswitch: fix flow memory leak in ovs_flow_cmd_new net: ethernet: mtk_eth_soc: disable hardware DSA untagging for second MAC virtio-net: Keep stop() to follow mirror sequence of open() selftests: net: udpgso_bench_tx: Cater for pending datagrams zerocopy benchmarking selftests: net: udpgso_bench: Fix racing bug between the rx/tx programs selftests: net: udpgso_bench_rx/tx: Stop when wrong CLI args are provided selftests: net: udpgso_bench_rx: Fix 'used uninitialized' compiler warning can: mcp251xfd: mcp251xfd_ring_set_ringparam(): assign missing tx_obj_num_coalesce_irq can: isotp: split tx timer into transmission and timeout can: isotp: handle wait_event_interruptible() return values can: raw: fix CAN FD frame transmissions over CAN XL devices can: j1939: fix errant WARN_ON_ONCE in j1939_session_deactivate hv_netvsc: Fix missed pagebuf entries in netvsc_dma_map/unmap() ...
This commit is contained in:
commit
edb9b8f380
1
.mailmap
1
.mailmap
@ -214,6 +214,7 @@ Jisheng Zhang <jszhang@kernel.org> <jszhang@marvell.com>
|
||||
Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com>
|
||||
Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
|
||||
Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
|
||||
John Crispin <john@phrozen.org> <blogic@openwrt.org>
|
||||
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
|
||||
John Stultz <johnstul@us.ibm.com>
|
||||
Jordan Crouse <jordan@cosmicpenguin.net> <jcrouse@codeaurora.org>
|
||||
|
8
CREDITS
8
CREDITS
@ -1173,6 +1173,10 @@ D: Future Domain TMC-16x0 SCSI driver (author)
|
||||
D: APM driver (early port)
|
||||
D: DRM drivers (author of several)
|
||||
|
||||
N: Veaceslav Falico
|
||||
E: vfalico@gmail.com
|
||||
D: Co-maintainer and co-author of the network bonding driver.
|
||||
|
||||
N: János Farkas
|
||||
E: chexum@shadow.banki.hu
|
||||
D: romfs, various (mostly networking) fixes
|
||||
@ -4179,6 +4183,10 @@ S: B-1206 Jingmao Guojigongyu
|
||||
S: 16 Baliqiao Nanjie, Beijing 101100
|
||||
S: People's Repulic of China
|
||||
|
||||
N: Vlad Yasevich
|
||||
E: vyasevich@gmail.com
|
||||
D: SCTP protocol maintainer.
|
||||
|
||||
N: Aviad Yehezkel
|
||||
E: aviadye@nvidia.com
|
||||
D: Kernel TLS implementation and offload support.
|
||||
|
@ -819,7 +819,7 @@ NAPI
|
||||
----
|
||||
This driver supports NAPI (Rx polling mode).
|
||||
For more information on NAPI, see
|
||||
https://www.linuxfoundation.org/collaborate/workgroups/networking/napi
|
||||
https://wiki.linuxfoundation.org/networking/napi
|
||||
|
||||
|
||||
MACVLAN
|
||||
|
@ -3771,7 +3771,6 @@ F: net/bluetooth/
|
||||
|
||||
BONDING DRIVER
|
||||
M: Jay Vosburgh <j.vosburgh@gmail.com>
|
||||
M: Veaceslav Falico <vfalico@gmail.com>
|
||||
M: Andy Gospodarek <andy@greyhouse.net>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
@ -14609,7 +14608,6 @@ F: tools/testing/selftests/net/ipsec.c
|
||||
|
||||
NETWORKING [IPv4/IPv6]
|
||||
M: "David S. Miller" <davem@davemloft.net>
|
||||
M: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
|
||||
M: David Ahern <dsahern@kernel.org>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
@ -18692,9 +18690,9 @@ F: drivers/target/
|
||||
F: include/target/
|
||||
|
||||
SCTP PROTOCOL
|
||||
M: Vlad Yasevich <vyasevich@gmail.com>
|
||||
M: Neil Horman <nhorman@tuxdriver.com>
|
||||
M: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
|
||||
M: Xin Long <lucien.xin@gmail.com>
|
||||
L: linux-sctp@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://lksctp.sourceforge.net
|
||||
|
@ -48,6 +48,7 @@ mcp251xfd_ring_set_ringparam(struct net_device *ndev,
|
||||
priv->rx_obj_num = layout.cur_rx;
|
||||
priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;
|
||||
priv->tx->obj_num = layout.cur_tx;
|
||||
priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -35,12 +35,13 @@ config NET_DSA_LANTIQ_GSWIP
|
||||
the xrx200 / VR9 SoC.
|
||||
|
||||
config NET_DSA_MT7530
|
||||
tristate "MediaTek MT753x and MT7621 Ethernet switch support"
|
||||
tristate "MediaTek MT7530 and MT7531 Ethernet switch support"
|
||||
select NET_DSA_TAG_MTK
|
||||
select MEDIATEK_GE_PHY
|
||||
help
|
||||
This enables support for the MediaTek MT7530, MT7531, and MT7621
|
||||
Ethernet switch chips.
|
||||
This enables support for the MediaTek MT7530 and MT7531 Ethernet
|
||||
switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT,
|
||||
MT7621ST and MT7623AI SoCs is supported.
|
||||
|
||||
config NET_DSA_MV88E6060
|
||||
tristate "Marvell 88E6060 ethernet switch chip support"
|
||||
|
@ -2410,6 +2410,9 @@ static int dpaa_eth_poll(struct napi_struct *napi, int budget)
|
||||
|
||||
cleaned = qman_p_poll_dqrr(np->p, budget);
|
||||
|
||||
if (np->xdp_act & XDP_REDIRECT)
|
||||
xdp_do_flush();
|
||||
|
||||
if (cleaned < budget) {
|
||||
napi_complete_done(napi, cleaned);
|
||||
qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
|
||||
@ -2417,9 +2420,6 @@ static int dpaa_eth_poll(struct napi_struct *napi, int budget)
|
||||
qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
|
||||
}
|
||||
|
||||
if (np->xdp_act & XDP_REDIRECT)
|
||||
xdp_do_flush();
|
||||
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
|
@ -1993,10 +1993,15 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
|
||||
if (rx_cleaned >= budget ||
|
||||
txconf_cleaned >= DPAA2_ETH_TXCONF_PER_NAPI) {
|
||||
work_done = budget;
|
||||
if (ch->xdp.res & XDP_REDIRECT)
|
||||
xdp_do_flush();
|
||||
goto out;
|
||||
}
|
||||
} while (store_cleaned);
|
||||
|
||||
if (ch->xdp.res & XDP_REDIRECT)
|
||||
xdp_do_flush();
|
||||
|
||||
/* Update NET DIM with the values for this CDAN */
|
||||
dpaa2_io_update_net_dim(ch->dpio, ch->stats.frames_per_cdan,
|
||||
ch->stats.bytes_per_cdan);
|
||||
@ -2032,9 +2037,7 @@ out:
|
||||
txc_fq->dq_bytes = 0;
|
||||
}
|
||||
|
||||
if (ch->xdp.res & XDP_REDIRECT)
|
||||
xdp_do_flush_map();
|
||||
else if (rx_cleaned && ch->xdp.res & XDP_TX)
|
||||
if (rx_cleaned && ch->xdp.res & XDP_TX)
|
||||
dpaa2_eth_xdp_tx_flush(priv, ch, &priv->fq[flowid]);
|
||||
|
||||
return work_done;
|
||||
|
@ -1055,6 +1055,9 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
pcs = lynx_pcs_create(mdiodev);
|
||||
if (!pcs)
|
||||
mdio_device_free(mdiodev);
|
||||
|
||||
return pcs;
|
||||
}
|
||||
|
||||
|
@ -880,7 +880,7 @@ void ice_set_ethtool_repr_ops(struct net_device *netdev);
|
||||
void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
|
||||
u16 ice_get_avail_txq_count(struct ice_pf *pf);
|
||||
u16 ice_get_avail_rxq_count(struct ice_pf *pf);
|
||||
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx);
|
||||
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked);
|
||||
void ice_update_vsi_stats(struct ice_vsi *vsi);
|
||||
void ice_update_pf_stats(struct ice_pf *pf);
|
||||
void
|
||||
|
@ -441,7 +441,7 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ice_pf_dcb_recfg(pf);
|
||||
ice_pf_dcb_recfg(pf, false);
|
||||
|
||||
out:
|
||||
/* enable previously downed VSIs */
|
||||
@ -731,12 +731,13 @@ static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
|
||||
/**
|
||||
* ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
|
||||
* @pf: pointer to the PF struct
|
||||
* @locked: is adev device lock held
|
||||
*
|
||||
* Assumed caller has already disabled all VSIs before
|
||||
* calling this function. Reconfiguring DCB based on
|
||||
* local_dcbx_cfg.
|
||||
*/
|
||||
void ice_pf_dcb_recfg(struct ice_pf *pf)
|
||||
void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked)
|
||||
{
|
||||
struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
|
||||
struct iidc_event *event;
|
||||
@ -783,14 +784,16 @@ void ice_pf_dcb_recfg(struct ice_pf *pf)
|
||||
if (vsi->type == ICE_VSI_PF)
|
||||
ice_dcbnl_set_all(vsi);
|
||||
}
|
||||
/* Notify the AUX drivers that TC change is finished */
|
||||
event = kzalloc(sizeof(*event), GFP_KERNEL);
|
||||
if (!event)
|
||||
return;
|
||||
if (!locked) {
|
||||
/* Notify the AUX drivers that TC change is finished */
|
||||
event = kzalloc(sizeof(*event), GFP_KERNEL);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
set_bit(IIDC_EVENT_AFTER_TC_CHANGE, event->type);
|
||||
ice_send_event_to_aux(pf, event);
|
||||
kfree(event);
|
||||
set_bit(IIDC_EVENT_AFTER_TC_CHANGE, event->type);
|
||||
ice_send_event_to_aux(pf, event);
|
||||
kfree(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1044,7 +1047,7 @@ ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
|
||||
}
|
||||
|
||||
/* changes in configuration update VSI */
|
||||
ice_pf_dcb_recfg(pf);
|
||||
ice_pf_dcb_recfg(pf, false);
|
||||
|
||||
/* enable previously downed VSIs */
|
||||
ice_dcb_ena_dis_vsi(pf, true, true);
|
||||
|
@ -23,7 +23,7 @@ u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index);
|
||||
int
|
||||
ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked);
|
||||
int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg);
|
||||
void ice_pf_dcb_recfg(struct ice_pf *pf);
|
||||
void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked);
|
||||
void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi);
|
||||
int ice_init_pf_dcb(struct ice_pf *pf, bool locked);
|
||||
void ice_update_dcb_stats(struct ice_pf *pf);
|
||||
@ -128,7 +128,7 @@ static inline u8 ice_get_pfc_mode(struct ice_pf *pf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ice_pf_dcb_recfg(struct ice_pf *pf) { }
|
||||
static inline void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked) { }
|
||||
static inline void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi) { }
|
||||
static inline void ice_update_dcb_stats(struct ice_pf *pf) { }
|
||||
static inline void
|
||||
|
@ -3641,7 +3641,9 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
|
||||
struct ice_vsi *vsi = np->vsi;
|
||||
struct ice_pf *pf = vsi->back;
|
||||
int new_rx = 0, new_tx = 0;
|
||||
bool locked = false;
|
||||
u32 curr_combined;
|
||||
int ret = 0;
|
||||
|
||||
/* do not support changing channels in Safe Mode */
|
||||
if (ice_is_safe_mode(pf)) {
|
||||
@ -3705,15 +3707,33 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ice_vsi_recfg_qs(vsi, new_rx, new_tx);
|
||||
if (pf->adev) {
|
||||
mutex_lock(&pf->adev_mutex);
|
||||
device_lock(&pf->adev->dev);
|
||||
locked = true;
|
||||
if (pf->adev->dev.driver) {
|
||||
netdev_err(dev, "Cannot change channels when RDMA is active\n");
|
||||
ret = -EBUSY;
|
||||
goto adev_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
if (!netif_is_rxfh_configured(dev))
|
||||
return ice_vsi_set_dflt_rss_lut(vsi, new_rx);
|
||||
ice_vsi_recfg_qs(vsi, new_rx, new_tx, locked);
|
||||
|
||||
if (!netif_is_rxfh_configured(dev)) {
|
||||
ret = ice_vsi_set_dflt_rss_lut(vsi, new_rx);
|
||||
goto adev_unlock;
|
||||
}
|
||||
|
||||
/* Update rss_size due to change in Rx queues */
|
||||
vsi->rss_size = ice_get_valid_rss_size(&pf->hw, new_rx);
|
||||
|
||||
return 0;
|
||||
adev_unlock:
|
||||
if (locked) {
|
||||
device_unlock(&pf->adev->dev);
|
||||
mutex_unlock(&pf->adev_mutex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4195,12 +4195,13 @@ bool ice_is_wol_supported(struct ice_hw *hw)
|
||||
* @vsi: VSI being changed
|
||||
* @new_rx: new number of Rx queues
|
||||
* @new_tx: new number of Tx queues
|
||||
* @locked: is adev device_lock held
|
||||
*
|
||||
* Only change the number of queues if new_tx, or new_rx is non-0.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx)
|
||||
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked)
|
||||
{
|
||||
struct ice_pf *pf = vsi->back;
|
||||
int err = 0, timeout = 50;
|
||||
@ -4229,7 +4230,7 @@ int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx)
|
||||
|
||||
ice_vsi_close(vsi);
|
||||
ice_vsi_rebuild(vsi, false);
|
||||
ice_pf_dcb_recfg(pf);
|
||||
ice_pf_dcb_recfg(pf, locked);
|
||||
ice_vsi_open(vsi);
|
||||
done:
|
||||
clear_bit(ICE_CFG_BUSY, pf->state);
|
||||
|
@ -417,10 +417,12 @@ static int igc_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
|
||||
*
|
||||
* We need to convert the system time value stored in the RX/TXSTMP registers
|
||||
* into a hwtstamp which can be used by the upper level timestamping functions.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
**/
|
||||
static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
|
||||
struct skb_shared_hwtstamps *hwtstamps,
|
||||
u64 systim)
|
||||
static int igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
|
||||
struct skb_shared_hwtstamps *hwtstamps,
|
||||
u64 systim)
|
||||
{
|
||||
switch (adapter->hw.mac.type) {
|
||||
case igc_i225:
|
||||
@ -430,8 +432,9 @@ static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
|
||||
systim & 0xFFFFFFFF);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -652,7 +655,8 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
|
||||
|
||||
regval = rd32(IGC_TXSTMPL);
|
||||
regval |= (u64)rd32(IGC_TXSTMPH) << 32;
|
||||
igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
|
||||
if (igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval))
|
||||
return;
|
||||
|
||||
switch (adapter->link_speed) {
|
||||
case SPEED_10:
|
||||
|
@ -1500,6 +1500,9 @@ static const struct devlink_param rvu_af_dl_params[] = {
|
||||
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
|
||||
rvu_af_dl_dwrr_mtu_get, rvu_af_dl_dwrr_mtu_set,
|
||||
rvu_af_dl_dwrr_mtu_validate),
|
||||
};
|
||||
|
||||
static const struct devlink_param rvu_af_dl_param_exact_match[] = {
|
||||
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
|
||||
"npc_exact_feature_disable", DEVLINK_PARAM_TYPE_STRING,
|
||||
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
|
||||
@ -1556,7 +1559,6 @@ int rvu_register_dl(struct rvu *rvu)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl;
|
||||
struct devlink *dl;
|
||||
size_t size;
|
||||
int err;
|
||||
|
||||
dl = devlink_alloc(&rvu_devlink_ops, sizeof(struct rvu_devlink),
|
||||
@ -1578,21 +1580,32 @@ int rvu_register_dl(struct rvu *rvu)
|
||||
goto err_dl_health;
|
||||
}
|
||||
|
||||
/* Register exact match devlink only for CN10K-B */
|
||||
size = ARRAY_SIZE(rvu_af_dl_params);
|
||||
if (!rvu_npc_exact_has_match_table(rvu))
|
||||
size -= 1;
|
||||
|
||||
err = devlink_params_register(dl, rvu_af_dl_params, size);
|
||||
err = devlink_params_register(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
|
||||
if (err) {
|
||||
dev_err(rvu->dev,
|
||||
"devlink params register failed with error %d", err);
|
||||
goto err_dl_health;
|
||||
}
|
||||
|
||||
/* Register exact match devlink only for CN10K-B */
|
||||
if (!rvu_npc_exact_has_match_table(rvu))
|
||||
goto done;
|
||||
|
||||
err = devlink_params_register(dl, rvu_af_dl_param_exact_match,
|
||||
ARRAY_SIZE(rvu_af_dl_param_exact_match));
|
||||
if (err) {
|
||||
dev_err(rvu->dev,
|
||||
"devlink exact match params register failed with error %d", err);
|
||||
goto err_dl_exact_match;
|
||||
}
|
||||
|
||||
done:
|
||||
devlink_register(dl);
|
||||
return 0;
|
||||
|
||||
err_dl_exact_match:
|
||||
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
|
||||
|
||||
err_dl_health:
|
||||
rvu_health_reporters_destroy(rvu);
|
||||
devlink_free(dl);
|
||||
@ -1605,8 +1618,14 @@ void rvu_unregister_dl(struct rvu *rvu)
|
||||
struct devlink *dl = rvu_dl->dl;
|
||||
|
||||
devlink_unregister(dl);
|
||||
devlink_params_unregister(dl, rvu_af_dl_params,
|
||||
ARRAY_SIZE(rvu_af_dl_params));
|
||||
|
||||
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
|
||||
|
||||
/* Unregister exact match devlink only for CN10K-B */
|
||||
if (rvu_npc_exact_has_match_table(rvu))
|
||||
devlink_params_unregister(dl, rvu_af_dl_param_exact_match,
|
||||
ARRAY_SIZE(rvu_af_dl_param_exact_match));
|
||||
|
||||
rvu_health_reporters_destroy(rvu);
|
||||
devlink_free(dl);
|
||||
}
|
||||
|
@ -3177,7 +3177,8 @@ static int mtk_open(struct net_device *dev)
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
int i, err;
|
||||
|
||||
if (mtk_uses_dsa(dev) && !eth->prog) {
|
||||
if ((mtk_uses_dsa(dev) && !eth->prog) &&
|
||||
!(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) {
|
||||
for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
|
||||
struct metadata_dst *md_dst = eth->dsa_meta[i];
|
||||
|
||||
@ -3194,7 +3195,8 @@ static int mtk_open(struct net_device *dev)
|
||||
}
|
||||
} else {
|
||||
/* Hardware special tag parsing needs to be disabled if at least
|
||||
* one MAC does not use DSA.
|
||||
* one MAC does not use DSA, or the second MAC of the MT7621 and
|
||||
* MT7623 SoCs is being used.
|
||||
*/
|
||||
u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
|
||||
val &= ~MTK_CDMP_STAG_EN;
|
||||
|
@ -519,7 +519,7 @@
|
||||
#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0)
|
||||
#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1)
|
||||
#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2)
|
||||
#define SGMII_DUPLEX_FULL BIT(4)
|
||||
#define SGMII_DUPLEX_HALF BIT(4)
|
||||
#define SGMII_IF_MODE_BIT5 BIT(5)
|
||||
#define SGMII_REMOTE_FAULT_DIS BIT(8)
|
||||
#define SGMII_CODE_SYNC_SET_VAL BIT(9)
|
||||
@ -1036,11 +1036,13 @@ struct mtk_soc_data {
|
||||
* @regmap: The register map pointing at the range used to setup
|
||||
* SGMII modes
|
||||
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
|
||||
* @interface: Currently configured interface mode
|
||||
* @pcs: Phylink PCS structure
|
||||
*/
|
||||
struct mtk_pcs {
|
||||
struct regmap *regmap;
|
||||
u32 ana_rgc3;
|
||||
phy_interface_t interface;
|
||||
struct phylink_pcs pcs;
|
||||
};
|
||||
|
||||
|
@ -615,8 +615,7 @@ mtk_foe_entry_commit_subflow(struct mtk_ppe *ppe, struct mtk_flow_entry *entry,
|
||||
u32 ib1_mask = mtk_get_ib1_pkt_type_mask(ppe->eth) | MTK_FOE_IB1_UDP;
|
||||
int type;
|
||||
|
||||
flow_info = kzalloc(offsetof(struct mtk_flow_entry, l2_data.end),
|
||||
GFP_ATOMIC);
|
||||
flow_info = kzalloc(sizeof(*flow_info), GFP_ATOMIC);
|
||||
if (!flow_info)
|
||||
return;
|
||||
|
||||
|
@ -279,7 +279,6 @@ struct mtk_flow_entry {
|
||||
struct {
|
||||
struct mtk_flow_entry *base_flow;
|
||||
struct hlist_node list;
|
||||
struct {} end;
|
||||
} l2_data;
|
||||
};
|
||||
struct rhash_head node;
|
||||
|
@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
int advertise, link_timer;
|
||||
bool changed, use_an;
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_2500BASEX)
|
||||
rgc3 = RG_PHY_SPEED_3_125G;
|
||||
else
|
||||
rgc3 = 0;
|
||||
|
||||
advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
|
||||
advertising);
|
||||
if (advertise < 0)
|
||||
@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
bmcr = 0;
|
||||
}
|
||||
|
||||
/* Configure the underlying interface speed */
|
||||
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
|
||||
RG_PHY_SPEED_3_125G, rgc3);
|
||||
if (mpcs->interface != interface) {
|
||||
/* PHYA power down */
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
|
||||
SGMII_PHYA_PWD, SGMII_PHYA_PWD);
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_2500BASEX)
|
||||
rgc3 = RG_PHY_SPEED_3_125G;
|
||||
else
|
||||
rgc3 = 0;
|
||||
|
||||
/* Configure the underlying interface speed */
|
||||
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
|
||||
RG_PHY_SPEED_3_125G, rgc3);
|
||||
|
||||
mpcs->interface = interface;
|
||||
}
|
||||
|
||||
/* Update the advertisement, noting whether it has changed */
|
||||
regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
|
||||
@ -108,9 +116,17 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
|
||||
SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
|
||||
|
||||
/* Release PHYA power down state */
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
|
||||
SGMII_PHYA_PWD, 0);
|
||||
/* Release PHYA power down state
|
||||
* Only removing bit SGMII_PHYA_PWD isn't enough.
|
||||
* There are cases when the SGMII_PHYA_PWD register contains 0x9 which
|
||||
* prevents SGMII from working. The SGMII still shows link but no traffic
|
||||
* can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was
|
||||
* taken from a good working state of the SGMII interface.
|
||||
* Unknown how much the QPHY needs but it is racy without a sleep.
|
||||
* Tested on mt7622 & mt7986.
|
||||
*/
|
||||
usleep_range(50, 100);
|
||||
regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
|
||||
|
||||
return changed;
|
||||
}
|
||||
@ -138,11 +154,11 @@ static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
|
||||
else
|
||||
sgm_mode = SGMII_SPEED_1000;
|
||||
|
||||
if (duplex == DUPLEX_FULL)
|
||||
sgm_mode |= SGMII_DUPLEX_FULL;
|
||||
if (duplex != DUPLEX_FULL)
|
||||
sgm_mode |= SGMII_DUPLEX_HALF;
|
||||
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
|
||||
SGMII_DUPLEX_FULL | SGMII_SPEED_MASK,
|
||||
SGMII_DUPLEX_HALF | SGMII_SPEED_MASK,
|
||||
sgm_mode);
|
||||
}
|
||||
}
|
||||
@ -171,6 +187,8 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
|
||||
return PTR_ERR(ss->pcs[i].regmap);
|
||||
|
||||
ss->pcs[i].pcs.ops = &mtk_pcs_ops;
|
||||
ss->pcs[i].pcs.poll = true;
|
||||
ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -608,12 +608,12 @@ allocate_new:
|
||||
lan966x_fdma_rx_reload(rx);
|
||||
}
|
||||
|
||||
if (counter < weight && napi_complete_done(napi, counter))
|
||||
lan_wr(0xff, lan966x, FDMA_INTR_DB_ENA);
|
||||
|
||||
if (redirect)
|
||||
xdp_do_flush();
|
||||
|
||||
if (counter < weight && napi_complete_done(napi, counter))
|
||||
lan_wr(0xff, lan966x, FDMA_INTR_DB_ENA);
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
|
@ -460,6 +460,7 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
|
||||
sizeof(struct nfp_tun_neigh_v4);
|
||||
unsigned long cookie = (unsigned long)neigh;
|
||||
struct nfp_flower_priv *priv = app->priv;
|
||||
struct nfp_tun_neigh_lag lag_info;
|
||||
struct nfp_neigh_entry *nn_entry;
|
||||
u32 port_id;
|
||||
u8 mtype;
|
||||
@ -468,6 +469,11 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
|
||||
if (!port_id)
|
||||
return;
|
||||
|
||||
if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT) {
|
||||
memset(&lag_info, 0, sizeof(struct nfp_tun_neigh_lag));
|
||||
nfp_flower_lag_get_info_from_netdev(app, netdev, &lag_info);
|
||||
}
|
||||
|
||||
spin_lock_bh(&priv->predt_lock);
|
||||
nn_entry = rhashtable_lookup_fast(&priv->neigh_table, &cookie,
|
||||
neigh_table_params);
|
||||
@ -515,7 +521,7 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
|
||||
neigh_ha_snapshot(common->dst_addr, neigh, netdev);
|
||||
|
||||
if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT)
|
||||
nfp_flower_lag_get_info_from_netdev(app, netdev, lag);
|
||||
memcpy(lag, &lag_info, sizeof(struct nfp_tun_neigh_lag));
|
||||
common->port_id = cpu_to_be32(port_id);
|
||||
|
||||
if (rhashtable_insert_fast(&priv->neigh_table,
|
||||
|
@ -1438,6 +1438,10 @@ int qede_poll(struct napi_struct *napi, int budget)
|
||||
rx_work_done = (likely(fp->type & QEDE_FASTPATH_RX) &&
|
||||
qede_has_rx_work(fp->rxq)) ?
|
||||
qede_rx_int(fp, budget) : 0;
|
||||
|
||||
if (fp->xdp_xmit & QEDE_XDP_REDIRECT)
|
||||
xdp_do_flush();
|
||||
|
||||
/* Handle case where we are called by netpoll with a budget of 0 */
|
||||
if (rx_work_done < budget || !budget) {
|
||||
if (!qede_poll_is_more_work(fp)) {
|
||||
@ -1457,9 +1461,6 @@ int qede_poll(struct napi_struct *napi, int budget)
|
||||
qede_update_tx_producer(fp->xdp_tx);
|
||||
}
|
||||
|
||||
if (fp->xdp_xmit & QEDE_XDP_REDIRECT)
|
||||
xdp_do_flush_map();
|
||||
|
||||
return rx_work_done;
|
||||
}
|
||||
|
||||
|
@ -1003,8 +1003,11 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
|
||||
/* Determine netdevice features */
|
||||
net_dev->features |= (efx->type->offload_features | NETIF_F_SG |
|
||||
NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_RXALL);
|
||||
if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
|
||||
if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM)) {
|
||||
net_dev->features |= NETIF_F_TSO6;
|
||||
if (efx_has_cap(efx, TX_TSO_V2_ENCAP))
|
||||
net_dev->hw_enc_features |= NETIF_F_TSO6;
|
||||
}
|
||||
/* Check whether device supports TSO */
|
||||
if (!efx->type->tso_versions || !efx->type->tso_versions(efx))
|
||||
net_dev->features &= ~NETIF_F_ALL_TSO;
|
||||
|
@ -560,6 +560,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
|
||||
plat_dat->has_gmac4 = 1;
|
||||
plat_dat->pmt = 1;
|
||||
plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
|
||||
if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
|
||||
plat_dat->rx_clk_runs_in_lpi = 1;
|
||||
|
||||
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
|
||||
if (ret)
|
||||
|
@ -1080,7 +1080,8 @@ static void stmmac_mac_link_up(struct phylink_config *config,
|
||||
|
||||
stmmac_mac_set(priv, priv->ioaddr, true);
|
||||
if (phy && priv->dma_cap.eee) {
|
||||
priv->eee_active = phy_init_eee(phy, 1) >= 0;
|
||||
priv->eee_active =
|
||||
phy_init_eee(phy, !priv->plat->rx_clk_runs_in_lpi) >= 0;
|
||||
priv->eee_enabled = stmmac_eee_init(priv);
|
||||
priv->tx_lpi_enabled = priv->eee_enabled;
|
||||
stmmac_set_eee_pls(priv, priv->hw, true);
|
||||
|
@ -987,9 +987,6 @@ static void netvsc_copy_to_send_buf(struct netvsc_device *net_device,
|
||||
void netvsc_dma_unmap(struct hv_device *hv_dev,
|
||||
struct hv_netvsc_packet *packet)
|
||||
{
|
||||
u32 page_count = packet->cp_partial ?
|
||||
packet->page_buf_cnt - packet->rmsg_pgcnt :
|
||||
packet->page_buf_cnt;
|
||||
int i;
|
||||
|
||||
if (!hv_is_isolation_supported())
|
||||
@ -998,7 +995,7 @@ void netvsc_dma_unmap(struct hv_device *hv_dev,
|
||||
if (!packet->dma_range)
|
||||
return;
|
||||
|
||||
for (i = 0; i < page_count; i++)
|
||||
for (i = 0; i < packet->page_buf_cnt; i++)
|
||||
dma_unmap_single(&hv_dev->device, packet->dma_range[i].dma,
|
||||
packet->dma_range[i].mapping_size,
|
||||
DMA_TO_DEVICE);
|
||||
@ -1028,9 +1025,7 @@ static int netvsc_dma_map(struct hv_device *hv_dev,
|
||||
struct hv_netvsc_packet *packet,
|
||||
struct hv_page_buffer *pb)
|
||||
{
|
||||
u32 page_count = packet->cp_partial ?
|
||||
packet->page_buf_cnt - packet->rmsg_pgcnt :
|
||||
packet->page_buf_cnt;
|
||||
u32 page_count = packet->page_buf_cnt;
|
||||
dma_addr_t dma;
|
||||
int i;
|
||||
|
||||
|
@ -233,7 +233,8 @@ static int dp83822_config_intr(struct phy_device *phydev)
|
||||
DP83822_ENERGY_DET_INT_EN |
|
||||
DP83822_LINK_QUAL_INT_EN);
|
||||
|
||||
if (!dp83822->fx_enabled)
|
||||
/* Private data pointer is NULL on DP83825/26 */
|
||||
if (!dp83822 || !dp83822->fx_enabled)
|
||||
misr_status |= DP83822_ANEG_COMPLETE_INT_EN |
|
||||
DP83822_DUP_MODE_CHANGE_INT_EN |
|
||||
DP83822_SPEED_CHANGED_INT_EN;
|
||||
@ -253,7 +254,8 @@ static int dp83822_config_intr(struct phy_device *phydev)
|
||||
DP83822_PAGE_RX_INT_EN |
|
||||
DP83822_EEE_ERROR_CHANGE_INT_EN);
|
||||
|
||||
if (!dp83822->fx_enabled)
|
||||
/* Private data pointer is NULL on DP83825/26 */
|
||||
if (!dp83822 || !dp83822->fx_enabled)
|
||||
misr_status |= DP83822_ANEG_ERR_INT_EN |
|
||||
DP83822_WOL_PKT_INT_EN;
|
||||
|
||||
|
@ -271,6 +271,8 @@ static struct phy_driver meson_gxl_phy[] = {
|
||||
.handle_interrupt = meson_gxl_handle_interrupt,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
.read_mmd = genphy_read_mmd_unsupported,
|
||||
.write_mmd = genphy_write_mmd_unsupported,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1517,7 +1517,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
|
||||
* another mac interface, so we should create a device link between
|
||||
* phy dev and mac dev.
|
||||
*/
|
||||
if (phydev->mdio.bus->parent && dev->dev.parent != phydev->mdio.bus->parent)
|
||||
if (dev && phydev->mdio.bus->parent && dev->dev.parent != phydev->mdio.bus->parent)
|
||||
phydev->devlink = device_link_add(dev->dev.parent, &phydev->mdio.dev,
|
||||
DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
|
||||
|
||||
|
@ -1677,13 +1677,13 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
|
||||
|
||||
received = virtnet_receive(rq, budget, &xdp_xmit);
|
||||
|
||||
if (xdp_xmit & VIRTIO_XDP_REDIR)
|
||||
xdp_do_flush();
|
||||
|
||||
/* Out of packets? */
|
||||
if (received < budget)
|
||||
virtqueue_napi_complete(napi, rq->vq, received);
|
||||
|
||||
if (xdp_xmit & VIRTIO_XDP_REDIR)
|
||||
xdp_do_flush();
|
||||
|
||||
if (xdp_xmit & VIRTIO_XDP_TX) {
|
||||
sq = virtnet_xdp_get_sq(vi);
|
||||
if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) {
|
||||
@ -2158,8 +2158,8 @@ static int virtnet_close(struct net_device *dev)
|
||||
cancel_delayed_work_sync(&vi->refill);
|
||||
|
||||
for (i = 0; i < vi->max_queue_pairs; i++) {
|
||||
xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
|
||||
napi_disable(&vi->rq[i].napi);
|
||||
xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
|
||||
virtnet_napi_tx_disable(&vi->sq[i].napi);
|
||||
}
|
||||
|
||||
|
@ -152,6 +152,15 @@ static irqreturn_t t7xx_dpmaif_isr_handler(int irq, void *data)
|
||||
}
|
||||
|
||||
t7xx_pcie_mac_clear_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
static irqreturn_t t7xx_dpmaif_isr_thread(int irq, void *data)
|
||||
{
|
||||
struct dpmaif_isr_para *isr_para = data;
|
||||
struct dpmaif_ctrl *dpmaif_ctrl = isr_para->dpmaif_ctrl;
|
||||
|
||||
t7xx_dpmaif_irq_cb(isr_para);
|
||||
t7xx_pcie_mac_set_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
|
||||
return IRQ_HANDLED;
|
||||
@ -188,7 +197,7 @@ static void t7xx_dpmaif_register_pcie_irq(struct dpmaif_ctrl *dpmaif_ctrl)
|
||||
t7xx_pcie_mac_clear_int(t7xx_dev, int_type);
|
||||
|
||||
t7xx_dev->intr_handler[int_type] = t7xx_dpmaif_isr_handler;
|
||||
t7xx_dev->intr_thread[int_type] = NULL;
|
||||
t7xx_dev->intr_thread[int_type] = t7xx_dpmaif_isr_thread;
|
||||
t7xx_dev->callback_param[int_type] = isr_para;
|
||||
|
||||
t7xx_pcie_mac_clear_int_status(t7xx_dev, int_type);
|
||||
|
@ -840,14 +840,13 @@ int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
|
||||
|
||||
if (!rxq->que_started) {
|
||||
atomic_set(&rxq->rx_processing, 0);
|
||||
pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
|
||||
dev_err(rxq->dpmaif_ctrl->dev, "Work RXQ: %d has not been started\n", rxq->index);
|
||||
return work_done;
|
||||
}
|
||||
|
||||
if (!rxq->sleep_lock_pending) {
|
||||
pm_runtime_get_noresume(rxq->dpmaif_ctrl->dev);
|
||||
if (!rxq->sleep_lock_pending)
|
||||
t7xx_pci_disable_sleep(t7xx_dev);
|
||||
}
|
||||
|
||||
ret = try_wait_for_completion(&t7xx_dev->sleep_lock_acquire);
|
||||
if (!ret) {
|
||||
@ -876,22 +875,22 @@ int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
|
||||
napi_complete_done(napi, work_done);
|
||||
t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
|
||||
t7xx_dpmaif_dlq_unmask_rx_done(&rxq->dpmaif_ctrl->hw_info, rxq->index);
|
||||
t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
|
||||
pm_runtime_mark_last_busy(rxq->dpmaif_ctrl->dev);
|
||||
pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
|
||||
atomic_set(&rxq->rx_processing, 0);
|
||||
} else {
|
||||
t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
|
||||
}
|
||||
|
||||
t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
|
||||
pm_runtime_mark_last_busy(rxq->dpmaif_ctrl->dev);
|
||||
pm_runtime_put_noidle(rxq->dpmaif_ctrl->dev);
|
||||
atomic_set(&rxq->rx_processing, 0);
|
||||
|
||||
return work_done;
|
||||
}
|
||||
|
||||
void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int que_mask)
|
||||
{
|
||||
struct dpmaif_rx_queue *rxq;
|
||||
int qno;
|
||||
struct dpmaif_ctrl *ctrl;
|
||||
int qno, ret;
|
||||
|
||||
qno = ffs(que_mask) - 1;
|
||||
if (qno < 0 || qno > DPMAIF_RXQ_NUM - 1) {
|
||||
@ -900,6 +899,18 @@ void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int
|
||||
}
|
||||
|
||||
rxq = &dpmaif_ctrl->rxq[qno];
|
||||
ctrl = rxq->dpmaif_ctrl;
|
||||
/* We need to make sure that the modem has been resumed before
|
||||
* calling napi. This can't be done inside the polling function
|
||||
* as we could be blocked waiting for device to be resumed,
|
||||
* which can't be done from softirq context the poll function
|
||||
* is running in.
|
||||
*/
|
||||
ret = pm_runtime_resume_and_get(ctrl->dev);
|
||||
if (ret < 0 && ret != -EACCES) {
|
||||
dev_err(ctrl->dev, "Failed to resume device: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
napi_schedule(&rxq->napi);
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/netdev_features.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/wwan.h>
|
||||
@ -45,12 +46,25 @@
|
||||
|
||||
static void t7xx_ccmni_enable_napi(struct t7xx_ccmni_ctrl *ctlb)
|
||||
{
|
||||
int i;
|
||||
struct dpmaif_ctrl *ctrl;
|
||||
int i, ret;
|
||||
|
||||
ctrl = ctlb->hif_ctrl;
|
||||
|
||||
if (ctlb->is_napi_en)
|
||||
return;
|
||||
|
||||
for (i = 0; i < RXQ_NUM; i++) {
|
||||
/* The usage count has to be bumped every time before calling
|
||||
* napi_schedule. It will be decresed in the poll routine,
|
||||
* right after napi_complete_done is called.
|
||||
*/
|
||||
ret = pm_runtime_resume_and_get(ctrl->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(ctrl->dev, "Failed to resume device: %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
napi_enable(ctlb->napi[i]);
|
||||
napi_schedule(ctlb->napi[i]);
|
||||
}
|
||||
|
@ -121,6 +121,8 @@ void t7xx_pci_pm_init_late(struct t7xx_pci_dev *t7xx_dev)
|
||||
iowrite32(T7XX_L1_BIT(0), IREG_BASE(t7xx_dev) + ENABLE_ASPM_LOWPWR);
|
||||
atomic_set(&t7xx_dev->md_pm_state, MTK_PM_RESUMED);
|
||||
|
||||
pm_runtime_mark_last_busy(&t7xx_dev->pdev->dev);
|
||||
pm_runtime_allow(&t7xx_dev->pdev->dev);
|
||||
pm_runtime_put_noidle(&t7xx_dev->pdev->dev);
|
||||
}
|
||||
|
||||
|
@ -252,6 +252,7 @@ struct plat_stmmacenet_data {
|
||||
int rss_en;
|
||||
int mac_port_sel_speed;
|
||||
bool en_tx_lpi_clockgating;
|
||||
bool rx_clk_runs_in_lpi;
|
||||
int has_xgmac;
|
||||
bool vlan_fail_q_en;
|
||||
u8 vlan_fail_q;
|
||||
|
@ -38,4 +38,16 @@
|
||||
*/
|
||||
#define find_closest_descending(x, a, as) __find_closest(x, a, as, >=)
|
||||
|
||||
/**
|
||||
* is_insidevar - check if the @ptr points inside the @var memory range.
|
||||
* @ptr: the pointer to a memory address.
|
||||
* @var: the variable which address and size identify the memory range.
|
||||
*
|
||||
* Evaluates to true if the address in @ptr lies within the memory
|
||||
* range allocated to @var.
|
||||
*/
|
||||
#define is_insidevar(ptr, var) \
|
||||
((uintptr_t)(ptr) >= (uintptr_t)(var) && \
|
||||
(uintptr_t)(ptr) < (uintptr_t)(var) + sizeof(var))
|
||||
|
||||
#endif
|
||||
|
@ -51,7 +51,6 @@ BTF_SET_END(bpf_lsm_current_hooks)
|
||||
*/
|
||||
BTF_SET_START(bpf_lsm_locked_sockopt_hooks)
|
||||
#ifdef CONFIG_SECURITY_NETWORK
|
||||
BTF_ID(func, bpf_lsm_socket_sock_rcv_skb)
|
||||
BTF_ID(func, bpf_lsm_sock_graft)
|
||||
BTF_ID(func, bpf_lsm_inet_csk_clone)
|
||||
BTF_ID(func, bpf_lsm_inet_conn_established)
|
||||
|
@ -7782,9 +7782,9 @@ int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 add_c
|
||||
|
||||
sort(tab->dtors, tab->cnt, sizeof(tab->dtors[0]), btf_id_cmp_func, NULL);
|
||||
|
||||
return 0;
|
||||
end:
|
||||
btf_free_dtor_kfunc_tab(btf);
|
||||
if (ret)
|
||||
btf_free_dtor_kfunc_tab(btf);
|
||||
btf_put(btf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ static int bpf_mem_cache_idx(size_t size)
|
||||
if (size <= 192)
|
||||
return size_index[(size - 1) / 8] - 1;
|
||||
|
||||
return fls(size - 1) - 1;
|
||||
return fls(size - 1) - 2;
|
||||
}
|
||||
|
||||
#define NUM_CACHES 11
|
||||
|
@ -3243,13 +3243,24 @@ static bool __is_pointer_value(bool allow_ptr_leaks,
|
||||
return reg->type != SCALAR_VALUE;
|
||||
}
|
||||
|
||||
/* Copy src state preserving dst->parent and dst->live fields */
|
||||
static void copy_register_state(struct bpf_reg_state *dst, const struct bpf_reg_state *src)
|
||||
{
|
||||
struct bpf_reg_state *parent = dst->parent;
|
||||
enum bpf_reg_liveness live = dst->live;
|
||||
|
||||
*dst = *src;
|
||||
dst->parent = parent;
|
||||
dst->live = live;
|
||||
}
|
||||
|
||||
static void save_register_state(struct bpf_func_state *state,
|
||||
int spi, struct bpf_reg_state *reg,
|
||||
int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
state->stack[spi].spilled_ptr = *reg;
|
||||
copy_register_state(&state->stack[spi].spilled_ptr, reg);
|
||||
if (size == BPF_REG_SIZE)
|
||||
state->stack[spi].spilled_ptr.live |= REG_LIVE_WRITTEN;
|
||||
|
||||
@ -3577,7 +3588,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
||||
*/
|
||||
s32 subreg_def = state->regs[dst_regno].subreg_def;
|
||||
|
||||
state->regs[dst_regno] = *reg;
|
||||
copy_register_state(&state->regs[dst_regno], reg);
|
||||
state->regs[dst_regno].subreg_def = subreg_def;
|
||||
} else {
|
||||
for (i = 0; i < size; i++) {
|
||||
@ -3598,7 +3609,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
||||
|
||||
if (dst_regno >= 0) {
|
||||
/* restore register state from stack */
|
||||
state->regs[dst_regno] = *reg;
|
||||
copy_register_state(&state->regs[dst_regno], reg);
|
||||
/* mark reg as written since spilled pointer state likely
|
||||
* has its liveness marks cleared by is_state_visited()
|
||||
* which resets stack/reg liveness for state transitions
|
||||
@ -9592,7 +9603,7 @@ do_sim:
|
||||
*/
|
||||
if (!ptr_is_dst_reg) {
|
||||
tmp = *dst_reg;
|
||||
*dst_reg = *ptr_reg;
|
||||
copy_register_state(dst_reg, ptr_reg);
|
||||
}
|
||||
ret = sanitize_speculative_path(env, NULL, env->insn_idx + 1,
|
||||
env->insn_idx);
|
||||
@ -10845,7 +10856,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
* to propagate min/max range.
|
||||
*/
|
||||
src_reg->id = ++env->id_gen;
|
||||
*dst_reg = *src_reg;
|
||||
copy_register_state(dst_reg, src_reg);
|
||||
dst_reg->live |= REG_LIVE_WRITTEN;
|
||||
dst_reg->subreg_def = DEF_NOT_SUBREG;
|
||||
} else {
|
||||
@ -10856,7 +10867,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
insn->src_reg);
|
||||
return -EACCES;
|
||||
} else if (src_reg->type == SCALAR_VALUE) {
|
||||
*dst_reg = *src_reg;
|
||||
copy_register_state(dst_reg, src_reg);
|
||||
/* Make sure ID is cleared otherwise
|
||||
* dst_reg min/max could be incorrectly
|
||||
* propagated into src_reg by find_equal_scalars()
|
||||
@ -11655,7 +11666,7 @@ static void find_equal_scalars(struct bpf_verifier_state *vstate,
|
||||
|
||||
bpf_for_each_reg_in_vstate(vstate, state, reg, ({
|
||||
if (reg->type == SCALAR_VALUE && reg->id == known_reg->id)
|
||||
*reg = *known_reg;
|
||||
copy_register_state(reg, known_reg);
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -833,6 +833,7 @@ static void do_bpf_send_signal(struct irq_work *entry)
|
||||
|
||||
work = container_of(entry, struct send_signal_irq_work, irq_work);
|
||||
group_send_sig_info(work->sig, SEND_SIG_PRIV, work->task, work->type);
|
||||
put_task_struct(work->task);
|
||||
}
|
||||
|
||||
static int bpf_send_signal_common(u32 sig, enum pid_type type)
|
||||
@ -867,7 +868,7 @@ static int bpf_send_signal_common(u32 sig, enum pid_type type)
|
||||
* to the irq_work. The current task may change when queued
|
||||
* irq works get executed.
|
||||
*/
|
||||
work->task = current;
|
||||
work->task = get_task_struct(current);
|
||||
work->sig = sig;
|
||||
work->type = type;
|
||||
irq_work_queue(&work->irq_work);
|
||||
|
@ -871,6 +871,7 @@ static unsigned int ip_sabotage_in(void *priv,
|
||||
if (nf_bridge && !nf_bridge->in_prerouting &&
|
||||
!netif_is_l3_master(skb->dev) &&
|
||||
!netif_is_l3_slave(skb->dev)) {
|
||||
nf_bridge_info_free(skb);
|
||||
state->okfn(state->net, state->sk, skb);
|
||||
return NF_STOLEN;
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ struct isotp_sock {
|
||||
canid_t rxid;
|
||||
ktime_t tx_gap;
|
||||
ktime_t lastrxcf_tstamp;
|
||||
struct hrtimer rxtimer, txtimer;
|
||||
struct hrtimer rxtimer, txtimer, txfrtimer;
|
||||
struct can_isotp_options opt;
|
||||
struct can_isotp_fc_options rxfc, txfc;
|
||||
struct can_isotp_ll_options ll;
|
||||
@ -871,7 +871,7 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
|
||||
}
|
||||
|
||||
/* start timer to send next consecutive frame with correct delay */
|
||||
hrtimer_start(&so->txtimer, so->tx_gap, HRTIMER_MODE_REL_SOFT);
|
||||
hrtimer_start(&so->txfrtimer, so->tx_gap, HRTIMER_MODE_REL_SOFT);
|
||||
}
|
||||
|
||||
static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
|
||||
@ -879,49 +879,39 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
|
||||
struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
|
||||
txtimer);
|
||||
struct sock *sk = &so->sk;
|
||||
enum hrtimer_restart restart = HRTIMER_NORESTART;
|
||||
|
||||
switch (so->tx.state) {
|
||||
case ISOTP_SENDING:
|
||||
/* don't handle timeouts in IDLE state */
|
||||
if (so->tx.state == ISOTP_IDLE)
|
||||
return HRTIMER_NORESTART;
|
||||
|
||||
/* cfecho should be consumed by isotp_rcv_echo() here */
|
||||
if (!so->cfecho) {
|
||||
/* start timeout for unlikely lost echo skb */
|
||||
hrtimer_set_expires(&so->txtimer,
|
||||
ktime_add(ktime_get(),
|
||||
ktime_set(ISOTP_ECHO_TIMEOUT, 0)));
|
||||
restart = HRTIMER_RESTART;
|
||||
/* we did not get any flow control or echo frame in time */
|
||||
|
||||
/* push out the next consecutive frame */
|
||||
isotp_send_cframe(so);
|
||||
break;
|
||||
}
|
||||
/* report 'communication error on send' */
|
||||
sk->sk_err = ECOMM;
|
||||
if (!sock_flag(sk, SOCK_DEAD))
|
||||
sk_error_report(sk);
|
||||
|
||||
/* cfecho has not been cleared in isotp_rcv_echo() */
|
||||
pr_notice_once("can-isotp: cfecho %08X timeout\n", so->cfecho);
|
||||
fallthrough;
|
||||
/* reset tx state */
|
||||
so->tx.state = ISOTP_IDLE;
|
||||
wake_up_interruptible(&so->wait);
|
||||
|
||||
case ISOTP_WAIT_FC:
|
||||
case ISOTP_WAIT_FIRST_FC:
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
/* we did not get any flow control frame in time */
|
||||
static enum hrtimer_restart isotp_txfr_timer_handler(struct hrtimer *hrtimer)
|
||||
{
|
||||
struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
|
||||
txfrtimer);
|
||||
|
||||
/* report 'communication error on send' */
|
||||
sk->sk_err = ECOMM;
|
||||
if (!sock_flag(sk, SOCK_DEAD))
|
||||
sk_error_report(sk);
|
||||
/* start echo timeout handling and cover below protocol error */
|
||||
hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
|
||||
/* reset tx state */
|
||||
so->tx.state = ISOTP_IDLE;
|
||||
wake_up_interruptible(&so->wait);
|
||||
break;
|
||||
/* cfecho should be consumed by isotp_rcv_echo() here */
|
||||
if (so->tx.state == ISOTP_SENDING && !so->cfecho)
|
||||
isotp_send_cframe(so);
|
||||
|
||||
default:
|
||||
WARN_ONCE(1, "can-isotp: tx timer state %08X cfecho %08X\n",
|
||||
so->tx.state, so->cfecho);
|
||||
}
|
||||
|
||||
return restart;
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||
@ -1162,6 +1152,10 @@ static int isotp_release(struct socket *sock)
|
||||
/* wait for complete transmission of current pdu */
|
||||
wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
|
||||
|
||||
/* force state machines to be idle also when a signal occurred */
|
||||
so->tx.state = ISOTP_IDLE;
|
||||
so->rx.state = ISOTP_IDLE;
|
||||
|
||||
spin_lock(&isotp_notifier_lock);
|
||||
while (isotp_busy_notifier == so) {
|
||||
spin_unlock(&isotp_notifier_lock);
|
||||
@ -1194,6 +1188,7 @@ static int isotp_release(struct socket *sock)
|
||||
}
|
||||
}
|
||||
|
||||
hrtimer_cancel(&so->txfrtimer);
|
||||
hrtimer_cancel(&so->txtimer);
|
||||
hrtimer_cancel(&so->rxtimer);
|
||||
|
||||
@ -1597,6 +1592,8 @@ static int isotp_init(struct sock *sk)
|
||||
so->rxtimer.function = isotp_rx_timer_handler;
|
||||
hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
|
||||
so->txtimer.function = isotp_tx_timer_handler;
|
||||
hrtimer_init(&so->txfrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
|
||||
so->txfrtimer.function = isotp_txfr_timer_handler;
|
||||
|
||||
init_waitqueue_head(&so->wait);
|
||||
spin_lock_init(&so->rx_lock);
|
||||
|
@ -1092,10 +1092,6 @@ static bool j1939_session_deactivate(struct j1939_session *session)
|
||||
bool active;
|
||||
|
||||
j1939_session_list_lock(priv);
|
||||
/* This function should be called with a session ref-count of at
|
||||
* least 2.
|
||||
*/
|
||||
WARN_ON_ONCE(kref_read(&session->kref) < 2);
|
||||
active = j1939_session_deactivate_locked(session);
|
||||
j1939_session_list_unlock(priv);
|
||||
|
||||
|
@ -132,8 +132,8 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
|
||||
return;
|
||||
|
||||
/* make sure to not pass oversized frames to the socket */
|
||||
if ((can_is_canfd_skb(oskb) && !ro->fd_frames && !ro->xl_frames) ||
|
||||
(can_is_canxl_skb(oskb) && !ro->xl_frames))
|
||||
if ((!ro->fd_frames && can_is_canfd_skb(oskb)) ||
|
||||
(!ro->xl_frames && can_is_canxl_skb(oskb)))
|
||||
return;
|
||||
|
||||
/* eliminate multiple filter matches for the same skb */
|
||||
@ -670,6 +670,11 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
|
||||
if (copy_from_sockptr(&ro->fd_frames, optval, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
/* Enabling CAN XL includes CAN FD */
|
||||
if (ro->xl_frames && !ro->fd_frames) {
|
||||
ro->fd_frames = ro->xl_frames;
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAN_RAW_XL_FRAMES:
|
||||
@ -679,6 +684,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
|
||||
if (copy_from_sockptr(&ro->xl_frames, optval, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
/* Enabling CAN XL includes CAN FD */
|
||||
if (ro->xl_frames)
|
||||
ro->fd_frames = ro->xl_frames;
|
||||
break;
|
||||
|
||||
case CAN_RAW_JOIN_FILTERS:
|
||||
@ -786,6 +794,25 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool raw_bad_txframe(struct raw_sock *ro, struct sk_buff *skb, int mtu)
|
||||
{
|
||||
/* Classical CAN -> no checks for flags and device capabilities */
|
||||
if (can_is_can_skb(skb))
|
||||
return false;
|
||||
|
||||
/* CAN FD -> needs to be enabled and a CAN FD or CAN XL device */
|
||||
if (ro->fd_frames && can_is_canfd_skb(skb) &&
|
||||
(mtu == CANFD_MTU || can_is_canxl_dev_mtu(mtu)))
|
||||
return false;
|
||||
|
||||
/* CAN XL -> needs to be enabled and a CAN XL device */
|
||||
if (ro->xl_frames && can_is_canxl_skb(skb) &&
|
||||
can_is_canxl_dev_mtu(mtu))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
@ -833,20 +860,8 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||
goto free_skb;
|
||||
|
||||
err = -EINVAL;
|
||||
if (ro->xl_frames && can_is_canxl_dev_mtu(dev->mtu)) {
|
||||
/* CAN XL, CAN FD and Classical CAN */
|
||||
if (!can_is_canxl_skb(skb) && !can_is_canfd_skb(skb) &&
|
||||
!can_is_can_skb(skb))
|
||||
goto free_skb;
|
||||
} else if (ro->fd_frames && dev->mtu == CANFD_MTU) {
|
||||
/* CAN FD and Classical CAN */
|
||||
if (!can_is_canfd_skb(skb) && !can_is_can_skb(skb))
|
||||
goto free_skb;
|
||||
} else {
|
||||
/* Classical CAN */
|
||||
if (!can_is_can_skb(skb))
|
||||
goto free_skb;
|
||||
}
|
||||
if (raw_bad_txframe(ro, skb, dev->mtu))
|
||||
goto free_skb;
|
||||
|
||||
sockcm_init(&sockc, sk);
|
||||
if (msg->msg_controllen) {
|
||||
|
@ -162,6 +162,15 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
|
||||
struct sk_buff *lp;
|
||||
int segs;
|
||||
|
||||
/* Do not splice page pool based packets w/ non-page pool
|
||||
* packets. This can result in reference count issues as page
|
||||
* pool pages will not decrement the reference count and will
|
||||
* instead be immediately returned to the pool or have frag
|
||||
* count decremented.
|
||||
*/
|
||||
if (p->pp_recycle != skb->pp_recycle)
|
||||
return -ETOOMANYREFS;
|
||||
|
||||
/* pairs with WRITE_ONCE() in netif_set_gro_max_size() */
|
||||
gro_max_size = READ_ONCE(p->dev->gro_max_size);
|
||||
|
||||
|
@ -4100,7 +4100,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
|
||||
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
|
||||
do {
|
||||
while (list_skb) {
|
||||
nskb = list_skb;
|
||||
list_skb = list_skb->next;
|
||||
|
||||
@ -4146,8 +4146,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
|
||||
if (skb_needs_linearize(nskb, features) &&
|
||||
__skb_linearize(nskb))
|
||||
goto err_linearize;
|
||||
|
||||
} while (list_skb);
|
||||
}
|
||||
|
||||
skb->truesize = skb->truesize - delta_truesize;
|
||||
skb->data_len = skb->data_len - delta_len;
|
||||
|
@ -1569,15 +1569,16 @@ void sock_map_unhash(struct sock *sk)
|
||||
psock = sk_psock(sk);
|
||||
if (unlikely(!psock)) {
|
||||
rcu_read_unlock();
|
||||
if (sk->sk_prot->unhash)
|
||||
sk->sk_prot->unhash(sk);
|
||||
return;
|
||||
saved_unhash = READ_ONCE(sk->sk_prot)->unhash;
|
||||
} else {
|
||||
saved_unhash = psock->saved_unhash;
|
||||
sock_map_remove_links(sk, psock);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
saved_unhash = psock->saved_unhash;
|
||||
sock_map_remove_links(sk, psock);
|
||||
rcu_read_unlock();
|
||||
saved_unhash(sk);
|
||||
if (WARN_ON_ONCE(saved_unhash == sock_map_unhash))
|
||||
return;
|
||||
if (saved_unhash)
|
||||
saved_unhash(sk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_map_unhash);
|
||||
|
||||
@ -1590,17 +1591,18 @@ void sock_map_destroy(struct sock *sk)
|
||||
psock = sk_psock_get(sk);
|
||||
if (unlikely(!psock)) {
|
||||
rcu_read_unlock();
|
||||
if (sk->sk_prot->destroy)
|
||||
sk->sk_prot->destroy(sk);
|
||||
return;
|
||||
saved_destroy = READ_ONCE(sk->sk_prot)->destroy;
|
||||
} else {
|
||||
saved_destroy = psock->saved_destroy;
|
||||
sock_map_remove_links(sk, psock);
|
||||
rcu_read_unlock();
|
||||
sk_psock_stop(psock);
|
||||
sk_psock_put(sk, psock);
|
||||
}
|
||||
|
||||
saved_destroy = psock->saved_destroy;
|
||||
sock_map_remove_links(sk, psock);
|
||||
rcu_read_unlock();
|
||||
sk_psock_stop(psock);
|
||||
sk_psock_put(sk, psock);
|
||||
saved_destroy(sk);
|
||||
if (WARN_ON_ONCE(saved_destroy == sock_map_destroy))
|
||||
return;
|
||||
if (saved_destroy)
|
||||
saved_destroy(sk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_map_destroy);
|
||||
|
||||
@ -1615,16 +1617,21 @@ void sock_map_close(struct sock *sk, long timeout)
|
||||
if (unlikely(!psock)) {
|
||||
rcu_read_unlock();
|
||||
release_sock(sk);
|
||||
return sk->sk_prot->close(sk, timeout);
|
||||
saved_close = READ_ONCE(sk->sk_prot)->close;
|
||||
} else {
|
||||
saved_close = psock->saved_close;
|
||||
sock_map_remove_links(sk, psock);
|
||||
rcu_read_unlock();
|
||||
sk_psock_stop(psock);
|
||||
release_sock(sk);
|
||||
cancel_work_sync(&psock->work);
|
||||
sk_psock_put(sk, psock);
|
||||
}
|
||||
|
||||
saved_close = psock->saved_close;
|
||||
sock_map_remove_links(sk, psock);
|
||||
rcu_read_unlock();
|
||||
sk_psock_stop(psock);
|
||||
release_sock(sk);
|
||||
cancel_work_sync(&psock->work);
|
||||
sk_psock_put(sk, psock);
|
||||
/* Make sure we do not recurse. This is a bug.
|
||||
* Leak the socket instead of crashing on a stack overflow.
|
||||
*/
|
||||
if (WARN_ON_ONCE(saved_close == sock_map_close))
|
||||
return;
|
||||
saved_close(sk, timeout);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sock_map_close);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/util_macros.h>
|
||||
|
||||
#include <net/inet_common.h>
|
||||
#include <net/tls.h>
|
||||
@ -639,10 +640,9 @@ EXPORT_SYMBOL_GPL(tcp_bpf_update_proto);
|
||||
*/
|
||||
void tcp_bpf_clone(const struct sock *sk, struct sock *newsk)
|
||||
{
|
||||
int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4;
|
||||
struct proto *prot = newsk->sk_prot;
|
||||
|
||||
if (prot == &tcp_bpf_prots[family][TCP_BPF_BASE])
|
||||
if (is_insidevar(prot, tcp_bpf_prots))
|
||||
newsk->sk_prot = sk->sk_prot_creator;
|
||||
}
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
|
@ -3127,17 +3127,17 @@ static void add_v4_addrs(struct inet6_dev *idev)
|
||||
offset = sizeof(struct in6_addr) - 4;
|
||||
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
|
||||
|
||||
if (idev->dev->flags&IFF_POINTOPOINT) {
|
||||
if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) {
|
||||
scope = IPV6_ADDR_COMPATv4;
|
||||
plen = 96;
|
||||
pflags |= RTF_NONEXTHOP;
|
||||
} else {
|
||||
if (idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_NONE)
|
||||
return;
|
||||
|
||||
addr.s6_addr32[0] = htonl(0xfe800000);
|
||||
scope = IFA_LINK;
|
||||
plen = 64;
|
||||
} else {
|
||||
scope = IPV6_ADDR_COMPATv4;
|
||||
plen = 96;
|
||||
pflags |= RTF_NONEXTHOP;
|
||||
}
|
||||
|
||||
if (addr.s6_addr32[3]) {
|
||||
@ -3447,6 +3447,30 @@ static void addrconf_gre_config(struct net_device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void addrconf_init_auto_addrs(struct net_device *dev)
|
||||
{
|
||||
switch (dev->type) {
|
||||
#if IS_ENABLED(CONFIG_IPV6_SIT)
|
||||
case ARPHRD_SIT:
|
||||
addrconf_sit_config(dev);
|
||||
break;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE)
|
||||
case ARPHRD_IP6GRE:
|
||||
case ARPHRD_IPGRE:
|
||||
addrconf_gre_config(dev);
|
||||
break;
|
||||
#endif
|
||||
case ARPHRD_LOOPBACK:
|
||||
init_loopback(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
addrconf_dev_config(dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int fixup_permanent_addr(struct net *net,
|
||||
struct inet6_dev *idev,
|
||||
struct inet6_ifaddr *ifp)
|
||||
@ -3615,26 +3639,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
|
||||
run_pending = 1;
|
||||
}
|
||||
|
||||
switch (dev->type) {
|
||||
#if IS_ENABLED(CONFIG_IPV6_SIT)
|
||||
case ARPHRD_SIT:
|
||||
addrconf_sit_config(dev);
|
||||
break;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE)
|
||||
case ARPHRD_IP6GRE:
|
||||
case ARPHRD_IPGRE:
|
||||
addrconf_gre_config(dev);
|
||||
break;
|
||||
#endif
|
||||
case ARPHRD_LOOPBACK:
|
||||
init_loopback(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
addrconf_dev_config(dev);
|
||||
break;
|
||||
}
|
||||
addrconf_init_auto_addrs(dev);
|
||||
|
||||
if (!IS_ERR_OR_NULL(idev)) {
|
||||
if (run_pending)
|
||||
@ -6397,7 +6402,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
|
||||
|
||||
if (idev->cnf.addr_gen_mode != new_val) {
|
||||
idev->cnf.addr_gen_mode = new_val;
|
||||
addrconf_dev_config(idev->dev);
|
||||
addrconf_init_auto_addrs(idev->dev);
|
||||
}
|
||||
} else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {
|
||||
struct net_device *dev;
|
||||
@ -6408,7 +6413,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
|
||||
if (idev &&
|
||||
idev->cnf.addr_gen_mode != new_val) {
|
||||
idev->cnf.addr_gen_mode = new_val;
|
||||
addrconf_dev_config(idev->dev);
|
||||
addrconf_init_auto_addrs(idev->dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +213,6 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local,
|
||||
ret = ieee802154_parse_frame_start(skb, &hdr);
|
||||
if (ret) {
|
||||
pr_debug("got invalid frame\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -587,6 +587,11 @@ static void mctp_sk_unhash(struct sock *sk)
|
||||
del_timer_sync(&msk->key_expiry);
|
||||
}
|
||||
|
||||
static void mctp_sk_destruct(struct sock *sk)
|
||||
{
|
||||
skb_queue_purge(&sk->sk_receive_queue);
|
||||
}
|
||||
|
||||
static struct proto mctp_proto = {
|
||||
.name = "MCTP",
|
||||
.owner = THIS_MODULE,
|
||||
@ -623,6 +628,7 @@ static int mctp_pf_create(struct net *net, struct socket *sock,
|
||||
return -ENOMEM;
|
||||
|
||||
sock_init_data(sock, sk);
|
||||
sk->sk_destruct = mctp_sk_destruct;
|
||||
|
||||
rc = 0;
|
||||
if (sk->sk_prot->init)
|
||||
|
@ -142,10 +142,11 @@ static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* do_basic_checks ensures sch->length > 0, do not use before */
|
||||
#define for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count) \
|
||||
for ((offset) = (dataoff) + sizeof(struct sctphdr), (count) = 0; \
|
||||
((sch) = skb_header_pointer((skb), (offset), sizeof(_sch), &(_sch))) && \
|
||||
(sch)->length; \
|
||||
(offset) < (skb)->len && \
|
||||
((sch) = skb_header_pointer((skb), (offset), sizeof(_sch), &(_sch))); \
|
||||
(offset) += (ntohs((sch)->length) + 3) & ~3, (count)++)
|
||||
|
||||
/* Some validity checks to make sure the chunks are fine */
|
||||
|
@ -400,6 +400,11 @@ static int nr_listen(struct socket *sock, int backlog)
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
lock_sock(sk);
|
||||
if (sock->state != SS_UNCONNECTED) {
|
||||
release_sock(sk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sk->sk_state != TCP_LISTEN) {
|
||||
memset(&nr_sk(sk)->user_addr, 0, AX25_ADDR_LEN);
|
||||
sk->sk_max_ack_backlog = backlog;
|
||||
|
@ -1004,14 +1004,14 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
key = kzalloc(sizeof(*key), GFP_KERNEL);
|
||||
if (!key) {
|
||||
error = -ENOMEM;
|
||||
goto err_kfree_key;
|
||||
goto err_kfree_flow;
|
||||
}
|
||||
|
||||
ovs_match_init(&match, key, false, &mask);
|
||||
error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
|
||||
a[OVS_FLOW_ATTR_MASK], log);
|
||||
if (error)
|
||||
goto err_kfree_flow;
|
||||
goto err_kfree_key;
|
||||
|
||||
ovs_flow_mask_key(&new_flow->key, key, true, &mask);
|
||||
|
||||
@ -1019,14 +1019,14 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
|
||||
key, log);
|
||||
if (error)
|
||||
goto err_kfree_flow;
|
||||
goto err_kfree_key;
|
||||
|
||||
/* Validate actions. */
|
||||
error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS],
|
||||
&new_flow->key, &acts, log);
|
||||
if (error) {
|
||||
OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
|
||||
goto err_kfree_flow;
|
||||
goto err_kfree_key;
|
||||
}
|
||||
|
||||
reply = ovs_flow_cmd_alloc_info(acts, &new_flow->id, info, false,
|
||||
@ -1126,10 +1126,10 @@ err_unlock_ovs:
|
||||
kfree_skb(reply);
|
||||
err_kfree_acts:
|
||||
ovs_nla_free_flow_actions(acts);
|
||||
err_kfree_flow:
|
||||
ovs_flow_free(new_flow, false);
|
||||
err_kfree_key:
|
||||
kfree(key);
|
||||
err_kfree_flow:
|
||||
ovs_flow_free(new_flow, false);
|
||||
error:
|
||||
return error;
|
||||
}
|
||||
|
@ -83,7 +83,10 @@ static struct qrtr_node *node_get(unsigned int node_id)
|
||||
|
||||
node->id = node_id;
|
||||
|
||||
radix_tree_insert(&nodes, node_id, node);
|
||||
if (radix_tree_insert(&nodes, node_id, node)) {
|
||||
kfree(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -488,6 +488,12 @@ static int rose_listen(struct socket *sock, int backlog)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
lock_sock(sk);
|
||||
if (sock->state != SS_UNCONNECTED) {
|
||||
release_sock(sk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sk->sk_state != TCP_LISTEN) {
|
||||
struct rose_sock *rose = rose_sk(sk);
|
||||
|
||||
@ -497,8 +503,10 @@ static int rose_listen(struct socket *sock, int backlog)
|
||||
memset(rose->dest_digis, 0, AX25_ADDR_LEN * ROSE_MAX_DIGIS);
|
||||
sk->sk_max_ack_backlog = backlog;
|
||||
sk->sk_state = TCP_LISTEN;
|
||||
release_sock(sk);
|
||||
return 0;
|
||||
}
|
||||
release_sock(sk);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -431,7 +431,10 @@ static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
|
||||
while (cl->cmode == HTB_MAY_BORROW && p && mask) {
|
||||
m = mask;
|
||||
while (m) {
|
||||
int prio = ffz(~m);
|
||||
unsigned int prio = ffz(~m);
|
||||
|
||||
if (WARN_ON_ONCE(prio > ARRAY_SIZE(p->inner.clprio)))
|
||||
break;
|
||||
m &= ~(1 << prio);
|
||||
|
||||
if (p->inner.clprio[prio].feed.rb_node)
|
||||
|
@ -196,9 +196,7 @@ void sctp_transport_reset_hb_timer(struct sctp_transport *transport)
|
||||
|
||||
/* When a data chunk is sent, reset the heartbeat interval. */
|
||||
expires = jiffies + sctp_transport_timeout(transport);
|
||||
if ((time_before(transport->hb_timer.expires, expires) ||
|
||||
!timer_pending(&transport->hb_timer)) &&
|
||||
!mod_timer(&transport->hb_timer,
|
||||
if (!mod_timer(&transport->hb_timer,
|
||||
expires + get_random_u32_below(transport->rto)))
|
||||
sctp_transport_hold(transport);
|
||||
}
|
||||
|
@ -2427,7 +2427,7 @@ static bool tls_is_tx_ready(struct tls_sw_context_tx *ctx)
|
||||
{
|
||||
struct tls_rec *rec;
|
||||
|
||||
rec = list_first_entry(&ctx->tx_list, struct tls_rec, list);
|
||||
rec = list_first_entry_or_null(&ctx->tx_list, struct tls_rec, list);
|
||||
if (!rec)
|
||||
return false;
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#define MAX_STRERR_LEN 256
|
||||
#define MAX_TEST_NAME 80
|
||||
|
||||
#define __always_unused __attribute__((__unused__))
|
||||
|
||||
#define _FAIL(errnum, fmt...) \
|
||||
({ \
|
||||
error_at_line(0, (errnum), __func__, __LINE__, fmt); \
|
||||
@ -321,7 +323,8 @@ static int socket_loopback(int family, int sotype)
|
||||
return socket_loopback_reuseport(family, sotype, -1);
|
||||
}
|
||||
|
||||
static void test_insert_invalid(int family, int sotype, int mapfd)
|
||||
static void test_insert_invalid(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
u32 key = 0;
|
||||
u64 value;
|
||||
@ -338,7 +341,8 @@ static void test_insert_invalid(int family, int sotype, int mapfd)
|
||||
FAIL_ERRNO("map_update: expected EBADF");
|
||||
}
|
||||
|
||||
static void test_insert_opened(int family, int sotype, int mapfd)
|
||||
static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
u32 key = 0;
|
||||
u64 value;
|
||||
@ -359,7 +363,8 @@ static void test_insert_opened(int family, int sotype, int mapfd)
|
||||
xclose(s);
|
||||
}
|
||||
|
||||
static void test_insert_bound(int family, int sotype, int mapfd)
|
||||
static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
@ -386,7 +391,8 @@ close:
|
||||
xclose(s);
|
||||
}
|
||||
|
||||
static void test_insert(int family, int sotype, int mapfd)
|
||||
static void test_insert(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
u64 value;
|
||||
u32 key;
|
||||
@ -402,7 +408,8 @@ static void test_insert(int family, int sotype, int mapfd)
|
||||
xclose(s);
|
||||
}
|
||||
|
||||
static void test_delete_after_insert(int family, int sotype, int mapfd)
|
||||
static void test_delete_after_insert(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
u64 value;
|
||||
u32 key;
|
||||
@ -419,7 +426,8 @@ static void test_delete_after_insert(int family, int sotype, int mapfd)
|
||||
xclose(s);
|
||||
}
|
||||
|
||||
static void test_delete_after_close(int family, int sotype, int mapfd)
|
||||
static void test_delete_after_close(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
int err, s;
|
||||
u64 value;
|
||||
@ -442,7 +450,8 @@ static void test_delete_after_close(int family, int sotype, int mapfd)
|
||||
FAIL_ERRNO("map_delete: expected EINVAL/EINVAL");
|
||||
}
|
||||
|
||||
static void test_lookup_after_insert(int family, int sotype, int mapfd)
|
||||
static void test_lookup_after_insert(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
u64 cookie, value;
|
||||
socklen_t len;
|
||||
@ -470,7 +479,8 @@ static void test_lookup_after_insert(int family, int sotype, int mapfd)
|
||||
xclose(s);
|
||||
}
|
||||
|
||||
static void test_lookup_after_delete(int family, int sotype, int mapfd)
|
||||
static void test_lookup_after_delete(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
int err, s;
|
||||
u64 value;
|
||||
@ -493,7 +503,8 @@ static void test_lookup_after_delete(int family, int sotype, int mapfd)
|
||||
xclose(s);
|
||||
}
|
||||
|
||||
static void test_lookup_32_bit_value(int family, int sotype, int mapfd)
|
||||
static void test_lookup_32_bit_value(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
u32 key, value32;
|
||||
int err, s;
|
||||
@ -523,7 +534,8 @@ close:
|
||||
xclose(s);
|
||||
}
|
||||
|
||||
static void test_update_existing(int family, int sotype, int mapfd)
|
||||
static void test_update_existing(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
int s1, s2;
|
||||
u64 value;
|
||||
@ -551,7 +563,7 @@ close_s1:
|
||||
/* Exercise the code path where we destroy child sockets that never
|
||||
* got accept()'ed, aka orphans, when parent socket gets closed.
|
||||
*/
|
||||
static void test_destroy_orphan_child(int family, int sotype, int mapfd)
|
||||
static void do_destroy_orphan_child(int family, int sotype, int mapfd)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
@ -582,10 +594,38 @@ close_srv:
|
||||
xclose(s);
|
||||
}
|
||||
|
||||
static void test_destroy_orphan_child(struct test_sockmap_listen *skel,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
int msg_verdict = bpf_program__fd(skel->progs.prog_msg_verdict);
|
||||
int skb_verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
|
||||
const struct test {
|
||||
int progfd;
|
||||
enum bpf_attach_type atype;
|
||||
} tests[] = {
|
||||
{ -1, -1 },
|
||||
{ msg_verdict, BPF_SK_MSG_VERDICT },
|
||||
{ skb_verdict, BPF_SK_SKB_VERDICT },
|
||||
};
|
||||
const struct test *t;
|
||||
|
||||
for (t = tests; t < tests + ARRAY_SIZE(tests); t++) {
|
||||
if (t->progfd != -1 &&
|
||||
xbpf_prog_attach(t->progfd, mapfd, t->atype, 0) != 0)
|
||||
return;
|
||||
|
||||
do_destroy_orphan_child(family, sotype, mapfd);
|
||||
|
||||
if (t->progfd != -1)
|
||||
xbpf_prog_detach2(t->progfd, mapfd, t->atype);
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform a passive open after removing listening socket from SOCKMAP
|
||||
* to ensure that callbacks get restored properly.
|
||||
*/
|
||||
static void test_clone_after_delete(int family, int sotype, int mapfd)
|
||||
static void test_clone_after_delete(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
@ -621,7 +661,8 @@ close_srv:
|
||||
* SOCKMAP, but got accept()'ed only after the parent has been removed
|
||||
* from SOCKMAP, gets cloned without parent psock state or callbacks.
|
||||
*/
|
||||
static void test_accept_after_delete(int family, int sotype, int mapfd)
|
||||
static void test_accept_after_delete(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
const u32 zero = 0;
|
||||
@ -675,7 +716,8 @@ close_srv:
|
||||
/* Check that child socket that got created and accepted while parent
|
||||
* was in a SOCKMAP is cloned without parent psock state or callbacks.
|
||||
*/
|
||||
static void test_accept_before_delete(int family, int sotype, int mapfd)
|
||||
static void test_accept_before_delete(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
const u32 zero = 0, one = 1;
|
||||
@ -784,7 +826,8 @@ done:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void test_syn_recv_insert_delete(int family, int sotype, int mapfd)
|
||||
static void test_syn_recv_insert_delete(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int sotype, int mapfd)
|
||||
{
|
||||
struct connect_accept_ctx ctx = { 0 };
|
||||
struct sockaddr_storage addr;
|
||||
@ -847,7 +890,8 @@ static void *listen_thread(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void test_race_insert_listen(int family, int socktype, int mapfd)
|
||||
static void test_race_insert_listen(struct test_sockmap_listen *skel __always_unused,
|
||||
int family, int socktype, int mapfd)
|
||||
{
|
||||
struct connect_accept_ctx ctx = { 0 };
|
||||
const u32 zero = 0;
|
||||
@ -1473,7 +1517,8 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
|
||||
int family, int sotype)
|
||||
{
|
||||
const struct op_test {
|
||||
void (*fn)(int family, int sotype, int mapfd);
|
||||
void (*fn)(struct test_sockmap_listen *skel,
|
||||
int family, int sotype, int mapfd);
|
||||
const char *name;
|
||||
int sotype;
|
||||
} tests[] = {
|
||||
@ -1520,7 +1565,7 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
|
||||
if (!test__start_subtest(s))
|
||||
continue;
|
||||
|
||||
t->fn(family, sotype, map_fd);
|
||||
t->fn(skel, family, sotype, map_fd);
|
||||
test_ops_cleanup(map);
|
||||
}
|
||||
}
|
||||
|
@ -225,3 +225,39 @@
|
||||
.result_unpriv = ACCEPT,
|
||||
.insn_processed = 15,
|
||||
},
|
||||
/* The test performs a conditional 64-bit write to a stack location
|
||||
* fp[-8], this is followed by an unconditional 8-bit write to fp[-8],
|
||||
* then data is read from fp[-8]. This sequence is unsafe.
|
||||
*
|
||||
* The test would be mistakenly marked as safe w/o dst register parent
|
||||
* preservation in verifier.c:copy_register_state() function.
|
||||
*
|
||||
* Note the usage of BPF_F_TEST_STATE_FREQ to force creation of the
|
||||
* checkpoint state after conditional 64-bit assignment.
|
||||
*/
|
||||
{
|
||||
"write tracking and register parent chain bug",
|
||||
.insns = {
|
||||
/* r6 = ktime_get_ns() */
|
||||
BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
|
||||
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||
/* r0 = ktime_get_ns() */
|
||||
BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
|
||||
/* if r0 > r6 goto +1 */
|
||||
BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_6, 1),
|
||||
/* *(u64 *)(r10 - 8) = 0xdeadbeef */
|
||||
BPF_ST_MEM(BPF_DW, BPF_REG_FP, -8, 0xdeadbeef),
|
||||
/* r1 = 42 */
|
||||
BPF_MOV64_IMM(BPF_REG_1, 42),
|
||||
/* *(u8 *)(r10 - 8) = r1 */
|
||||
BPF_STX_MEM(BPF_B, BPF_REG_FP, BPF_REG_1, -8),
|
||||
/* r2 = *(u64 *)(r10 - 8) */
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_FP, -8),
|
||||
/* exit(0) */
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.flags = BPF_F_TEST_STATE_FREQ,
|
||||
.errstr = "invalid read from stack off -8+1 size 8",
|
||||
.result = REJECT,
|
||||
},
|
||||
|
@ -6,7 +6,7 @@ ksft_skip=4
|
||||
NS=ns
|
||||
IP6=2001:db8:1::1/64
|
||||
TGT6=2001:db8:1::2
|
||||
TMPF=`mktemp`
|
||||
TMPF=$(mktemp --suffix ".pcap")
|
||||
|
||||
cleanup()
|
||||
{
|
||||
|
@ -7,6 +7,7 @@ readonly GREEN='\033[0;92m'
|
||||
readonly YELLOW='\033[0;33m'
|
||||
readonly RED='\033[0;31m'
|
||||
readonly NC='\033[0m' # No Color
|
||||
readonly TESTPORT=8000
|
||||
|
||||
readonly KSFT_PASS=0
|
||||
readonly KSFT_FAIL=1
|
||||
@ -56,11 +57,26 @@ trap wake_children EXIT
|
||||
|
||||
run_one() {
|
||||
local -r args=$@
|
||||
local nr_socks=0
|
||||
local i=0
|
||||
local -r timeout=10
|
||||
|
||||
./udpgso_bench_rx &
|
||||
./udpgso_bench_rx -t &
|
||||
./udpgso_bench_rx -p "$TESTPORT" &
|
||||
./udpgso_bench_rx -p "$TESTPORT" -t &
|
||||
|
||||
./udpgso_bench_tx ${args}
|
||||
# Wait for the above test program to get ready to receive connections.
|
||||
while [ "$i" -lt "$timeout" ]; do
|
||||
nr_socks="$(ss -lnHi | grep -c "\*:${TESTPORT}")"
|
||||
[ "$nr_socks" -eq 2 ] && break
|
||||
i=$((i + 1))
|
||||
sleep 1
|
||||
done
|
||||
if [ "$nr_socks" -ne 2 ]; then
|
||||
echo "timed out while waiting for udpgso_bench_rx"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./udpgso_bench_tx -p "$TESTPORT" ${args}
|
||||
}
|
||||
|
||||
run_in_netns() {
|
||||
|
@ -250,7 +250,7 @@ static int recv_msg(int fd, char *buf, int len, int *gso_size)
|
||||
static void do_flush_udp(int fd)
|
||||
{
|
||||
static char rbuf[ETH_MAX_MTU];
|
||||
int ret, len, gso_size, budget = 256;
|
||||
int ret, len, gso_size = 0, budget = 256;
|
||||
|
||||
len = cfg_read_all ? sizeof(rbuf) : 0;
|
||||
while (budget--) {
|
||||
@ -336,6 +336,8 @@ static void parse_opts(int argc, char **argv)
|
||||
cfg_verify = true;
|
||||
cfg_read_all = true;
|
||||
break;
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ static int cfg_payload_len = (1472 * 42);
|
||||
static int cfg_port = 8000;
|
||||
static int cfg_runtime_ms = -1;
|
||||
static bool cfg_poll;
|
||||
static int cfg_poll_loop_timeout_ms = 2000;
|
||||
static bool cfg_segment;
|
||||
static bool cfg_sendmmsg;
|
||||
static bool cfg_tcp;
|
||||
@ -235,16 +236,17 @@ static void flush_errqueue_recv(int fd)
|
||||
}
|
||||
}
|
||||
|
||||
static void flush_errqueue(int fd, const bool do_poll)
|
||||
static void flush_errqueue(int fd, const bool do_poll,
|
||||
unsigned long poll_timeout, const bool poll_err)
|
||||
{
|
||||
if (do_poll) {
|
||||
struct pollfd fds = {0};
|
||||
int ret;
|
||||
|
||||
fds.fd = fd;
|
||||
ret = poll(&fds, 1, 500);
|
||||
ret = poll(&fds, 1, poll_timeout);
|
||||
if (ret == 0) {
|
||||
if (cfg_verbose)
|
||||
if ((cfg_verbose) && (poll_err))
|
||||
fprintf(stderr, "poll timeout\n");
|
||||
} else if (ret < 0) {
|
||||
error(1, errno, "poll");
|
||||
@ -254,6 +256,20 @@ static void flush_errqueue(int fd, const bool do_poll)
|
||||
flush_errqueue_recv(fd);
|
||||
}
|
||||
|
||||
static void flush_errqueue_retry(int fd, unsigned long num_sends)
|
||||
{
|
||||
unsigned long tnow, tstop;
|
||||
bool first_try = true;
|
||||
|
||||
tnow = gettimeofday_ms();
|
||||
tstop = tnow + cfg_poll_loop_timeout_ms;
|
||||
do {
|
||||
flush_errqueue(fd, true, tstop - tnow, first_try);
|
||||
first_try = false;
|
||||
tnow = gettimeofday_ms();
|
||||
} while ((stat_zcopies != num_sends) && (tnow < tstop));
|
||||
}
|
||||
|
||||
static int send_tcp(int fd, char *data)
|
||||
{
|
||||
int ret, done = 0, count = 0;
|
||||
@ -413,7 +429,8 @@ static int send_udp_segment(int fd, char *data)
|
||||
|
||||
static void usage(const char *filepath)
|
||||
{
|
||||
error(1, 0, "Usage: %s [-46acmHPtTuvz] [-C cpu] [-D dst ip] [-l secs] [-M messagenr] [-p port] [-s sendsize] [-S gsosize]",
|
||||
error(1, 0, "Usage: %s [-46acmHPtTuvz] [-C cpu] [-D dst ip] [-l secs] "
|
||||
"[-L secs] [-M messagenr] [-p port] [-s sendsize] [-S gsosize]",
|
||||
filepath);
|
||||
}
|
||||
|
||||
@ -423,7 +440,7 @@ static void parse_opts(int argc, char **argv)
|
||||
int max_len, hdrlen;
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "46acC:D:Hl:mM:p:s:PS:tTuvz")) != -1) {
|
||||
while ((c = getopt(argc, argv, "46acC:D:Hl:L:mM:p:s:PS:tTuvz")) != -1) {
|
||||
switch (c) {
|
||||
case '4':
|
||||
if (cfg_family != PF_UNSPEC)
|
||||
@ -452,6 +469,9 @@ static void parse_opts(int argc, char **argv)
|
||||
case 'l':
|
||||
cfg_runtime_ms = strtoul(optarg, NULL, 10) * 1000;
|
||||
break;
|
||||
case 'L':
|
||||
cfg_poll_loop_timeout_ms = strtoul(optarg, NULL, 10) * 1000;
|
||||
break;
|
||||
case 'm':
|
||||
cfg_sendmmsg = true;
|
||||
break;
|
||||
@ -490,6 +510,8 @@ static void parse_opts(int argc, char **argv)
|
||||
case 'z':
|
||||
cfg_zerocopy = true;
|
||||
break;
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -677,7 +699,7 @@ int main(int argc, char **argv)
|
||||
num_sends += send_udp(fd, buf[i]);
|
||||
num_msgs++;
|
||||
if ((cfg_zerocopy && ((num_msgs & 0xF) == 0)) || cfg_tx_tstamp)
|
||||
flush_errqueue(fd, cfg_poll);
|
||||
flush_errqueue(fd, cfg_poll, 500, true);
|
||||
|
||||
if (cfg_msg_nr && num_msgs >= cfg_msg_nr)
|
||||
break;
|
||||
@ -696,7 +718,7 @@ int main(int argc, char **argv)
|
||||
} while (!interrupted && (cfg_runtime_ms == -1 || tnow < tstop));
|
||||
|
||||
if (cfg_zerocopy || cfg_tx_tstamp)
|
||||
flush_errqueue(fd, true);
|
||||
flush_errqueue_retry(fd, num_sends);
|
||||
|
||||
if (close(fd))
|
||||
error(1, errno, "close");
|
||||
|
Loading…
Reference in New Issue
Block a user