mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Lots of fixes, double the count even for the "new normal".
Largely due to my time off followed by a networking conference
which distracted most maintainers (less so the AI generators).
Including fixes from Bluetooth and WiFi.
Current release - regressions:
- wifi: mt76: fix MAC address for non OF pcie cards
Current release - new code bugs:
- mptcp: fix BUILD_BUG_ON on legacy ARM config
- wifi: cfg80211: guard optional PMSR nominal time
Previous releases - regressions:
- qrtr: ns: raise node count limit to 512, we arbitrarily picked
256 as a limit, turns out it was too low for real world deployments
- vhost-net: fix TX stall when vhost owns virtio-net header
- eth: amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN
- wifi: ath12k: fix low MLO RX throughput on WCN7850
Previous releases - always broken:
- number of random AI fixes for SCTP, RDS and TIPC protocols
- more AI-looking fixes for WiFi drivers
- number of fixes for missing pointer reloading after skb pull
- reject BPF redirect use from qdisc qevent block
- tcp: initialize standalone TCP-AO response padding
- vsock/virtio: collapse receive queue under memory pressure to avoid
client OOMing the host with tiny messages
- ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup,
make sure the ICMP response routing follows the routing policy
- gro: fix double aggregation of flush-marked skbs
- ovpn: fix various refcount bugs
- tls: device: push pending open record on splice EOF
- eth: mlx5:
- use sender devcom for MPV master-up
- fix MCIA register buffer overflow on 32 dword reads
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmpiX68ACgkQMUZtbf5S
IrvYsRAAkuMhUpz0Ss9aF7rBY8iTp4SofSvFeVe06ywraUfqPuflGlak07t1Lz/i
G4MuKXN0q8m+B0EZddfMeYw6rCGd0SCtFAkxUI3dd+pu4hssgioaCPL193drSsfC
/lYeacjVL45jNrQvAWwKsRaAs3xdwzxWf0ddIXWvVWbdDsVfIf/mYahSS3TvniWw
MQtEbWPnFwPvOrHzb+1ChLELCtig/yvK+3xS9JrwOkjUF4BczOUgqrYlG5MWerXP
f/JDLsegPcoZaTycW5F5fshY05umeRQza/zCFqMKQNcQux49fjREnYxBuyTacVCo
0cxhsNbKOhvBpBFNsHA6TjUbDxuiyL8L/g3e7VOlQFxI4hX3IMsnsP+UrSdE2zyG
lgFAQ6HIcelgFnzFcwp9YEGsiZ5nDoJKe5aBcgftzTFPx3Plh1UeCrNjYtJawcjk
1POovopI+G6eszwluVOoucUdDD3wf0jPgDqvdOcI9P9FVTsFmvRESsfen7NbdjG0
v5mk9+sasWL1dns6mre6nt5is4QWSg7PDjufQUhuPKSSEnld+csEgmyxmUm0/FgL
krUZLHdx0Yj9yIOAIYAvz8QoW9jHIyK05Mr7CoL4a/9RJ4rtxjb+3CT9qebeyd49
jK5uzYX6tPHvILFK4CgZwcE/z9S+DoxCAuDEp6LhfstKsJW4KIM=
=DIF8
-----END PGP SIGNATURE-----
Merge tag 'net-7.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Lots of fixes, double the count even for the 'new normal'. Largely due
to my time off followed by a networking conference which distracted
most maintainers (less so the AI generators).
Including fixes from Bluetooth and WiFi.
Current release - regressions:
- wifi: mt76: fix MAC address for non OF pcie cards
Current release - new code bugs:
- mptcp: fix BUILD_BUG_ON on legacy ARM config
- wifi: cfg80211: guard optional PMSR nominal time
Previous releases - regressions:
- qrtr: ns: raise node count limit to 512, we arbitrarily picked
256 as a limit, turns out it was too low for real world deployments
- vhost-net: fix TX stall when vhost owns virtio-net header
- eth: amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN
- wifi: ath12k: fix low MLO RX throughput on WCN7850
Previous releases - always broken:
- number of random AI fixes for SCTP, RDS and TIPC protocols
- more AI-looking fixes for WiFi drivers
- number of fixes for missing pointer reloading after skb pull
- reject BPF redirect use from qdisc qevent block
- tcp: initialize standalone TCP-AO response padding
- vsock/virtio: collapse receive queue under memory pressure to avoid
client OOMing the host with tiny messages
- ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup,
make sure the ICMP response routing follows the routing policy
- gro: fix double aggregation of flush-marked skbs
- ovpn: fix various refcount bugs
- tls: device: push pending open record on splice EOF
- eth: mlx5:
- use sender devcom for MPV master-up
- fix MCIA register buffer overflow on 32 dword reads"
* tag 'net-7.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (234 commits)
drop_monitor: perform u64_stats updates under IRQ-disabled section
drop_monitor: fix size calculations for 64-bit attributes
net: drop_monitor: fix info leak in NET_DM_ATTR_PAYLOAD
mptcp: fix BUILD_BUG_ON on legacy ARM config
selftests: mptcp: userspace_pm: fix undefined variable port
mptcp: fix stale skb->sk reference on subflow close
mptcp: pm: userspace: fix use-after-free in get_local_id
mptcp: decrement subflows counter on failed passive join
mac802154: hold an interface reference across the scan worker
sctp: don't free the ASCONF's own transport in DEL-IP processing
phonet: check register_netdevice_notifier() error in phonet_device_init()
phonet: pep: fix use-after-free in pep_get_sb()
bnge/bng_re: fix ring ID widths
tipc: fix integer overflow in tipc_recvmsg() and tipc_recvstream()
net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets()
mctp: check register_netdevice_notifier() error in mctp_device_init()
ptp: netc: explicitly clear TMR_OFF during initialization
rds: tcp: unregister sysctl before tearing down listen socket
ipv6: Change allocation flags to match rcu_read_lock section requirements
net: slip: serialize receive against buffer reallocation
...
This commit is contained in:
commit
d326f83e81
11
.mailmap
11
.mailmap
|
|
@ -66,6 +66,11 @@ Alex Hung <alexhung@gmail.com> <alex.hung@canonical.com>
|
|||
Alex Shi <alexs@kernel.org> <alex.shi@intel.com>
|
||||
Alex Shi <alexs@kernel.org> <alex.shi@linaro.org>
|
||||
Alex Shi <alexs@kernel.org> <alex.shi@linux.alibaba.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <maxtram95@gmail.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <maximmi@mellanox.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <maximmi@nvidia.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <maxim@isovalent.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <alice@isovalent.com>
|
||||
Aloka Dixit <quic_alokad@quicinc.com> <alokad@codeaurora.org>
|
||||
Al Viro <viro@ftp.linux.org.uk>
|
||||
Al Viro <viro@zenIV.linux.org.uk>
|
||||
|
|
@ -585,8 +590,6 @@ Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@osg.samsung.com>
|
|||
Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@redhat.com>
|
||||
Mauro Carvalho Chehab <mchehab@kernel.org> <m.chehab@samsung.com>
|
||||
Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@s-opensource.com>
|
||||
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@mellanox.com>
|
||||
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@nvidia.com>
|
||||
Maxime Ripard <mripard@kernel.org> <maxime@cerno.tech>
|
||||
Maxime Ripard <mripard@kernel.org> <maxime.ripard@bootlin.com>
|
||||
Maxime Ripard <mripard@kernel.org> <maxime.ripard@free-electrons.com>
|
||||
|
|
@ -595,8 +598,8 @@ Mayuresh Janorkar <mayur@ti.com>
|
|||
Md Sadre Alam <quic_mdalam@quicinc.com> <mdalam@codeaurora.org>
|
||||
Miaoqing Pan <quic_miaoqing@quicinc.com> <miaoqing@codeaurora.org>
|
||||
Michael Buesch <m@bues.ch>
|
||||
Michal Grzeschik <mgr@kernel.org> <m.grzeschik@pengutronix.de>
|
||||
Michal Grzeschik <mgr@kernel.org> <mgr@pengutronix.de>
|
||||
Michael Grzeschik <mgr@kernel.org> <m.grzeschik@pengutronix.de>
|
||||
Michael Grzeschik <mgr@kernel.org> <mgr@pengutronix.de>
|
||||
Michael Riesch <michael.riesch@collabora.com> <michael.riesch@wolfvision.net>
|
||||
Michal Simek <michal.simek@amd.com> <michal.simek@xilinx.com>
|
||||
Michel Dänzer <michel@tungstengraphics.com>
|
||||
|
|
|
|||
|
|
@ -1585,31 +1585,31 @@ attribute-sets:
|
|||
type: u32
|
||||
-
|
||||
name: mode
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: guard
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: protect
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: fast-leave
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: learning
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: unicast-flood
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: proxyarp
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: learning-sync
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: proxyarp-wifi
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: root-id
|
||||
type: binary
|
||||
|
|
@ -1656,34 +1656,34 @@ attribute-sets:
|
|||
type: pad
|
||||
-
|
||||
name: mcast-flood
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mcast-to-ucast
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: vlan-tunnel
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: bcast-flood
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: group-fwd-mask
|
||||
type: u16
|
||||
-
|
||||
name: neigh-suppress
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: isolated
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: backup-port
|
||||
type: u32
|
||||
-
|
||||
name: mrp-ring-open
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mrp-in-open
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mcast-eht-hosts-limit
|
||||
type: u32
|
||||
|
|
@ -1692,10 +1692,10 @@ attribute-sets:
|
|||
type: u32
|
||||
-
|
||||
name: locked
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mab
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mcast-n-groups
|
||||
type: u32
|
||||
|
|
@ -1704,7 +1704,7 @@ attribute-sets:
|
|||
type: u32
|
||||
-
|
||||
name: neigh-vlan-suppress
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: backup-nhid
|
||||
type: u32
|
||||
|
|
|
|||
|
|
@ -19109,6 +19109,7 @@ F: drivers/nfc/
|
|||
F: include/net/nfc/
|
||||
F: include/uapi/linux/nfc.h
|
||||
F: net/nfc/
|
||||
F: tools/testing/selftests/nci/
|
||||
|
||||
NFC VIRTUAL NCI DEVICE DRIVER
|
||||
M: Bongsu Jeon <bongsu.jeon@samsung.com>
|
||||
|
|
@ -25973,8 +25974,9 @@ F: Documentation/devicetree/bindings/phy/st,stm32mp25-combophy.yaml
|
|||
F: drivers/phy/st/phy-stm32-combophy.c
|
||||
|
||||
STMMAC ETHERNET DRIVER
|
||||
M: Maxime Chevallier <maxime.chevallier@bootlin.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Orphan
|
||||
S: Maintained
|
||||
F: Documentation/networking/device_drivers/ethernet/stmicro/
|
||||
F: drivers/net/ethernet/stmicro/stmmac/
|
||||
|
||||
|
|
@ -27930,7 +27932,6 @@ F: drivers/usb/isp1760/*
|
|||
|
||||
USB LAN78XX ETHERNET DRIVER
|
||||
M: Thangaraj Samynathan <Thangaraj.S@microchip.com>
|
||||
M: Rengarajan Sundararajan <Rengarajan.S@microchip.com>
|
||||
M: UNGLinuxDriver@microchip.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ ATOMIC_NOTIFIER_HEAD(s390_epoch_delta_notifier);
|
|||
EXPORT_SYMBOL(s390_epoch_delta_notifier);
|
||||
|
||||
unsigned char ptff_function_mask[16];
|
||||
EXPORT_SYMBOL(ptff_function_mask);
|
||||
|
||||
static unsigned long lpar_offset;
|
||||
static unsigned long initial_leap_seconds;
|
||||
|
|
|
|||
|
|
@ -2782,7 +2782,9 @@ static int btusb_setup_realtek(struct hci_dev *hdev)
|
|||
|
||||
static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
|
||||
if (skb->len >= HCI_EVENT_HDR_SIZE + 1 &&
|
||||
skb->data[0] == HCI_VENDOR_PKT &&
|
||||
skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
|
||||
struct rtk_dev_coredump_hdr hdr = {
|
||||
.code = RTK_DEVCOREDUMP_CODE_MEMDUMP,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ static void bng_re_fill_fw_msg(struct bnge_fw_msg *fw_msg, void *msg,
|
|||
}
|
||||
|
||||
static int bng_re_net_ring_free(struct bng_re_dev *rdev,
|
||||
u16 fw_ring_id, int type)
|
||||
u32 fw_ring_id, int type)
|
||||
{
|
||||
struct bnge_auxr_dev *aux_dev = rdev->aux_dev;
|
||||
struct hwrm_ring_free_input req = {};
|
||||
|
|
@ -123,7 +123,7 @@ static int bng_re_net_ring_free(struct bng_re_dev *rdev,
|
|||
|
||||
bng_re_init_hwrm_hdr((void *)&req, HWRM_RING_FREE);
|
||||
req.ring_type = type;
|
||||
req.ring_id = cpu_to_le16(fw_ring_id);
|
||||
req.ring_id = cpu_to_le32(fw_ring_id);
|
||||
bng_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
|
||||
sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT);
|
||||
rc = bnge_send_msg(aux_dev, &fw_msg);
|
||||
|
|
@ -161,7 +161,7 @@ static int bng_re_net_ring_alloc(struct bng_re_dev *rdev,
|
|||
sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT);
|
||||
rc = bnge_send_msg(aux_dev, &fw_msg);
|
||||
if (!rc)
|
||||
*fw_ring_id = le16_to_cpu(resp.ring_id);
|
||||
*fw_ring_id = (u16)le32_to_cpu(resp.ring_id);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1211,7 +1211,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
data = true;
|
||||
}
|
||||
v6 = false;
|
||||
group.ip4 = iph->daddr;
|
||||
group.ip4 = ip_hdr(skb)->daddr;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
} else if (iph->version == 6) {
|
||||
ip6h = ipv6_hdr(skb);
|
||||
|
|
@ -1235,7 +1235,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
data = true;
|
||||
}
|
||||
v6 = true;
|
||||
group.ip6 = ip6h->daddr;
|
||||
group.ip6 = ipv6_hdr(skb)->daddr;
|
||||
#endif
|
||||
} else {
|
||||
dev->stats.tx_errors++;
|
||||
|
|
@ -1278,12 +1278,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash],
|
||||
node) {
|
||||
if (!v6) {
|
||||
if (gnode->group_addr.ip4 == iph->daddr)
|
||||
if (gnode->group_addr.ip4 == group.ip4)
|
||||
goto found;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
} else {
|
||||
if (ipv6_addr_equal(&gnode->group_addr.ip6,
|
||||
&ip6h->daddr))
|
||||
&group.ip6))
|
||||
goto found;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -2000,14 +2000,18 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,
|
|||
struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb);
|
||||
int len = skb_transport_offset(skb) + sizeof(*ihrv3);
|
||||
void *zero_grec = (void *)&igmpv3_zero_grec;
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
struct amt_group_node *gnode;
|
||||
union amt_addr group, host;
|
||||
struct igmpv3_grec *grec;
|
||||
__be32 saddr;
|
||||
u16 nsrcs;
|
||||
u16 ngrec;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ntohs(ihrv3->ngrec); i++) {
|
||||
saddr = ip_hdr(skb)->saddr;
|
||||
ngrec = ntohs(ihrv3->ngrec);
|
||||
|
||||
for (i = 0; i < ngrec; i++) {
|
||||
len += sizeof(*grec);
|
||||
if (!ip_mc_may_pull(skb, len))
|
||||
break;
|
||||
|
|
@ -2019,10 +2023,13 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,
|
|||
if (!ip_mc_may_pull(skb, len))
|
||||
break;
|
||||
|
||||
grec = (void *)(skb->data + len - sizeof(*grec) -
|
||||
nsrcs * sizeof(__be32));
|
||||
|
||||
memset(&group, 0, sizeof(union amt_addr));
|
||||
group.ip4 = grec->grec_mca;
|
||||
memset(&host, 0, sizeof(union amt_addr));
|
||||
host.ip4 = iph->saddr;
|
||||
host.ip4 = saddr;
|
||||
gnode = amt_lookup_group(tunnel, &group, &host, false);
|
||||
if (!gnode) {
|
||||
gnode = amt_add_group(amt, tunnel, &group, &host,
|
||||
|
|
@ -2162,14 +2169,18 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,
|
|||
struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb);
|
||||
int len = skb_transport_offset(skb) + sizeof(*mld2r);
|
||||
void *zero_grec = (void *)&mldv2_zero_grec;
|
||||
struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||
struct amt_group_node *gnode;
|
||||
union amt_addr group, host;
|
||||
struct mld2_grec *grec;
|
||||
struct in6_addr saddr;
|
||||
u16 nsrcs;
|
||||
u16 ngrec;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) {
|
||||
saddr = ipv6_hdr(skb)->saddr;
|
||||
ngrec = ntohs(mld2r->mld2r_ngrec);
|
||||
|
||||
for (i = 0; i < ngrec; i++) {
|
||||
len += sizeof(*grec);
|
||||
if (!ipv6_mc_may_pull(skb, len))
|
||||
break;
|
||||
|
|
@ -2181,10 +2192,13 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,
|
|||
if (!ipv6_mc_may_pull(skb, len))
|
||||
break;
|
||||
|
||||
grec = (void *)(skb->data + len - sizeof(*grec) -
|
||||
nsrcs * sizeof(struct in6_addr));
|
||||
|
||||
memset(&group, 0, sizeof(union amt_addr));
|
||||
group.ip6 = grec->grec_mca;
|
||||
memset(&host, 0, sizeof(union amt_addr));
|
||||
host.ip6 = ip6h->saddr;
|
||||
host.ip6 = saddr;
|
||||
gnode = amt_lookup_group(tunnel, &group, &host, true);
|
||||
if (!gnode) {
|
||||
gnode = amt_add_group(amt, tunnel, &group, &host,
|
||||
|
|
@ -2305,7 +2319,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
|
|||
skb_push(skb, sizeof(*eth));
|
||||
skb_reset_mac_header(skb);
|
||||
skb_pull(skb, sizeof(*eth));
|
||||
eth = eth_hdr(skb);
|
||||
|
||||
if (skb_cow_head(skb, 0))
|
||||
return true;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(*iph)))
|
||||
return true;
|
||||
|
|
@ -2315,6 +2331,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
|
|||
if (!ipv4_is_multicast(iph->daddr))
|
||||
return true;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
eth = eth_hdr(skb);
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
ip_eth_mc_map(iph->daddr, eth->h_dest);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
|
@ -2328,6 +2345,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
|
|||
if (!ipv6_addr_is_multicast(&ip6h->daddr))
|
||||
return true;
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
eth = eth_hdr(skb);
|
||||
eth->h_proto = htons(ETH_P_IPV6);
|
||||
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
|
||||
#endif
|
||||
|
|
@ -2351,10 +2369,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
|||
struct sk_buff *skb)
|
||||
{
|
||||
struct amt_header_membership_query *amtmq;
|
||||
struct igmpv3_query *ihv3;
|
||||
struct ethhdr *eth, *oeth;
|
||||
struct igmpv3_query *ihv3;
|
||||
u8 h_source[ETH_ALEN];
|
||||
struct iphdr *iph;
|
||||
int hdr_size, len;
|
||||
u64 response_mac;
|
||||
|
||||
hdr_size = sizeof(*amtmq) + sizeof(struct udphdr);
|
||||
if (!pskb_may_pull(skb, hdr_size))
|
||||
|
|
@ -2367,6 +2387,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
|||
if (amtmq->nonce != amt->nonce)
|
||||
return true;
|
||||
|
||||
response_mac = amtmq->response_mac;
|
||||
|
||||
hdr_size -= sizeof(*eth);
|
||||
if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false))
|
||||
return true;
|
||||
|
|
@ -2376,6 +2398,9 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
|||
skb_pull(skb, sizeof(*eth));
|
||||
skb_reset_network_header(skb);
|
||||
eth = eth_hdr(skb);
|
||||
ether_addr_copy(h_source, oeth->h_source);
|
||||
if (skb_cow_head(skb, 0))
|
||||
return true;
|
||||
if (!pskb_may_pull(skb, sizeof(*iph)))
|
||||
return true;
|
||||
|
||||
|
|
@ -2388,6 +2413,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
|||
sizeof(*ihv3)))
|
||||
return true;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
if (!ipv4_is_multicast(iph->daddr))
|
||||
return true;
|
||||
|
||||
|
|
@ -2395,10 +2421,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
|||
skb_reset_transport_header(skb);
|
||||
skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS);
|
||||
WRITE_ONCE(amt->ready4, true);
|
||||
amt->mac = amtmq->response_mac;
|
||||
amt->mac = response_mac;
|
||||
amt->req_cnt = 0;
|
||||
amt->qi = ihv3->qqic;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
eth = eth_hdr(skb);
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
ip_eth_mc_map(iph->daddr, eth->h_dest);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
|
@ -2421,10 +2448,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
|||
skb_reset_transport_header(skb);
|
||||
skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS);
|
||||
WRITE_ONCE(amt->ready6, true);
|
||||
amt->mac = amtmq->response_mac;
|
||||
amt->mac = response_mac;
|
||||
amt->req_cnt = 0;
|
||||
amt->qi = mld2q->mld2q_qqic;
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
eth = eth_hdr(skb);
|
||||
eth->h_proto = htons(ETH_P_IPV6);
|
||||
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
|
||||
#endif
|
||||
|
|
@ -2432,7 +2460,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
|||
return true;
|
||||
}
|
||||
|
||||
ether_addr_copy(eth->h_source, oeth->h_source);
|
||||
ether_addr_copy(eth->h_source, h_source);
|
||||
skb->pkt_type = PACKET_MULTICAST;
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
len = skb->len;
|
||||
|
|
@ -2455,8 +2483,11 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
|||
struct ethhdr *eth;
|
||||
struct iphdr *iph;
|
||||
int len, hdr_size;
|
||||
u64 response_mac;
|
||||
__be32 saddr;
|
||||
__be32 nonce;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
saddr = ip_hdr(skb)->saddr;
|
||||
|
||||
hdr_size = sizeof(*amtmu) + sizeof(struct udphdr);
|
||||
if (!pskb_may_pull(skb, hdr_size))
|
||||
|
|
@ -2466,15 +2497,18 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
|||
if (amtmu->reserved || amtmu->version)
|
||||
return true;
|
||||
|
||||
nonce = amtmu->nonce;
|
||||
response_mac = amtmu->response_mac;
|
||||
|
||||
if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false))
|
||||
return true;
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) {
|
||||
if (tunnel->ip4 == iph->saddr) {
|
||||
if ((amtmu->nonce == tunnel->nonce &&
|
||||
amtmu->response_mac == tunnel->mac)) {
|
||||
if (tunnel->ip4 == saddr) {
|
||||
if ((nonce == tunnel->nonce &&
|
||||
response_mac == tunnel->mac)) {
|
||||
mod_delayed_work(amt_wq, &tunnel->gc_wq,
|
||||
msecs_to_jiffies(amt_gmi(amt))
|
||||
* 3);
|
||||
|
|
@ -2492,6 +2526,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
|||
if (!pskb_may_pull(skb, sizeof(*iph)))
|
||||
return true;
|
||||
|
||||
if (skb_cow_head(skb, 0))
|
||||
return true;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
if (iph->version == 4) {
|
||||
if (ip_mc_check_igmp(skb)) {
|
||||
|
|
@ -2508,6 +2545,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
|||
eth = eth_hdr(skb);
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
iph = ip_hdr(skb);
|
||||
ip_eth_mc_map(iph->daddr, eth->h_dest);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
} else if (iph->version == 6) {
|
||||
|
|
@ -2527,6 +2565,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
|||
eth = eth_hdr(skb);
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
eth->h_proto = htons(ETH_P_IPV6);
|
||||
ip6h = ipv6_hdr(skb);
|
||||
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
|
||||
#endif
|
||||
} else {
|
||||
|
|
@ -2772,7 +2811,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb)
|
|||
static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct amt_dev *amt;
|
||||
struct iphdr *iph;
|
||||
__be32 saddr;
|
||||
int type;
|
||||
bool err;
|
||||
|
||||
|
|
@ -2785,7 +2824,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
skb->dev = amt->dev;
|
||||
iph = ip_hdr(skb);
|
||||
saddr = ip_hdr(skb)->saddr;
|
||||
type = amt_parse_type(skb);
|
||||
if (type == -1) {
|
||||
err = true;
|
||||
|
|
@ -2795,7 +2834,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
|||
if (amt->mode == AMT_MODE_GATEWAY) {
|
||||
switch (type) {
|
||||
case AMT_MSG_ADVERTISEMENT:
|
||||
if (iph->saddr != amt->discovery_ip) {
|
||||
if (saddr != amt->discovery_ip) {
|
||||
netdev_dbg(amt->dev, "Invalid Relay IP\n");
|
||||
err = true;
|
||||
goto drop;
|
||||
|
|
@ -2807,7 +2846,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
|||
}
|
||||
goto out;
|
||||
case AMT_MSG_MULTICAST_DATA:
|
||||
if (iph->saddr != amt->remote_ip) {
|
||||
if (saddr != amt->remote_ip) {
|
||||
netdev_dbg(amt->dev, "Invalid Relay IP\n");
|
||||
err = true;
|
||||
goto drop;
|
||||
|
|
@ -2818,7 +2857,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
|||
else
|
||||
goto out;
|
||||
case AMT_MSG_MEMBERSHIP_QUERY:
|
||||
if (iph->saddr != amt->remote_ip) {
|
||||
if (saddr != amt->remote_ip) {
|
||||
netdev_dbg(amt->dev, "Invalid Relay IP\n");
|
||||
err = true;
|
||||
goto drop;
|
||||
|
|
@ -2995,9 +3034,15 @@ static int amt_dev_open(struct net_device *dev)
|
|||
amt->event_idx = 0;
|
||||
amt->nr_events = 0;
|
||||
|
||||
enable_delayed_work(&amt->discovery_wq);
|
||||
enable_delayed_work(&amt->req_wq);
|
||||
|
||||
err = amt_socket_create(amt);
|
||||
if (err)
|
||||
if (err) {
|
||||
disable_delayed_work(&amt->req_wq);
|
||||
disable_delayed_work(&amt->discovery_wq);
|
||||
return err;
|
||||
}
|
||||
|
||||
amt->req_cnt = 0;
|
||||
amt->remote_ip = 0;
|
||||
|
|
@ -3023,8 +3068,8 @@ static int amt_dev_stop(struct net_device *dev)
|
|||
struct sock *sk;
|
||||
int i;
|
||||
|
||||
cancel_delayed_work_sync(&amt->req_wq);
|
||||
cancel_delayed_work_sync(&amt->discovery_wq);
|
||||
disable_delayed_work_sync(&amt->req_wq);
|
||||
disable_delayed_work_sync(&amt->discovery_wq);
|
||||
cancel_delayed_work_sync(&amt->secret_wq);
|
||||
|
||||
/* shutdown */
|
||||
|
|
@ -3278,6 +3323,8 @@ static int amt_newlink(struct net_device *dev,
|
|||
INIT_DELAYED_WORK(&amt->req_wq, amt_req_work);
|
||||
INIT_DELAYED_WORK(&amt->secret_wq, amt_secret_work);
|
||||
INIT_WORK(&amt->event_wq, amt_event_work);
|
||||
disable_delayed_work(&amt->req_wq);
|
||||
disable_delayed_work(&amt->discovery_wq);
|
||||
INIT_LIST_HEAD(&amt->tunnel_list);
|
||||
return 0;
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -3455,7 +3455,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave)
|
|||
{
|
||||
bond_arp_send_all(bond, slave);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
bond_ns_send_all(bond, slave);
|
||||
if (likely(ipv6_mod_enabled()))
|
||||
bond_ns_send_all(bond, slave);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1686,11 +1686,14 @@ static void airoha_qdma_stop_napi(struct airoha_qdma *qdma)
|
|||
}
|
||||
}
|
||||
|
||||
static void airoha_dev_get_hw_stats(struct airoha_gdm_dev *dev)
|
||||
static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = dev->port;
|
||||
struct airoha_eth *eth = dev->eth;
|
||||
u32 val, i = 0;
|
||||
u64 data;
|
||||
|
||||
spin_lock(&port->stats_lock);
|
||||
|
||||
/* Read relevant MIB for GDM with multiple port attached */
|
||||
if (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)
|
||||
|
|
@ -1701,152 +1704,188 @@ static void airoha_dev_get_hw_stats(struct airoha_gdm_dev *dev)
|
|||
|
||||
u64_stats_update_begin(&dev->stats.syncp);
|
||||
|
||||
/* TX */
|
||||
/* TX - 64-bit H+L registers: hw accumulates the total, read directly.
|
||||
* Use local variable to prevent readers from seeing intermediate values.
|
||||
* Clamp to prevent regression from torn reads between H and L.
|
||||
*/
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id));
|
||||
dev->stats.tx_ok_pkts += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_L(port->id));
|
||||
dev->stats.tx_ok_pkts += val;
|
||||
data += val;
|
||||
dev->stats.tx_ok_pkts = max(data, dev->stats.tx_ok_pkts);
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_H(port->id));
|
||||
dev->stats.tx_ok_bytes += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_L(port->id));
|
||||
dev->stats.tx_ok_bytes += val;
|
||||
data += val;
|
||||
dev->stats.tx_ok_bytes = max(data, dev->stats.tx_ok_bytes);
|
||||
|
||||
/* TX - 32-bit registers: accumulate delta to handle wrap-around. */
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_DROP_CNT(port->id));
|
||||
dev->stats.tx_drops += val;
|
||||
dev->stats.tx_drops += (u32)(val - dev->stats.mib_prev.tx_drops);
|
||||
dev->stats.mib_prev.tx_drops = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_BC_CNT(port->id));
|
||||
dev->stats.tx_broadcast += val;
|
||||
dev->stats.tx_broadcast += (u32)(val - dev->stats.mib_prev.tx_broadcast);
|
||||
dev->stats.mib_prev.tx_broadcast = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_MC_CNT(port->id));
|
||||
dev->stats.tx_multicast += val;
|
||||
dev->stats.tx_multicast += (u32)(val - dev->stats.mib_prev.tx_multicast);
|
||||
dev->stats.mib_prev.tx_multicast = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_RUNT_CNT(port->id));
|
||||
dev->stats.tx_len[i] += val;
|
||||
dev->stats.mib_prev.tx_runt64 +=
|
||||
(u32)(val - dev->stats.mib_prev.tx_runt);
|
||||
dev->stats.mib_prev.tx_runt = val;
|
||||
|
||||
/* tx_len[0]: RUNT (32-bit, delta) + E64 (64-bit, absolute). */
|
||||
data = dev->stats.mib_prev.tx_runt64;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_H(port->id));
|
||||
dev->stats.tx_len[i] += ((u64)val << 32);
|
||||
data += (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_L(port->id));
|
||||
dev->stats.tx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.tx_len[i] = max(data, dev->stats.tx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_H(port->id));
|
||||
dev->stats.tx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_L(port->id));
|
||||
dev->stats.tx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.tx_len[i] = max(data, dev->stats.tx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_H(port->id));
|
||||
dev->stats.tx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_L(port->id));
|
||||
dev->stats.tx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.tx_len[i] = max(data, dev->stats.tx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_H(port->id));
|
||||
dev->stats.tx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_L(port->id));
|
||||
dev->stats.tx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.tx_len[i] = max(data, dev->stats.tx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_H(port->id));
|
||||
dev->stats.tx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_L(port->id));
|
||||
dev->stats.tx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.tx_len[i] = max(data, dev->stats.tx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_H(port->id));
|
||||
dev->stats.tx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_L(port->id));
|
||||
dev->stats.tx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.tx_len[i] = max(data, dev->stats.tx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_LONG_CNT(port->id));
|
||||
dev->stats.tx_len[i++] += val;
|
||||
dev->stats.tx_len[i++] += (u32)(val - dev->stats.mib_prev.tx_long);
|
||||
dev->stats.mib_prev.tx_long = val;
|
||||
|
||||
/* RX */
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_H(port->id));
|
||||
dev->stats.rx_ok_pkts += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_L(port->id));
|
||||
dev->stats.rx_ok_pkts += val;
|
||||
data += val;
|
||||
dev->stats.rx_ok_pkts = max(data, dev->stats.rx_ok_pkts);
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_H(port->id));
|
||||
dev->stats.rx_ok_bytes += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_L(port->id));
|
||||
dev->stats.rx_ok_bytes += val;
|
||||
data += val;
|
||||
dev->stats.rx_ok_bytes = max(data, dev->stats.rx_ok_bytes);
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_DROP_CNT(port->id));
|
||||
dev->stats.rx_drops += val;
|
||||
dev->stats.rx_drops += (u32)(val - dev->stats.mib_prev.rx_drops);
|
||||
dev->stats.mib_prev.rx_drops = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_BC_CNT(port->id));
|
||||
dev->stats.rx_broadcast += val;
|
||||
dev->stats.rx_broadcast += (u32)(val - dev->stats.mib_prev.rx_broadcast);
|
||||
dev->stats.mib_prev.rx_broadcast = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_MC_CNT(port->id));
|
||||
dev->stats.rx_multicast += val;
|
||||
dev->stats.rx_multicast += (u32)(val - dev->stats.mib_prev.rx_multicast);
|
||||
dev->stats.mib_prev.rx_multicast = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ERROR_DROP_CNT(port->id));
|
||||
dev->stats.rx_errors += val;
|
||||
dev->stats.rx_errors += (u32)(val - dev->stats.mib_prev.rx_errors);
|
||||
dev->stats.mib_prev.rx_errors = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_CRC_ERR_CNT(port->id));
|
||||
dev->stats.rx_crc_error += val;
|
||||
dev->stats.rx_crc_error += (u32)(val - dev->stats.mib_prev.rx_crc_error);
|
||||
dev->stats.mib_prev.rx_crc_error = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_OVERFLOW_DROP_CNT(port->id));
|
||||
dev->stats.rx_over_errors += val;
|
||||
dev->stats.rx_over_errors += (u32)(val - dev->stats.mib_prev.rx_over_errors);
|
||||
dev->stats.mib_prev.rx_over_errors = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_FRAG_CNT(port->id));
|
||||
dev->stats.rx_fragment += val;
|
||||
dev->stats.rx_fragment += (u32)(val - dev->stats.mib_prev.rx_fragment);
|
||||
dev->stats.mib_prev.rx_fragment = val;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_JABBER_CNT(port->id));
|
||||
dev->stats.rx_jabber += val;
|
||||
dev->stats.rx_jabber += (u32)(val - dev->stats.mib_prev.rx_jabber);
|
||||
dev->stats.mib_prev.rx_jabber = val;
|
||||
|
||||
i = 0;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_RUNT_CNT(port->id));
|
||||
dev->stats.rx_len[i] += val;
|
||||
dev->stats.mib_prev.rx_runt64 +=
|
||||
(u32)(val - dev->stats.mib_prev.rx_runt);
|
||||
dev->stats.mib_prev.rx_runt = val;
|
||||
|
||||
/* rx_len[0]: RUNT (32-bit, delta) + E64 (64-bit, absolute). */
|
||||
data = dev->stats.mib_prev.rx_runt64;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_H(port->id));
|
||||
dev->stats.rx_len[i] += ((u64)val << 32);
|
||||
data += (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_L(port->id));
|
||||
dev->stats.rx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.rx_len[i] = max(data, dev->stats.rx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_H(port->id));
|
||||
dev->stats.rx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_L(port->id));
|
||||
dev->stats.rx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.rx_len[i] = max(data, dev->stats.rx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_H(port->id));
|
||||
dev->stats.rx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_L(port->id));
|
||||
dev->stats.rx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.rx_len[i] = max(data, dev->stats.rx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_H(port->id));
|
||||
dev->stats.rx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_L(port->id));
|
||||
dev->stats.rx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.rx_len[i] = max(data, dev->stats.rx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_H(port->id));
|
||||
dev->stats.rx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_L(port->id));
|
||||
dev->stats.rx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.rx_len[i] = max(data, dev->stats.rx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_H(port->id));
|
||||
dev->stats.rx_len[i] += ((u64)val << 32);
|
||||
data = (u64)val << 32;
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_L(port->id));
|
||||
dev->stats.rx_len[i++] += val;
|
||||
data += val;
|
||||
dev->stats.rx_len[i] = max(data, dev->stats.rx_len[i]);
|
||||
i++;
|
||||
|
||||
val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_LONG_CNT(port->id));
|
||||
dev->stats.rx_len[i++] += val;
|
||||
dev->stats.rx_len[i] += (u32)(val - dev->stats.mib_prev.rx_long);
|
||||
dev->stats.mib_prev.rx_long = val;
|
||||
|
||||
u64_stats_update_end(&dev->stats.syncp);
|
||||
}
|
||||
|
||||
static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = dev->port;
|
||||
int i;
|
||||
|
||||
spin_lock(&port->stats_lock);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(port->devs); i++) {
|
||||
if (port->devs[i])
|
||||
airoha_dev_get_hw_stats(port->devs[i]);
|
||||
}
|
||||
|
||||
/* Reset MIB counters */
|
||||
airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id),
|
||||
FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK);
|
||||
|
||||
spin_unlock(&port->stats_lock);
|
||||
}
|
||||
|
|
@ -2504,8 +2543,7 @@ static int airoha_tc_setup_qdisc_ets(struct net_device *dev,
|
|||
if (opt->parent == TC_H_ROOT)
|
||||
return -EINVAL;
|
||||
|
||||
channel = TC_H_MAJ(opt->handle) >> 16;
|
||||
channel = channel % AIROHA_NUM_QOS_CHANNELS;
|
||||
channel = TC_H_MIN(opt->parent) % AIROHA_NUM_QOS_CHANNELS;
|
||||
|
||||
switch (opt->command) {
|
||||
case TC_ETS_REPLACE:
|
||||
|
|
|
|||
|
|
@ -245,6 +245,33 @@ struct airoha_hw_stats {
|
|||
u64 rx_fragment;
|
||||
u64 rx_jabber;
|
||||
u64 rx_len[7];
|
||||
|
||||
struct {
|
||||
/* Previous HW register values for 32-bit counter delta
|
||||
* tracking. Storing the last seen value and accumulating
|
||||
* (u32)(curr - prev) into the 64-bit software counter
|
||||
* handles wrap-around transparently via unsigned arithmetic.
|
||||
* tx_runt64/rx_runt64 hold the running sum of runt deltas.
|
||||
* These fields are never reported to userspace.
|
||||
*/
|
||||
u32 tx_drops;
|
||||
u32 tx_broadcast;
|
||||
u32 tx_multicast;
|
||||
u32 tx_runt;
|
||||
u32 tx_long;
|
||||
u64 tx_runt64;
|
||||
u32 rx_drops;
|
||||
u32 rx_broadcast;
|
||||
u32 rx_multicast;
|
||||
u32 rx_errors;
|
||||
u32 rx_crc_error;
|
||||
u32 rx_over_errors;
|
||||
u32 rx_fragment;
|
||||
u32 rx_jabber;
|
||||
u32 rx_runt;
|
||||
u32 rx_long;
|
||||
u64 rx_runt64;
|
||||
} mib_prev;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id,
|
|||
dma_addr_t dma_addr;
|
||||
int ret;
|
||||
|
||||
dma_addr = dma_map_single(npu->dev, p, size, DMA_TO_DEVICE);
|
||||
dma_addr = dma_map_single(npu->dev, p, size, DMA_BIDIRECTIONAL);
|
||||
ret = dma_mapping_error(npu->dev, dma_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -191,7 +191,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id,
|
|||
|
||||
spin_unlock_bh(&npu->cores[core].lock);
|
||||
|
||||
dma_unmap_single(npu->dev, dma_addr, size, DMA_TO_DEVICE);
|
||||
dma_unmap_single(npu->dev, dma_addr, size, DMA_BIDIRECTIONAL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1659,6 +1659,7 @@ void airoha_ppe_deinit(struct airoha_eth *eth)
|
|||
npu = rcu_replace_pointer(eth->npu, NULL,
|
||||
lockdep_is_held(&flow_offload_mutex));
|
||||
if (npu) {
|
||||
synchronize_rcu();
|
||||
npu->ops.ppe_deinit(npu);
|
||||
airoha_npu_put(npu);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,13 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq)
|
|||
comp = cq_info->comp;
|
||||
eid = le64_to_cpu(comp->event.eid);
|
||||
while (eid > pdsc->last_eid) {
|
||||
u16 ecode = le16_to_cpu(comp->event.ecode);
|
||||
u16 ecode;
|
||||
|
||||
/* Order the payload read after the event id, the field the
|
||||
* driver uses to detect a new completion.
|
||||
*/
|
||||
dma_rmb();
|
||||
ecode = le16_to_cpu(comp->event.ecode);
|
||||
|
||||
switch (ecode) {
|
||||
case PDS_EVENT_LINK_CHANGE:
|
||||
|
|
@ -101,6 +107,10 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq)
|
|||
spin_lock_irqsave(&pdsc->adminq_lock, irqflags);
|
||||
comp = cq->info[cq->tail_idx].comp;
|
||||
while (pdsc_color_match(comp->color, cq->done_color)) {
|
||||
/* Order the payload reads after the color bit, the field the
|
||||
* driver uses to detect a new completion.
|
||||
*/
|
||||
dma_rmb();
|
||||
q_info = &q->info[q->tail_idx];
|
||||
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -177,17 +177,21 @@ void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf,
|
|||
{
|
||||
struct pds_auxiliary_dev *padev;
|
||||
|
||||
if (!*pd_ptr)
|
||||
return;
|
||||
|
||||
mutex_lock(&pf->config_lock);
|
||||
|
||||
/* A concurrent del may have already torn this device down and
|
||||
* cleared it.
|
||||
*/
|
||||
padev = *pd_ptr;
|
||||
if (!padev)
|
||||
goto out_unlock;
|
||||
|
||||
pds_client_unregister(pf, padev->client_id);
|
||||
auxiliary_device_delete(&padev->aux_dev);
|
||||
auxiliary_device_uninit(&padev->aux_dev);
|
||||
*pd_ptr = NULL;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&pf->config_lock);
|
||||
}
|
||||
|
||||
|
|
@ -210,6 +214,13 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf,
|
|||
|
||||
mutex_lock(&pf->config_lock);
|
||||
|
||||
/* Nothing to do if the aux device is already present. This also
|
||||
* guards against a second add overwriting *pd_ptr and leaking the
|
||||
* first, symmetric with the check in pdsc_auxbus_dev_del().
|
||||
*/
|
||||
if (*pd_ptr)
|
||||
goto out_unlock;
|
||||
|
||||
mask = BIT_ULL(PDSC_S_FW_DEAD) |
|
||||
BIT_ULL(PDSC_S_STOPPING_DRIVER);
|
||||
if (cf->state & mask) {
|
||||
|
|
|
|||
|
|
@ -110,7 +110,6 @@ static void pdsc_qcq_intr_free(struct pdsc *pdsc, struct pdsc_qcq *qcq)
|
|||
return;
|
||||
|
||||
pdsc_intr_free(pdsc, qcq->intx);
|
||||
qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED;
|
||||
}
|
||||
|
||||
static int pdsc_qcq_intr_alloc(struct pdsc *pdsc, struct pdsc_qcq *qcq)
|
||||
|
|
@ -145,6 +144,12 @@ void pdsc_qcq_free(struct pdsc *pdsc, struct pdsc_qcq *qcq)
|
|||
|
||||
pdsc_qcq_intr_free(pdsc, qcq);
|
||||
|
||||
/* Drain any work queued by ISR before it was freed above */
|
||||
if (qcq->work.func)
|
||||
cancel_work_sync(&qcq->work);
|
||||
|
||||
qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED;
|
||||
|
||||
if (qcq->q_base)
|
||||
dma_free_coherent(dev, qcq->q_size,
|
||||
qcq->q_base, qcq->q_base_pa);
|
||||
|
|
@ -304,8 +309,11 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index,
|
|||
|
||||
static void pdsc_core_uninit(struct pdsc *pdsc)
|
||||
{
|
||||
pdsc_qcq_free(pdsc, &pdsc->notifyqcq);
|
||||
/* Free adminqcq first: its work accesses notifyqcq, so we must
|
||||
* disable its IRQ and drain its work before freeing notifyqcq.
|
||||
*/
|
||||
pdsc_qcq_free(pdsc, &pdsc->adminqcq);
|
||||
pdsc_qcq_free(pdsc, &pdsc->notifyqcq);
|
||||
|
||||
if (pdsc->kern_dbpage) {
|
||||
iounmap(pdsc->kern_dbpage);
|
||||
|
|
@ -479,8 +487,6 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing)
|
|||
{
|
||||
if (!pdsc->pdev->is_virtfn)
|
||||
pdsc_devcmd_reset(pdsc);
|
||||
if (pdsc->adminqcq.work.func)
|
||||
cancel_work_sync(&pdsc->adminqcq.work);
|
||||
|
||||
pci_clear_master(pdsc->pdev);
|
||||
|
||||
|
|
@ -533,6 +539,7 @@ static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc)
|
|||
dev_dbg_ratelimited(pdsc->dev, "%s: adminq in use\n",
|
||||
__func__);
|
||||
cpu_relax();
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -606,9 +613,10 @@ void pdsc_pci_reset_thread(struct work_struct *work)
|
|||
struct pdsc *pdsc = container_of(work, struct pdsc, pci_reset_work);
|
||||
struct pci_dev *pdev = pdsc->pdev;
|
||||
|
||||
pci_dev_get(pdev);
|
||||
pci_reset_function(pdev);
|
||||
pci_dev_put(pdev);
|
||||
/* Use try variant to avoid deadlock with pdsc_remove().
|
||||
* If lock is contended, the watchdog timer will retry.
|
||||
*/
|
||||
pci_try_reset_function(pdev);
|
||||
}
|
||||
|
||||
static void pdsc_check_pci_health(struct pdsc *pdsc)
|
||||
|
|
|
|||
|
|
@ -90,6 +90,12 @@ int pdsc_dl_flash_update(struct devlink *dl,
|
|||
{
|
||||
struct pdsc *pdsc = devlink_priv(dl);
|
||||
|
||||
if (params->component) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Component update not supported by this device");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return pdsc_firmware_update(pdsc, params->fw, extack);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -238,6 +238,10 @@ static int pdsc_init_pf(struct pdsc *pdsc)
|
|||
/* General workqueue and timer, but don't start timer yet */
|
||||
snprintf(wq_name, sizeof(wq_name), "%s.%d", PDS_CORE_DRV_NAME, pdsc->uid);
|
||||
pdsc->wq = create_singlethread_workqueue(wq_name);
|
||||
if (!pdsc->wq) {
|
||||
err = -ENOMEM;
|
||||
goto err_out_unmap_bars;
|
||||
}
|
||||
INIT_WORK(&pdsc->health_work, pdsc_health_thread);
|
||||
INIT_WORK(&pdsc->pci_reset_work, pdsc_pci_reset_thread);
|
||||
timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
|
||||
|
|
@ -253,7 +257,7 @@ static int pdsc_init_pf(struct pdsc *pdsc)
|
|||
err = pdsc_setup(pdsc, PDSC_SETUP_INIT);
|
||||
if (err) {
|
||||
mutex_unlock(&pdsc->config_lock);
|
||||
goto err_out_unmap_bars;
|
||||
goto err_out_shutdown_timer;
|
||||
}
|
||||
|
||||
err = pdsc_start(pdsc);
|
||||
|
|
@ -305,13 +309,14 @@ static int pdsc_init_pf(struct pdsc *pdsc)
|
|||
pdsc_stop(pdsc);
|
||||
err_out_teardown:
|
||||
pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING);
|
||||
err_out_unmap_bars:
|
||||
err_out_shutdown_timer:
|
||||
timer_shutdown_sync(&pdsc->wdtimer);
|
||||
if (pdsc->wq)
|
||||
destroy_workqueue(pdsc->wq);
|
||||
mutex_destroy(&pdsc->config_lock);
|
||||
mutex_destroy(&pdsc->devcmd_lock);
|
||||
pci_free_irq_vectors(pdsc->pdev);
|
||||
err_out_unmap_bars:
|
||||
pdsc_unmap_bars(pdsc);
|
||||
err_out_release_regions:
|
||||
pci_release_regions(pdsc->pdev);
|
||||
|
|
@ -435,8 +440,6 @@ static void pdsc_remove(struct pci_dev *pdev)
|
|||
pdsc_auxbus_dev_del(pdsc, pdsc, &pdsc->padev);
|
||||
|
||||
timer_shutdown_sync(&pdsc->wdtimer);
|
||||
if (pdsc->wq)
|
||||
destroy_workqueue(pdsc->wq);
|
||||
|
||||
mutex_lock(&pdsc->config_lock);
|
||||
set_bit(PDSC_S_STOPPING_DRIVER, &pdsc->state);
|
||||
|
|
@ -444,6 +447,9 @@ static void pdsc_remove(struct pci_dev *pdev)
|
|||
pdsc_stop(pdsc);
|
||||
pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING);
|
||||
mutex_unlock(&pdsc->config_lock);
|
||||
|
||||
if (pdsc->wq)
|
||||
destroy_workqueue(pdsc->wq);
|
||||
mutex_destroy(&pdsc->config_lock);
|
||||
mutex_destroy(&pdsc->devcmd_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -267,9 +267,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable,
|
|||
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg);
|
||||
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL);
|
||||
reg |= XGBE_VEND2_MAC_AUTO_SW;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg);
|
||||
if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) {
|
||||
reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL);
|
||||
if (enable)
|
||||
reg |= XGBE_VEND2_MAC_AUTO_SW;
|
||||
else
|
||||
reg &= ~XGBE_VEND2_MAC_AUTO_SW;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg);
|
||||
}
|
||||
}
|
||||
|
||||
static void xgbe_an37_restart(struct xgbe_prv_data *pdata)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ struct bnge_pf_info {
|
|||
};
|
||||
|
||||
#define INVALID_HW_RING_ID ((u16)-1)
|
||||
#define INVALID_HW_RING_ID_32BIT (U32_MAX)
|
||||
|
||||
enum {
|
||||
BNGE_FW_CAP_SHORT_CMD = BIT_ULL(0),
|
||||
|
|
|
|||
|
|
@ -1283,7 +1283,7 @@ int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn)
|
|||
|
||||
int hwrm_ring_free_send_msg(struct bnge_net *bn,
|
||||
struct bnge_ring_struct *ring,
|
||||
u32 ring_type, int cmpl_ring_id)
|
||||
u32 ring_type, u32 cmpl_ring_id)
|
||||
{
|
||||
struct hwrm_ring_free_input *req;
|
||||
struct bnge_dev *bd = bn->bd;
|
||||
|
|
@ -1295,7 +1295,7 @@ int hwrm_ring_free_send_msg(struct bnge_net *bn,
|
|||
|
||||
req->cmpl_ring = cpu_to_le16(cmpl_ring_id);
|
||||
req->ring_type = ring_type;
|
||||
req->ring_id = cpu_to_le16(ring->fw_ring_id);
|
||||
req->ring_id = cpu_to_le32(ring->fw_ring_id);
|
||||
|
||||
bnge_hwrm_req_hold(bd, req);
|
||||
rc = bnge_hwrm_req_send(bd, req);
|
||||
|
|
@ -1317,7 +1317,7 @@ int hwrm_ring_alloc_send_msg(struct bnge_net *bn,
|
|||
struct hwrm_ring_alloc_output *resp;
|
||||
struct hwrm_ring_alloc_input *req;
|
||||
struct bnge_dev *bd = bn->bd;
|
||||
u16 ring_id, flags = 0;
|
||||
u32 ring_id, flags = 0;
|
||||
int rc;
|
||||
|
||||
rc = bnge_hwrm_req_init(bd, req, HWRM_RING_ALLOC);
|
||||
|
|
@ -1401,7 +1401,7 @@ int hwrm_ring_alloc_send_msg(struct bnge_net *bn,
|
|||
|
||||
resp = bnge_hwrm_req_hold(bd, req);
|
||||
rc = bnge_hwrm_req_send(bd, req);
|
||||
ring_id = le16_to_cpu(resp->ring_id);
|
||||
ring_id = le32_to_cpu(resp->ring_id);
|
||||
bnge_hwrm_req_drop(bd, req);
|
||||
|
||||
exit:
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ int bnge_hwrm_cfa_l2_set_rx_mask(struct bnge_dev *bd,
|
|||
void bnge_hwrm_stat_ctx_free(struct bnge_net *bn);
|
||||
int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn);
|
||||
int hwrm_ring_free_send_msg(struct bnge_net *bn, struct bnge_ring_struct *ring,
|
||||
u32 ring_type, int cmpl_ring_id);
|
||||
u32 ring_type, u32 cmpl_ring_id);
|
||||
int hwrm_ring_alloc_send_msg(struct bnge_net *bn,
|
||||
struct bnge_ring_struct *ring,
|
||||
u32 ring_type, u32 map_index);
|
||||
|
|
|
|||
|
|
@ -1327,12 +1327,12 @@ static int bnge_alloc_core(struct bnge_net *bn)
|
|||
return rc;
|
||||
}
|
||||
|
||||
u16 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr)
|
||||
u32 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr)
|
||||
{
|
||||
return rxr->rx_cpr->ring_struct.fw_ring_id;
|
||||
}
|
||||
|
||||
u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr)
|
||||
u32 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr)
|
||||
{
|
||||
return txr->tx_cpr->ring_struct.fw_ring_id;
|
||||
}
|
||||
|
|
@ -1375,12 +1375,12 @@ static void bnge_init_nq_tree(struct bnge_net *bn)
|
|||
struct bnge_nq_ring_info *nqr = &bn->bnapi[i]->nq_ring;
|
||||
struct bnge_ring_struct *ring = &nqr->ring_struct;
|
||||
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
for (j = 0; j < nqr->cp_ring_count; j++) {
|
||||
struct bnge_cp_ring_info *cpr = &nqr->cp_ring_arr[j];
|
||||
|
||||
ring = &cpr->ring_struct;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1637,7 +1637,7 @@ static void bnge_init_one_rx_ring_rxbd(struct bnge_net *bn,
|
|||
|
||||
ring = &rxr->rx_ring_struct;
|
||||
bnge_init_rxbd_pages(ring, type);
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
}
|
||||
|
||||
static void bnge_init_one_agg_ring_rxbd(struct bnge_net *bn,
|
||||
|
|
@ -1647,7 +1647,7 @@ static void bnge_init_one_agg_ring_rxbd(struct bnge_net *bn,
|
|||
u32 type;
|
||||
|
||||
ring = &rxr->rx_agg_ring_struct;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
if (bnge_is_agg_reqd(bn->bd)) {
|
||||
type = ((u32)BNGE_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
|
||||
RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP;
|
||||
|
|
@ -1708,7 +1708,7 @@ static void bnge_init_tx_rings(struct bnge_net *bn)
|
|||
struct bnge_tx_ring_info *txr = &bn->tx_ring[i];
|
||||
struct bnge_ring_struct *ring = &txr->tx_ring_struct;
|
||||
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
|
||||
netif_queue_set_napi(bn->netdev, i, NETDEV_QUEUE_TYPE_TX,
|
||||
&txr->bnapi->napi);
|
||||
|
|
@ -1867,7 +1867,7 @@ static int bnge_hwrm_rx_agg_ring_alloc(struct bnge_net *bn,
|
|||
ring->fw_ring_id);
|
||||
bnge_db_write(bn->bd, &rxr->rx_agg_db, rxr->rx_agg_prod);
|
||||
bnge_db_write(bn->bd, &rxr->rx_db, rxr->rx_prod);
|
||||
bn->grp_info[grp_idx].agg_fw_ring_id = ring->fw_ring_id;
|
||||
bn->grp_info[grp_idx].agg_fw_ring_id = (u16)ring->fw_ring_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1886,7 +1886,7 @@ static int bnge_hwrm_rx_ring_alloc(struct bnge_net *bn,
|
|||
return rc;
|
||||
|
||||
bnge_set_db(bn, &rxr->rx_db, type, map_idx, ring->fw_ring_id);
|
||||
bn->grp_info[map_idx].rx_fw_ring_id = ring->fw_ring_id;
|
||||
bn->grp_info[map_idx].rx_fw_ring_id = (u16)ring->fw_ring_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1916,7 +1916,7 @@ static int bnge_hwrm_ring_alloc(struct bnge_net *bn)
|
|||
bnge_set_db(bn, &nqr->nq_db, type, map_idx, ring->fw_ring_id);
|
||||
bnge_db_nq(bn, &nqr->nq_db, nqr->nq_raw_cons);
|
||||
enable_irq(vector);
|
||||
bn->grp_info[i].nq_fw_ring_id = ring->fw_ring_id;
|
||||
bn->grp_info[i].nq_fw_ring_id = (u16)ring->fw_ring_id;
|
||||
|
||||
if (!i) {
|
||||
rc = bnge_hwrm_set_async_event_cr(bd, ring->fw_ring_id);
|
||||
|
|
@ -1986,15 +1986,13 @@ void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic)
|
|||
tbl_size = bnge_get_rxfh_indir_size(bd);
|
||||
|
||||
for (i = 0; i < tbl_size; i++) {
|
||||
u16 ring_id, j;
|
||||
u32 j;
|
||||
|
||||
j = bd->rss_indir_tbl[i];
|
||||
rxr = &bn->rx_ring[j];
|
||||
|
||||
ring_id = rxr->rx_ring_struct.fw_ring_id;
|
||||
*ring_tbl++ = cpu_to_le16(ring_id);
|
||||
ring_id = bnge_cp_ring_for_rx(rxr);
|
||||
*ring_tbl++ = cpu_to_le16(ring_id);
|
||||
*ring_tbl++ = cpu_to_le16(rxr->rx_ring_struct.fw_ring_id);
|
||||
*ring_tbl++ = cpu_to_le16(bnge_cp_ring_for_rx(rxr));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2285,7 +2283,7 @@ static void bnge_disable_int(struct bnge_net *bn)
|
|||
nqr = &bnapi->nq_ring;
|
||||
ring = &nqr->ring_struct;
|
||||
|
||||
if (ring->fw_ring_id != INVALID_HW_RING_ID)
|
||||
if (ring->fw_ring_id != INVALID_HW_RING_ID_32BIT)
|
||||
bnge_db_nq(bn, &nqr->nq_db, nqr->nq_raw_cons);
|
||||
}
|
||||
}
|
||||
|
|
@ -2401,7 +2399,7 @@ static void bnge_hwrm_rx_ring_free(struct bnge_net *bn,
|
|||
u32 grp_idx = rxr->bnapi->index;
|
||||
u32 cmpl_ring_id;
|
||||
|
||||
if (ring->fw_ring_id == INVALID_HW_RING_ID)
|
||||
if (ring->fw_ring_id == INVALID_HW_RING_ID_32BIT)
|
||||
return;
|
||||
|
||||
cmpl_ring_id = bnge_cp_ring_for_rx(rxr);
|
||||
|
|
@ -2409,7 +2407,7 @@ static void bnge_hwrm_rx_ring_free(struct bnge_net *bn,
|
|||
RING_FREE_REQ_RING_TYPE_RX,
|
||||
close_path ? cmpl_ring_id :
|
||||
INVALID_HW_RING_ID);
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
bn->grp_info[grp_idx].rx_fw_ring_id = INVALID_HW_RING_ID;
|
||||
}
|
||||
|
||||
|
|
@ -2421,14 +2419,14 @@ static void bnge_hwrm_rx_agg_ring_free(struct bnge_net *bn,
|
|||
u32 grp_idx = rxr->bnapi->index;
|
||||
u32 cmpl_ring_id;
|
||||
|
||||
if (ring->fw_ring_id == INVALID_HW_RING_ID)
|
||||
if (ring->fw_ring_id == INVALID_HW_RING_ID_32BIT)
|
||||
return;
|
||||
|
||||
cmpl_ring_id = bnge_cp_ring_for_rx(rxr);
|
||||
hwrm_ring_free_send_msg(bn, ring, RING_FREE_REQ_RING_TYPE_RX_AGG,
|
||||
close_path ? cmpl_ring_id :
|
||||
INVALID_HW_RING_ID);
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
bn->grp_info[grp_idx].agg_fw_ring_id = INVALID_HW_RING_ID;
|
||||
}
|
||||
|
||||
|
|
@ -2439,14 +2437,14 @@ static void bnge_hwrm_tx_ring_free(struct bnge_net *bn,
|
|||
struct bnge_ring_struct *ring = &txr->tx_ring_struct;
|
||||
u32 cmpl_ring_id;
|
||||
|
||||
if (ring->fw_ring_id == INVALID_HW_RING_ID)
|
||||
if (ring->fw_ring_id == INVALID_HW_RING_ID_32BIT)
|
||||
return;
|
||||
|
||||
cmpl_ring_id = close_path ? bnge_cp_ring_for_tx(txr) :
|
||||
INVALID_HW_RING_ID;
|
||||
hwrm_ring_free_send_msg(bn, ring, RING_FREE_REQ_RING_TYPE_TX,
|
||||
cmpl_ring_id);
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
}
|
||||
|
||||
static void bnge_hwrm_cp_ring_free(struct bnge_net *bn,
|
||||
|
|
@ -2455,12 +2453,12 @@ static void bnge_hwrm_cp_ring_free(struct bnge_net *bn,
|
|||
struct bnge_ring_struct *ring;
|
||||
|
||||
ring = &cpr->ring_struct;
|
||||
if (ring->fw_ring_id == INVALID_HW_RING_ID)
|
||||
if (ring->fw_ring_id == INVALID_HW_RING_ID_32BIT)
|
||||
return;
|
||||
|
||||
hwrm_ring_free_send_msg(bn, ring, RING_FREE_REQ_RING_TYPE_L2_CMPL,
|
||||
INVALID_HW_RING_ID);
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
}
|
||||
|
||||
static void bnge_hwrm_ring_free(struct bnge_net *bn, bool close_path)
|
||||
|
|
@ -2496,11 +2494,11 @@ static void bnge_hwrm_ring_free(struct bnge_net *bn, bool close_path)
|
|||
bnge_hwrm_cp_ring_free(bn, &nqr->cp_ring_arr[j]);
|
||||
|
||||
ring = &nqr->ring_struct;
|
||||
if (ring->fw_ring_id != INVALID_HW_RING_ID) {
|
||||
if (ring->fw_ring_id != INVALID_HW_RING_ID_32BIT) {
|
||||
hwrm_ring_free_send_msg(bn, ring,
|
||||
RING_FREE_REQ_RING_TYPE_NQ,
|
||||
INVALID_HW_RING_ID);
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID;
|
||||
ring->fw_ring_id = INVALID_HW_RING_ID_32BIT;
|
||||
bn->grp_info[i].nq_fw_ring_id = INVALID_HW_RING_ID;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -630,8 +630,8 @@ struct bnge_l2_filter {
|
|||
refcount_t refcnt;
|
||||
};
|
||||
|
||||
u16 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr);
|
||||
u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr);
|
||||
u32 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr);
|
||||
u32 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr);
|
||||
void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic);
|
||||
int bnge_alloc_rx_data(struct bnge_net *bn, struct bnge_rx_ring_info *rxr,
|
||||
u16 prod, gfp_t gfp);
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ struct bnge_ctx_mem_info {
|
|||
struct bnge_ring_struct {
|
||||
struct bnge_ring_mem_info ring_mem;
|
||||
|
||||
u16 fw_ring_id;
|
||||
u32 fw_ring_id;
|
||||
union {
|
||||
u16 grp_idx;
|
||||
u16 map_idx; /* Used by NQs */
|
||||
|
|
|
|||
|
|
@ -4732,6 +4732,7 @@ static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv)
|
|||
dpaa2_mac_disconnect(mac);
|
||||
|
||||
dpaa2_mac_close(mac);
|
||||
put_device(&mac->mc_dev->dev);
|
||||
kfree(mac);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1560,6 +1560,7 @@ static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv)
|
|||
dpaa2_mac_disconnect(mac);
|
||||
|
||||
dpaa2_mac_close(mac);
|
||||
put_device(&mac->mc_dev->dev);
|
||||
kfree(mac);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -900,22 +900,28 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode,
|
|||
{
|
||||
struct mac_device *mac_dev = fman_config_to_mac(config);
|
||||
struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs;
|
||||
u32 tmp;
|
||||
u32 ecntrl, maccfg2;
|
||||
|
||||
maccfg2 = ioread32be(®s->maccfg2);
|
||||
maccfg2 &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE);
|
||||
|
||||
switch (state->interface) {
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
tmp = DTSEC_ECNTRL_RMM;
|
||||
ecntrl = DTSEC_ECNTRL_RMM;
|
||||
maccfg2 |= MACCFG2_NIBBLE_MODE;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM;
|
||||
ecntrl = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM;
|
||||
maccfg2 |= MACCFG2_BYTE_MODE;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM;
|
||||
ecntrl = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM;
|
||||
maccfg2 |= MACCFG2_BYTE_MODE;
|
||||
break;
|
||||
default:
|
||||
dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n",
|
||||
|
|
@ -923,7 +929,8 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode,
|
|||
return;
|
||||
}
|
||||
|
||||
iowrite32be(tmp, ®s->ecntrl);
|
||||
iowrite32be(ecntrl, ®s->ecntrl);
|
||||
iowrite32be(maccfg2, ®s->maccfg2);
|
||||
}
|
||||
|
||||
static void dtsec_link_up(struct phylink_config *config, struct phy_device *phy,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/u64_stats_sync.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
|
|
@ -41,6 +42,7 @@
|
|||
|
||||
/* Interval to schedule a stats report update, 20000ms. */
|
||||
#define GVE_STATS_REPORT_TIMER_PERIOD 20000
|
||||
#define GVE_RX_NAPI_RESCHED_MS 20 /* msecs */
|
||||
|
||||
/* Numbers of NIC tx/rx stats in stats report. */
|
||||
#define NIC_TX_STATS_REPORT_NUM 0
|
||||
|
|
@ -341,6 +343,7 @@ struct gve_rx_ring {
|
|||
struct xdp_rxq_info xdp_rxq;
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
struct page_frag_cache page_cache; /* Page cache to allocate XDP frames */
|
||||
struct timer_list starvation_timer; /* for queue starvation recovery */
|
||||
};
|
||||
|
||||
/* A TX desc ring entry */
|
||||
|
|
|
|||
|
|
@ -18,6 +18,16 @@
|
|||
#include <net/tcp.h>
|
||||
#include <net/xdp_sock_drv.h>
|
||||
|
||||
static void gve_rx_starvation_timer(struct timer_list *t)
|
||||
{
|
||||
struct gve_rx_ring *rx = timer_container_of(rx, t, starvation_timer);
|
||||
struct gve_priv *priv = rx->gve;
|
||||
struct gve_notify_block *block;
|
||||
|
||||
block = &priv->ntfy_blocks[rx->ntfy_id];
|
||||
napi_schedule(&block->napi);
|
||||
}
|
||||
|
||||
static void gve_rx_free_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx)
|
||||
{
|
||||
struct device *hdev = &priv->pdev->dev;
|
||||
|
|
@ -120,6 +130,7 @@ void gve_rx_stop_ring_dqo(struct gve_priv *priv, int idx)
|
|||
|
||||
if (rx->dqo.page_pool)
|
||||
page_pool_disable_direct_recycling(rx->dqo.page_pool);
|
||||
timer_shutdown_sync(&rx->starvation_timer);
|
||||
gve_remove_napi(priv, ntfy_idx);
|
||||
gve_rx_remove_from_block(priv, idx);
|
||||
gve_rx_reset_ring_dqo(priv, idx);
|
||||
|
|
@ -208,8 +219,10 @@ static int gve_rx_alloc_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx,
|
|||
void gve_rx_start_ring_dqo(struct gve_priv *priv, int idx)
|
||||
{
|
||||
int ntfy_idx = gve_rx_idx_to_ntfy(priv, idx);
|
||||
struct gve_rx_ring *rx = &priv->rx[idx];
|
||||
|
||||
gve_rx_add_to_block(priv, idx);
|
||||
timer_setup(&rx->starvation_timer, gve_rx_starvation_timer, 0);
|
||||
gve_add_napi(priv, ntfy_idx, gve_napi_poll_dqo);
|
||||
}
|
||||
|
||||
|
|
@ -365,6 +378,7 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
|
|||
struct gve_rx_compl_queue_dqo *complq = &rx->dqo.complq;
|
||||
struct gve_rx_buf_queue_dqo *bufq = &rx->dqo.bufq;
|
||||
struct gve_priv *priv = rx->gve;
|
||||
u32 num_bufs_avail_to_hw;
|
||||
u32 num_avail_slots;
|
||||
u32 num_full_slots;
|
||||
u32 num_posted = 0;
|
||||
|
|
@ -400,6 +414,26 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
|
|||
}
|
||||
|
||||
rx->fill_cnt += num_posted;
|
||||
|
||||
/* If the queue has fewer than GVE_RX_BUF_THRESH_DQO descriptors
|
||||
* visible to the hardware, the hardware is in danger of starving
|
||||
* and cannot trigger interrupts.
|
||||
*
|
||||
* We use a threshold of 32 because a single maximum-sized RSC
|
||||
* packet can consume up to 19 descriptors in the Rx path. Lower
|
||||
* thresholds (e.g., 8 or 16) would be unsafe as they could cause
|
||||
* the device to drop/stall on a maximum-sized RSC packet.
|
||||
*
|
||||
* Start the timer to periodically reschedule NAPI and recover.
|
||||
*/
|
||||
num_bufs_avail_to_hw =
|
||||
((bufq->tail & ~(GVE_RX_BUF_THRESH_DQO - 1)) -
|
||||
bufq->head) & bufq->mask;
|
||||
|
||||
if (num_bufs_avail_to_hw < GVE_RX_BUF_THRESH_DQO) {
|
||||
mod_timer(&rx->starvation_timer,
|
||||
jiffies + msecs_to_jiffies(GVE_RX_NAPI_RESCHED_MS));
|
||||
}
|
||||
}
|
||||
|
||||
static void gve_rx_skb_csum(struct sk_buff *skb,
|
||||
|
|
|
|||
|
|
@ -594,7 +594,11 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
|
|||
skb = build_skb(buf, priv->rx_buf_size);
|
||||
if (unlikely(!skb)) {
|
||||
net_dbg_ratelimited("build_skb failed\n");
|
||||
goto refill;
|
||||
/* Retain the slot; return budget so NAPI retries this
|
||||
* buffer. Refill would overwrite rx_buf[]/rx_phys[]
|
||||
* and leak them.
|
||||
*/
|
||||
return budget;
|
||||
}
|
||||
|
||||
dma_unmap_single(priv->dev, priv->rx_phys[priv->rx_head],
|
||||
|
|
@ -622,14 +626,15 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
|
|||
rx++;
|
||||
}
|
||||
|
||||
refill:
|
||||
buf = netdev_alloc_frag(priv->rx_buf_size);
|
||||
if (!buf)
|
||||
goto done;
|
||||
phys = dma_map_single(priv->dev, buf,
|
||||
RX_BUF_SIZE, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(priv->dev, phys))
|
||||
if (dma_mapping_error(priv->dev, phys)) {
|
||||
skb_free_frag(buf);
|
||||
goto done;
|
||||
}
|
||||
priv->rx_buf[priv->rx_head] = buf;
|
||||
priv->rx_phys[priv->rx_head] = phys;
|
||||
hip04_set_recv_desc(priv, phys);
|
||||
|
|
|
|||
|
|
@ -104,8 +104,6 @@ struct hinic_dev {
|
|||
u16 num_rss;
|
||||
u16 rss_limit;
|
||||
struct hinic_rss_type rss_type;
|
||||
u8 *rss_hkey_user;
|
||||
s32 *rss_indir_user;
|
||||
struct hinic_intr_coal_info *rx_intr_coalesce;
|
||||
struct hinic_intr_coal_info *tx_intr_coalesce;
|
||||
struct hinic_sriov_info sriov_info;
|
||||
|
|
|
|||
|
|
@ -1064,17 +1064,6 @@ static int __set_rss_rxfh(struct net_device *netdev,
|
|||
int err;
|
||||
|
||||
if (indir) {
|
||||
if (!nic_dev->rss_indir_user) {
|
||||
nic_dev->rss_indir_user =
|
||||
kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (!nic_dev->rss_indir_user)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(nic_dev->rss_indir_user, indir,
|
||||
sizeof(u32) * HINIC_RSS_INDIR_SIZE);
|
||||
|
||||
err = hinic_rss_set_indir_tbl(nic_dev,
|
||||
nic_dev->rss_tmpl_idx, indir);
|
||||
if (err)
|
||||
|
|
@ -1082,16 +1071,6 @@ static int __set_rss_rxfh(struct net_device *netdev,
|
|||
}
|
||||
|
||||
if (key) {
|
||||
if (!nic_dev->rss_hkey_user) {
|
||||
nic_dev->rss_hkey_user =
|
||||
kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL);
|
||||
|
||||
if (!nic_dev->rss_hkey_user)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE);
|
||||
|
||||
err = hinic_rss_set_template_tbl(nic_dev,
|
||||
nic_dev->rss_tmpl_idx, key);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -767,6 +767,9 @@ static inline bool ice_is_txtime_ena(const struct ice_tx_ring *ring)
|
|||
struct ice_vsi *vsi = ring->vsi;
|
||||
struct ice_pf *pf = vsi->back;
|
||||
|
||||
if (vsi->type != ICE_VSI_PF)
|
||||
return false;
|
||||
|
||||
return test_bit(ring->q_index, pf->txtime_txqs);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -512,9 +512,6 @@ int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf)
|
|||
struct ice_repr *repr;
|
||||
int err;
|
||||
|
||||
if (!ice_is_eswitch_mode_switchdev(pf))
|
||||
return 0;
|
||||
|
||||
repr = ice_repr_create_vf(vf);
|
||||
if (IS_ERR(repr))
|
||||
return PTR_ERR(repr);
|
||||
|
|
|
|||
|
|
@ -2623,7 +2623,7 @@ int ice_init_lag(struct ice_pf *pf)
|
|||
goto free_lport_res;
|
||||
|
||||
/* associate recipes to profiles */
|
||||
for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) {
|
||||
for (n = 0; n < ICE_MAX_NUM_PROFILES; n++) {
|
||||
err = ice_aq_get_recipe_to_profile(&pf->hw, n,
|
||||
&recipe_bits, NULL);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -2368,6 +2368,9 @@ int ice_parser_profile_init(struct ice_parser_result *rslt,
|
|||
u16 proto_off = 0;
|
||||
u16 off;
|
||||
|
||||
if (rslt->ptype >= ICE_FLOW_PTYPE_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
memset(prof, 0, sizeof(*prof));
|
||||
set_bit(rslt->ptype, prof->ptypes);
|
||||
if (blk == ICE_BLK_SW) {
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ static u64 ice_ptp_extend_40b_ts(struct ice_pf *pf, u64 in_tstamp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
return ice_ptp_extend_32b_ts(pf->ptp.cached_phc_time,
|
||||
return ice_ptp_extend_32b_ts(READ_ONCE(pf->ptp.cached_phc_time),
|
||||
(in_tstamp >> 8) & mask);
|
||||
}
|
||||
|
||||
|
|
@ -3037,6 +3037,11 @@ void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
|
|||
struct ice_ptp *ptp = &pf->ptp;
|
||||
int err;
|
||||
|
||||
if (ptp->state == ICE_PTP_UNINIT) {
|
||||
dev_dbg(ice_pf_to_dev(pf), "PTP was not initialized, skipping rebuild\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptp->state == ICE_PTP_READY) {
|
||||
ice_ptp_prepare_for_reset(pf, reset_type);
|
||||
} else if (ptp->state != ICE_PTP_RESETTING) {
|
||||
|
|
|
|||
|
|
@ -484,12 +484,14 @@ static int ice_start_vfs(struct ice_pf *pf)
|
|||
goto teardown;
|
||||
}
|
||||
|
||||
retval = ice_eswitch_attach_vf(pf, vf);
|
||||
if (retval) {
|
||||
dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d",
|
||||
vf->vf_id, retval);
|
||||
ice_vf_vsi_release(vf);
|
||||
goto teardown;
|
||||
if (ice_is_eswitch_mode_switchdev(pf)) {
|
||||
retval = ice_eswitch_attach_vf(pf, vf);
|
||||
if (retval) {
|
||||
dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d",
|
||||
vf->vf_id, retval);
|
||||
ice_vf_vsi_release(vf);
|
||||
goto teardown;
|
||||
}
|
||||
}
|
||||
|
||||
set_bit(ICE_VF_STATE_INIT, vf->vf_states);
|
||||
|
|
|
|||
|
|
@ -1654,7 +1654,7 @@ int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off)
|
|||
ret = ipv6_skip_exthdr(skb, exthdr - skb->data,
|
||||
&l4_proto, &frag_off);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
goto checksum_sw_fb;
|
||||
}
|
||||
|
||||
/* define outer transport */
|
||||
|
|
@ -1673,11 +1673,7 @@ int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off)
|
|||
l4.hdr = skb_inner_network_header(skb);
|
||||
break;
|
||||
default:
|
||||
if (first->tx_flags & ICE_TX_FLAGS_TSO)
|
||||
return -1;
|
||||
|
||||
skb_checksum_help(skb);
|
||||
return 0;
|
||||
goto checksum_sw_fb;
|
||||
}
|
||||
|
||||
/* compute outer L3 header size */
|
||||
|
|
@ -1736,7 +1732,7 @@ int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off)
|
|||
ipv6_skip_exthdr(skb, exthdr - skb->data, &l4_proto,
|
||||
&frag_off);
|
||||
} else {
|
||||
return -1;
|
||||
goto checksum_sw_fb;
|
||||
}
|
||||
|
||||
/* compute inner L3 header size */
|
||||
|
|
@ -1789,15 +1785,17 @@ int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off)
|
|||
break;
|
||||
|
||||
default:
|
||||
if (first->tx_flags & ICE_TX_FLAGS_TSO)
|
||||
return -1;
|
||||
skb_checksum_help(skb);
|
||||
return 0;
|
||||
goto checksum_sw_fb;
|
||||
}
|
||||
|
||||
off->td_cmd |= cmd;
|
||||
off->td_offset |= offset;
|
||||
return 1;
|
||||
|
||||
checksum_sw_fb:
|
||||
if (first->tx_flags & ICE_TX_FLAGS_TSO)
|
||||
return -1;
|
||||
return skb_checksum_help(skb);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -812,7 +812,8 @@ void ice_reset_all_vfs(struct ice_pf *pf)
|
|||
}
|
||||
ice_vf_post_vsi_rebuild(vf);
|
||||
|
||||
ice_eswitch_attach_vf(pf, vf);
|
||||
if (ice_is_eswitch_mode_switchdev(pf))
|
||||
ice_eswitch_attach_vf(pf, vf);
|
||||
|
||||
mutex_unlock(&vf->cfg_lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3555,7 +3555,6 @@ int idpf_vc_core_init(struct idpf_adapter *adapter)
|
|||
|
||||
pci_sriov_set_totalvfs(adapter->pdev, idpf_get_max_vfs(adapter));
|
||||
num_max_vports = idpf_get_max_vports(adapter);
|
||||
adapter->max_vports = num_max_vports;
|
||||
adapter->vports = kzalloc_objs(*adapter->vports, num_max_vports);
|
||||
if (!adapter->vports)
|
||||
return -ENOMEM;
|
||||
|
|
@ -3576,6 +3575,12 @@ int idpf_vc_core_init(struct idpf_adapter *adapter)
|
|||
goto err_netdev_alloc;
|
||||
}
|
||||
|
||||
/* Set max_vports only after vports, netdevs and vport_config buffers
|
||||
* are allocated to make sure max_vport bound loops don't end up
|
||||
* crashing, following allocation errors on init.
|
||||
*/
|
||||
adapter->max_vports = num_max_vports;
|
||||
|
||||
/* Start the mailbox task before requesting vectors. This will ensure
|
||||
* vector information response from mailbox is handled
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
|
|||
if (allocated) {
|
||||
pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
|
||||
pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
|
||||
pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT;
|
||||
}
|
||||
|
||||
if (allocated != count)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4)
|
||||
|
||||
#define MCAST_INVALID_GRP (-1U)
|
||||
#define RATE_MANTISSA_BITS 8
|
||||
|
||||
static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst,
|
||||
u32 *burst_exp, u32 *burst_mantissa)
|
||||
|
|
@ -66,28 +67,30 @@ static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst,
|
|||
static void otx2_get_egress_rate_cfg(u64 maxrate, u32 *exp,
|
||||
u32 *mantissa, u32 *div_exp)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
/* Rate calculation by hardware
|
||||
*
|
||||
* PIR_ADD = ((256 + mantissa) << exp) / 256
|
||||
* rate = (2 * PIR_ADD) / ( 1 << div_exp)
|
||||
* The resultant rate is in Mbps.
|
||||
*
|
||||
* Use div_exp = 0 and compute exp/mantissa for maxrate / 2; the
|
||||
* leading factor of two yields the full rate. Rates below 2 Mbps
|
||||
* are floored to the smallest step (exp = 0, mantissa = 0).
|
||||
*/
|
||||
|
||||
/* 2Mbps to 100Gbps can be expressed with div_exp = 0.
|
||||
* Setting this to '0' will ease the calculation of
|
||||
* exponent and mantissa.
|
||||
*/
|
||||
*div_exp = 0;
|
||||
|
||||
if (maxrate) {
|
||||
*exp = ilog2(maxrate) ? ilog2(maxrate) - 1 : 0;
|
||||
tmp = maxrate - rounddown_pow_of_two(maxrate);
|
||||
if (maxrate < MAX_RATE_MANTISSA)
|
||||
*mantissa = tmp * 2;
|
||||
else
|
||||
*mantissa = tmp / (1ULL << (*exp - 7));
|
||||
maxrate = maxrate / 2;
|
||||
if (!maxrate) {
|
||||
/* Rates below 2 Mbps map to the smallest step */
|
||||
*exp = 0;
|
||||
*mantissa = 0;
|
||||
} else {
|
||||
*exp = ilog2(maxrate);
|
||||
/* Clear MSB and derive fractional bits */
|
||||
maxrate &= ~BIT(*exp);
|
||||
*mantissa = (maxrate << RATE_MANTISSA_BITS) >> *exp;
|
||||
}
|
||||
} else {
|
||||
/* Instead of disabling rate limiting, set all values to max */
|
||||
*exp = MAX_RATE_EXPONENT;
|
||||
|
|
|
|||
|
|
@ -173,6 +173,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
|
|||
}
|
||||
memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
|
||||
|
||||
/* Report 0 for non ETS TSA */
|
||||
for (i = 0; i < ets->ets_cap; i++) {
|
||||
if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC &&
|
||||
priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS)
|
||||
ets->tc_tx_bw[i] = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -317,6 +324,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||
if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) {
|
||||
netdev_err(netdev,
|
||||
"Failed to validate ETS: CB Shaper is not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate Bandwidth Sum */
|
||||
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||
if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
|
||||
|
|
|
|||
|
|
@ -211,11 +211,11 @@ static void mlx5e_disable_async_events(struct mlx5e_priv *priv)
|
|||
|
||||
static int mlx5e_devcom_event_mpv(int event, void *my_data, void *event_data)
|
||||
{
|
||||
struct mlx5e_priv *slave_priv = my_data;
|
||||
struct mlx5e_priv *master_priv = event_data;
|
||||
|
||||
switch (event) {
|
||||
case MPV_DEVCOM_MASTER_UP:
|
||||
mlx5_devcom_comp_set_ready(slave_priv->devcom, true);
|
||||
mlx5_devcom_comp_set_ready(master_priv->devcom, true);
|
||||
break;
|
||||
case MPV_DEVCOM_MASTER_DOWN:
|
||||
/* no need for comp set ready false since we unregister after
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw,
|
|||
flow_act.action = flow_action;
|
||||
vport->egress.allowed_vlan =
|
||||
mlx5_add_flow_rules(vport->egress.acl, spec,
|
||||
&flow_act, fwd_dest, 0);
|
||||
&flow_act, fwd_dest, fwd_dest ? 1 : 0);
|
||||
if (IS_ERR(vport->egress.allowed_vlan)) {
|
||||
err = PTR_ERR(vport->egress.allowed_vlan);
|
||||
esw_warn(esw->dev,
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
|
||||
ptr = MLX5_ADDR_OF(mcia_reg, out, dwords);
|
||||
|
||||
*module_id = ptr[0];
|
||||
|
||||
|
|
@ -399,7 +399,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
|
||||
ptr = MLX5_ADDR_OF(mcia_reg, out, dwords);
|
||||
memcpy(data, ptr, size);
|
||||
|
||||
return size;
|
||||
|
|
|
|||
|
|
@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res)
|
|||
res->mutex =
|
||||
nfp_cpp_mutex_alloc(cpp,
|
||||
NFP_RESOURCE_TBL_TARGET, addr, key);
|
||||
if (!res->mutex)
|
||||
return -ENOMEM;
|
||||
|
||||
res->cpp_id = NFP_CPP_ID(entry.region.cpp_target,
|
||||
entry.region.cpp_action,
|
||||
entry.region.cpp_token);
|
||||
|
|
|
|||
|
|
@ -192,6 +192,12 @@ enum rtase_sw_flag_content {
|
|||
RTASE_SWF_MSIX_ENABLED = BIT(2),
|
||||
};
|
||||
|
||||
enum rtase_parse_result {
|
||||
RTASE_PARSE_OK,
|
||||
RTASE_PARSE_SKIP,
|
||||
RTASE_PARSE_DROP,
|
||||
};
|
||||
|
||||
#define RSVD_MASK 0x3FFFC000
|
||||
|
||||
struct rtase_tx_desc {
|
||||
|
|
@ -363,4 +369,6 @@ struct rtase_private {
|
|||
|
||||
#define RTASE_MSS_MASK GENMASK(28, 18)
|
||||
|
||||
#define RTASE_MIN_PAD_LEN 47
|
||||
|
||||
#endif /* RTASE_H */
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/ptp_classify.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <asm/irq.h>
|
||||
|
|
@ -1252,6 +1253,199 @@ static u32 rtase_tx_csum(struct sk_buff *skb, const struct net_device *dev)
|
|||
return csum_cmd;
|
||||
}
|
||||
|
||||
static enum rtase_parse_result rtase_get_l3_proto(struct sk_buff *skb,
|
||||
__be16 *proto,
|
||||
u32 *network_offset)
|
||||
{
|
||||
struct vlan_hdr *vh, _vh;
|
||||
struct ethhdr *eh, _eh;
|
||||
u32 offset = ETH_HLEN;
|
||||
|
||||
eh = skb_header_pointer(skb, 0, sizeof(_eh), &_eh);
|
||||
if (!eh)
|
||||
return RTASE_PARSE_DROP;
|
||||
|
||||
*proto = eh->h_proto;
|
||||
|
||||
while (eth_type_vlan(*proto)) {
|
||||
vh = skb_header_pointer(skb, offset, sizeof(_vh), &_vh);
|
||||
if (!vh)
|
||||
return RTASE_PARSE_DROP;
|
||||
|
||||
*proto = vh->h_vlan_encapsulated_proto;
|
||||
offset += VLAN_HLEN;
|
||||
}
|
||||
|
||||
*network_offset = offset;
|
||||
|
||||
return RTASE_PARSE_OK;
|
||||
}
|
||||
|
||||
static bool rtase_pad_to_transport_len(struct sk_buff *skb,
|
||||
u32 transport_offset,
|
||||
u32 pad_to_len)
|
||||
{
|
||||
u32 trans_data_len;
|
||||
u32 pad_len;
|
||||
|
||||
trans_data_len = skb->len - transport_offset;
|
||||
if (trans_data_len >= pad_to_len)
|
||||
return true;
|
||||
|
||||
if (skb_is_nonlinear(skb)) {
|
||||
if (skb_linearize(skb))
|
||||
return false;
|
||||
}
|
||||
|
||||
pad_len = pad_to_len - trans_data_len;
|
||||
if (__skb_put_padto(skb, skb->len + pad_len, false))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static enum rtase_parse_result rtase_get_transport_offset(struct sk_buff *skb,
|
||||
u32 *transport_offset,
|
||||
u8 *transport_proto,
|
||||
u32 *pad_to_len)
|
||||
{
|
||||
enum rtase_parse_result ret;
|
||||
struct ipv6hdr *i6h, _i6h;
|
||||
struct iphdr *ih, _ih;
|
||||
bool non_first_frag;
|
||||
__be16 proto;
|
||||
u32 offset;
|
||||
u32 no;
|
||||
|
||||
ret = rtase_get_l3_proto(skb, &proto, &no);
|
||||
if (ret != RTASE_PARSE_OK)
|
||||
return ret;
|
||||
|
||||
switch (proto) {
|
||||
case htons(ETH_P_IP):
|
||||
ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih);
|
||||
if (!ih)
|
||||
return RTASE_PARSE_DROP;
|
||||
|
||||
if (ih->ihl < 5)
|
||||
return RTASE_PARSE_DROP;
|
||||
|
||||
offset = no + ih->ihl * 4;
|
||||
if (offset > skb->len)
|
||||
return RTASE_PARSE_DROP;
|
||||
|
||||
non_first_frag = ntohs(ih->frag_off) & IP_OFFSET;
|
||||
|
||||
if (ih->protocol == IPPROTO_TCP) {
|
||||
if (skb->len - offset < sizeof(struct tcphdr)) {
|
||||
if (non_first_frag) {
|
||||
*transport_offset = offset;
|
||||
*transport_proto = IPPROTO_TCP;
|
||||
*pad_to_len = sizeof(struct tcphdr);
|
||||
|
||||
return RTASE_PARSE_OK;
|
||||
}
|
||||
|
||||
return RTASE_PARSE_DROP;
|
||||
}
|
||||
|
||||
return RTASE_PARSE_SKIP;
|
||||
}
|
||||
|
||||
if (ih->protocol != IPPROTO_UDP)
|
||||
return RTASE_PARSE_SKIP;
|
||||
|
||||
*transport_offset = offset;
|
||||
*transport_proto = IPPROTO_UDP;
|
||||
|
||||
if (skb->len - offset < sizeof(struct udphdr)) {
|
||||
if (non_first_frag) {
|
||||
*pad_to_len = sizeof(struct udphdr);
|
||||
|
||||
return RTASE_PARSE_OK;
|
||||
}
|
||||
|
||||
return RTASE_PARSE_DROP;
|
||||
}
|
||||
|
||||
return RTASE_PARSE_OK;
|
||||
|
||||
case htons(ETH_P_IPV6):
|
||||
i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h);
|
||||
if (!i6h)
|
||||
return RTASE_PARSE_DROP;
|
||||
|
||||
offset = no + sizeof(*i6h);
|
||||
|
||||
if (i6h->nexthdr == IPPROTO_TCP) {
|
||||
if (skb->len - offset < sizeof(struct tcphdr))
|
||||
return RTASE_PARSE_DROP;
|
||||
|
||||
return RTASE_PARSE_SKIP;
|
||||
}
|
||||
|
||||
if (i6h->nexthdr != IPPROTO_UDP)
|
||||
return RTASE_PARSE_SKIP;
|
||||
|
||||
if (skb->len - offset < sizeof(struct udphdr))
|
||||
return RTASE_PARSE_DROP;
|
||||
|
||||
*transport_offset = offset;
|
||||
*transport_proto = IPPROTO_UDP;
|
||||
|
||||
return RTASE_PARSE_OK;
|
||||
|
||||
default:
|
||||
return RTASE_PARSE_SKIP;
|
||||
}
|
||||
}
|
||||
|
||||
static bool rtase_skb_pad(struct sk_buff *skb)
|
||||
{
|
||||
enum rtase_parse_result ret;
|
||||
u32 transport_offset;
|
||||
__be16 *dest, _dest;
|
||||
u32 trans_data_len;
|
||||
u32 pad_to_len = 0;
|
||||
u8 transport_proto;
|
||||
u16 dest_port;
|
||||
|
||||
ret = rtase_get_transport_offset(skb, &transport_offset,
|
||||
&transport_proto, &pad_to_len);
|
||||
if (ret == RTASE_PARSE_SKIP) {
|
||||
return true;
|
||||
} else if (ret == RTASE_PARSE_DROP) {
|
||||
netdev_dbg(skb->dev, "drop malformed packet\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pad_to_len &&
|
||||
!rtase_pad_to_transport_len(skb, transport_offset, pad_to_len))
|
||||
return false;
|
||||
|
||||
if (transport_proto != IPPROTO_UDP)
|
||||
return true;
|
||||
|
||||
trans_data_len = skb->len - transport_offset;
|
||||
if (trans_data_len < offsetof(struct udphdr, len) ||
|
||||
trans_data_len >= RTASE_MIN_PAD_LEN)
|
||||
return true;
|
||||
|
||||
dest = skb_header_pointer(skb,
|
||||
transport_offset +
|
||||
offsetof(struct udphdr, dest),
|
||||
sizeof(_dest), &_dest);
|
||||
if (!dest)
|
||||
return true;
|
||||
|
||||
dest_port = ntohs(*dest);
|
||||
if (dest_port != PTP_EV_PORT && dest_port != PTP_GEN_PORT)
|
||||
return true;
|
||||
|
||||
return rtase_pad_to_transport_len(skb, transport_offset,
|
||||
RTASE_MIN_PAD_LEN);
|
||||
}
|
||||
|
||||
static int rtase_xmit_frags(struct rtase_ring *ring, struct sk_buff *skb,
|
||||
u32 opts1, u32 opts2)
|
||||
{
|
||||
|
|
@ -1365,6 +1559,9 @@ static netdev_tx_t rtase_start_xmit(struct sk_buff *skb,
|
|||
opts2 |= rtase_tx_csum(skb, dev);
|
||||
}
|
||||
|
||||
if (!rtase_skb_pad(skb))
|
||||
goto err_dma_0;
|
||||
|
||||
frags = rtase_xmit_frags(ring, skb, opts1, opts2);
|
||||
if (unlikely(frags < 0))
|
||||
goto err_dma_0;
|
||||
|
|
|
|||
|
|
@ -525,6 +525,32 @@ static int intel_set_reg_access(const struct pmc_serdes_regs *regs, int max_regs
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the SerDes lane rate must change to serve @interface.
|
||||
* If the current rate cannot be determined, reconfigure as before.
|
||||
*/
|
||||
static bool intel_serdes_needs_reconfig(struct stmmac_priv *priv,
|
||||
struct intel_priv_data *intel_priv,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
u32 cur_rate, want_rate;
|
||||
int data;
|
||||
|
||||
if (!intel_priv->mdio_adhoc_addr)
|
||||
return true;
|
||||
|
||||
data = mdiobus_read(priv->mii, intel_priv->mdio_adhoc_addr,
|
||||
SERDES_GCR0);
|
||||
if (data < 0)
|
||||
return true;
|
||||
|
||||
cur_rate = (data & SERDES_RATE_MASK) >> SERDES_RATE_PCIE_SHIFT;
|
||||
want_rate = interface == PHY_INTERFACE_MODE_2500BASEX ?
|
||||
SERDES_RATE_PCIE_GEN2 : SERDES_RATE_PCIE_GEN1;
|
||||
|
||||
return cur_rate != want_rate;
|
||||
}
|
||||
|
||||
static int intel_mac_finish(struct net_device *ndev,
|
||||
void *intel_data,
|
||||
unsigned int mode,
|
||||
|
|
@ -536,6 +562,11 @@ static int intel_mac_finish(struct net_device *ndev,
|
|||
int max_regs = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!intel_serdes_needs_reconfig(priv, intel_priv, interface)) {
|
||||
priv->plat->phy_interface = interface;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = intel_tsn_lane_is_available(ndev, intel_priv);
|
||||
if (ret < 0) {
|
||||
netdev_info(priv->dev, "No TSN lane available to set the registers.\n");
|
||||
|
|
|
|||
|
|
@ -106,6 +106,17 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
|
|||
ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
|
||||
}
|
||||
|
||||
static void dwmac4_dma_deinit_channel(struct stmmac_priv *priv,
|
||||
void __iomem *ioaddr, u32 chan)
|
||||
{
|
||||
const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
|
||||
u32 value;
|
||||
|
||||
value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
|
||||
value &= ~DMA_CHAN_INTR_DEFAULT_MASK;
|
||||
writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
|
||||
}
|
||||
|
||||
static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
|
||||
void __iomem *ioaddr,
|
||||
struct stmmac_dma_cfg *dma_cfg, u32 chan)
|
||||
|
|
@ -125,6 +136,17 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
|
|||
ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
|
||||
}
|
||||
|
||||
static void dwmac410_dma_deinit_channel(struct stmmac_priv *priv,
|
||||
void __iomem *ioaddr, u32 chan)
|
||||
{
|
||||
const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
|
||||
u32 value;
|
||||
|
||||
value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
|
||||
value &= ~DMA_CHAN_INTR_DEFAULT_MASK_4_10;
|
||||
writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
|
||||
}
|
||||
|
||||
static void dwmac4_dma_init(void __iomem *ioaddr,
|
||||
struct stmmac_dma_cfg *dma_cfg)
|
||||
{
|
||||
|
|
@ -548,6 +570,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = {
|
|||
.reset = dwmac4_dma_reset,
|
||||
.init = dwmac4_dma_init,
|
||||
.init_chan = dwmac4_dma_init_channel,
|
||||
.deinit_chan = dwmac4_dma_deinit_channel,
|
||||
.init_rx_chan = dwmac4_dma_init_rx_chan,
|
||||
.init_tx_chan = dwmac4_dma_init_tx_chan,
|
||||
.axi = dwmac4_dma_axi,
|
||||
|
|
@ -577,6 +600,7 @@ const struct stmmac_dma_ops dwmac410_dma_ops = {
|
|||
.reset = dwmac4_dma_reset,
|
||||
.init = dwmac4_dma_init,
|
||||
.init_chan = dwmac410_dma_init_channel,
|
||||
.deinit_chan = dwmac410_dma_deinit_channel,
|
||||
.init_rx_chan = dwmac4_dma_init_rx_chan,
|
||||
.init_tx_chan = dwmac4_dma_init_tx_chan,
|
||||
.axi = dwmac4_dma_axi,
|
||||
|
|
|
|||
|
|
@ -1370,36 +1370,40 @@ static int dwxgmac2_config_l4_filter(struct mac_device_info *hw, u32 filter_no,
|
|||
value &= ~XGMAC_L4PEN0;
|
||||
}
|
||||
|
||||
value &= ~(XGMAC_L4SPM0 | XGMAC_L4SPIM0);
|
||||
value &= ~(XGMAC_L4DPM0 | XGMAC_L4DPIM0);
|
||||
if (sa) {
|
||||
value |= XGMAC_L4SPM0;
|
||||
if (inv)
|
||||
value |= XGMAC_L4SPIM0;
|
||||
else
|
||||
value &= ~XGMAC_L4SPIM0;
|
||||
} else {
|
||||
value |= XGMAC_L4DPM0;
|
||||
if (inv)
|
||||
value |= XGMAC_L4DPIM0;
|
||||
else
|
||||
value &= ~XGMAC_L4DPIM0;
|
||||
}
|
||||
|
||||
ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dwxgmac2_filter_read(hw, filter_no, XGMAC_L4_ADDR, &value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (sa) {
|
||||
value = FIELD_PREP(XGMAC_L4SP0, match);
|
||||
|
||||
ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
value &= ~XGMAC_L4SP0;
|
||||
value |= FIELD_PREP(XGMAC_L4SP0, match);
|
||||
} else {
|
||||
value = FIELD_PREP(XGMAC_L4DP0, match);
|
||||
|
||||
ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
value &= ~XGMAC_L4DP0;
|
||||
value |= FIELD_PREP(XGMAC_L4DP0, match);
|
||||
}
|
||||
|
||||
ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!en)
|
||||
return dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -170,6 +170,8 @@ struct stmmac_dma_ops {
|
|||
void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg);
|
||||
void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
|
||||
struct stmmac_dma_cfg *dma_cfg, u32 chan);
|
||||
void (*deinit_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
|
||||
u32 chan);
|
||||
void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
|
||||
struct stmmac_dma_cfg *dma_cfg,
|
||||
dma_addr_t phy, u32 chan);
|
||||
|
|
@ -235,6 +237,8 @@ struct stmmac_dma_ops {
|
|||
stmmac_do_void_callback(__priv, dma, init, __args)
|
||||
#define stmmac_init_chan(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
|
||||
#define stmmac_deinit_chan(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, dma, deinit_chan, __priv, __args)
|
||||
#define stmmac_init_rx_chan(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, dma, init_rx_chan, __priv, __args)
|
||||
#define stmmac_init_tx_chan(__priv, __args...) \
|
||||
|
|
|
|||
|
|
@ -1083,63 +1083,45 @@ static void stmmac_mac_link_up(struct phylink_config *config,
|
|||
old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
|
||||
ctrl = old_ctrl & ~priv->hw->link.speed_mask;
|
||||
|
||||
if (interface == PHY_INTERFACE_MODE_USXGMII) {
|
||||
switch (speed) {
|
||||
case SPEED_10000:
|
||||
ctrl |= priv->hw->link.xgmii.speed10000;
|
||||
break;
|
||||
case SPEED_5000:
|
||||
ctrl |= priv->hw->link.xgmii.speed5000;
|
||||
break;
|
||||
case SPEED_2500:
|
||||
switch (speed) {
|
||||
case SPEED_100000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed100000;
|
||||
break;
|
||||
case SPEED_50000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed50000;
|
||||
break;
|
||||
case SPEED_40000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed40000;
|
||||
break;
|
||||
case SPEED_25000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed25000;
|
||||
break;
|
||||
case SPEED_10000:
|
||||
ctrl |= priv->hw->link.xgmii.speed10000;
|
||||
break;
|
||||
case SPEED_5000:
|
||||
ctrl |= priv->hw->link.xgmii.speed5000;
|
||||
break;
|
||||
case SPEED_2500:
|
||||
if (interface == PHY_INTERFACE_MODE_USXGMII)
|
||||
ctrl |= priv->hw->link.xgmii.speed2500;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} else if (interface == PHY_INTERFACE_MODE_XLGMII) {
|
||||
switch (speed) {
|
||||
case SPEED_100000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed100000;
|
||||
break;
|
||||
case SPEED_50000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed50000;
|
||||
break;
|
||||
case SPEED_40000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed40000;
|
||||
break;
|
||||
case SPEED_25000:
|
||||
ctrl |= priv->hw->link.xlgmii.speed25000;
|
||||
break;
|
||||
case SPEED_10000:
|
||||
ctrl |= priv->hw->link.xgmii.speed10000;
|
||||
break;
|
||||
case SPEED_2500:
|
||||
else
|
||||
ctrl |= priv->hw->link.speed2500;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
ctrl |= priv->hw->link.speed1000;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
switch (speed) {
|
||||
case SPEED_2500:
|
||||
ctrl |= priv->hw->link.speed2500;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
ctrl |= priv->hw->link.speed1000;
|
||||
break;
|
||||
case SPEED_100:
|
||||
ctrl |= priv->hw->link.speed100;
|
||||
break;
|
||||
case SPEED_10:
|
||||
ctrl |= priv->hw->link.speed10;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case SPEED_1000:
|
||||
ctrl |= priv->hw->link.speed1000;
|
||||
break;
|
||||
case SPEED_100:
|
||||
ctrl |= priv->hw->link.speed100;
|
||||
break;
|
||||
case SPEED_10:
|
||||
ctrl |= priv->hw->link.speed10;
|
||||
break;
|
||||
default:
|
||||
netdev_err(priv->dev,
|
||||
"unsupported speed %s on %s, leaving the MAC disabled\n",
|
||||
phy_speed_to_str(speed), phy_modes(interface));
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->plat->fix_mac_speed)
|
||||
|
|
@ -2560,6 +2542,7 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
|
|||
{
|
||||
u8 rx_channels_count = priv->plat->rx_queues_to_use;
|
||||
u8 tx_channels_count = priv->plat->tx_queues_to_use;
|
||||
u8 dma_csr_ch = max(rx_channels_count, tx_channels_count);
|
||||
u8 chan;
|
||||
|
||||
for (chan = 0; chan < rx_channels_count; chan++)
|
||||
|
|
@ -2567,6 +2550,9 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
|
|||
|
||||
for (chan = 0; chan < tx_channels_count; chan++)
|
||||
stmmac_stop_tx_dma(priv, chan);
|
||||
|
||||
for (chan = 0; chan < dma_csr_ch; chan++)
|
||||
stmmac_deinit_chan(priv, priv->ioaddr, chan);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -446,6 +446,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv,
|
|||
}
|
||||
|
||||
#define ETHER_TYPE_FULL_MASK cpu_to_be16(~0)
|
||||
#define IP_PROTO_FULL_MASK 0xFF
|
||||
|
||||
static int tc_add_basic_flow(struct stmmac_priv *priv,
|
||||
struct flow_cls_offload *cls,
|
||||
|
|
@ -461,6 +462,37 @@ static int tc_add_basic_flow(struct stmmac_priv *priv,
|
|||
|
||||
flow_rule_match_basic(rule, &match);
|
||||
|
||||
/* Both network proto and transport proto not present in the key */
|
||||
if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto)) {
|
||||
NL_SET_ERR_MSG_MOD(cls->common.extack,
|
||||
"filter must specify network or transport protocol");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* If the proto is present in the key and is not full mask */
|
||||
if ((match.mask->n_proto && match.mask->n_proto != ETHER_TYPE_FULL_MASK) ||
|
||||
(match.mask->ip_proto && match.mask->ip_proto != IP_PROTO_FULL_MASK)) {
|
||||
NL_SET_ERR_MSG_MOD(cls->common.extack,
|
||||
"only full protocol mask is supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Network proto is present in the key and is not IPv4 */
|
||||
if (match.mask->n_proto && match.key->n_proto != cpu_to_be16(ETH_P_IP)) {
|
||||
NL_SET_ERR_MSG_MOD(cls->common.extack,
|
||||
"only IPv4 network protocol is supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Transport proto is present in the key and is not TCP or UDP */
|
||||
if (match.mask->ip_proto &&
|
||||
match.key->ip_proto != IPPROTO_TCP &&
|
||||
match.key->ip_proto != IPPROTO_UDP) {
|
||||
NL_SET_ERR_MSG_MOD(cls->common.extack,
|
||||
"only TCP and UDP transport protocols are supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
entry->ip_proto = match.key->ip_proto;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -598,6 +630,8 @@ static int tc_add_flow(struct stmmac_priv *priv,
|
|||
ret = tc_flow_parsers[i].fn(priv, cls, entry);
|
||||
if (!ret)
|
||||
entry->in_use = true;
|
||||
else if (ret == -EOPNOTSUPP)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!entry->in_use)
|
||||
|
|
@ -627,6 +661,7 @@ static int tc_del_flow(struct stmmac_priv *priv,
|
|||
entry->in_use = false;
|
||||
entry->cookie = 0;
|
||||
entry->is_l4 = false;
|
||||
entry->action = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,11 +96,13 @@ int txgbe_read_eeprom_hostif(struct wx *wx,
|
|||
dword_len = round_up(length, 4) >> 2;
|
||||
|
||||
for (i = 0; i < dword_len; i++) {
|
||||
u32 copy_len = min_t(u32, 4, length - i * 4);
|
||||
|
||||
value = rd32a(wx, WX_FW2SW_MBOX, i + offset);
|
||||
le32_to_cpus(&value);
|
||||
|
||||
memcpy(data, &value, 4);
|
||||
data += 4;
|
||||
memcpy(data, &value, copy_len);
|
||||
data += copy_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -945,6 +945,7 @@ static void txgbe_remove(struct pci_dev *pdev)
|
|||
netdev = wx->netdev;
|
||||
wx_disable_sriov(wx);
|
||||
unregister_netdev(netdev);
|
||||
txgbe_fdir_filter_exit(wx);
|
||||
|
||||
timer_shutdown_sync(&wx->service_timer);
|
||||
cancel_work_sync(&wx->service_task);
|
||||
|
|
|
|||
|
|
@ -43,8 +43,17 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
|
|||
#define GENEVE_OPT_GRO_HINT_LEN 1
|
||||
|
||||
struct geneve_opt_gro_hint {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
u8 inner_proto_id:2,
|
||||
nested_is_v6:1;
|
||||
nested_is_v6:1,
|
||||
rsvd:5;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
u8 rsvd:5,
|
||||
nested_is_v6:1,
|
||||
inner_proto_id:2;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
u8 nested_nh_offset;
|
||||
u8 nested_tp_offset;
|
||||
u8 nested_hdr_len;
|
||||
|
|
@ -577,6 +586,7 @@ static int geneve_post_decap_hint(const struct sock *sk, struct sk_buff *skb,
|
|||
struct iphdr *iph;
|
||||
struct udphdr *uh;
|
||||
__be16 p;
|
||||
int err;
|
||||
|
||||
hint_off = geneve_sk_gro_hint_off(sk, *geneveh, &p, &len);
|
||||
if (!hint_off)
|
||||
|
|
@ -601,12 +611,20 @@ static int geneve_post_decap_hint(const struct sock *sk, struct sk_buff *skb,
|
|||
!geneve_opt_gro_hint_validate(skb->data, gro_hint)))
|
||||
return -EINVAL;
|
||||
|
||||
ipv6h = (void *)skb->data + gro_hint->nested_nh_offset;
|
||||
iph = (struct iphdr *)ipv6h;
|
||||
total_len = skb->len - gro_hint->nested_nh_offset;
|
||||
if (total_len >= GRO_LEGACY_MAX_SIZE)
|
||||
return -E2BIG;
|
||||
|
||||
err = skb_ensure_writable(skb, gro_hint->nested_tp_offset + sizeof(*uh));
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
|
||||
*geneveh = geneve_hdr(skb);
|
||||
gro_hint = geneve_opt_gro_hint(*geneveh, hint_off);
|
||||
|
||||
ipv6h = (void *)skb->data + gro_hint->nested_nh_offset;
|
||||
iph = (struct iphdr *)ipv6h;
|
||||
|
||||
/*
|
||||
* After stripping the outer encap, the packet still carries a
|
||||
* tunnel encapsulation: the nested one.
|
||||
|
|
@ -2376,6 +2394,9 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
|
|||
struct geneve_config cfg;
|
||||
int err;
|
||||
|
||||
if (!rtnl_dev_link_net_capable(dev, geneve->net))
|
||||
return -EPERM;
|
||||
|
||||
/* If the geneve device is configured for metadata (or externally
|
||||
* controlled, for example, OVS), then nothing can be changed.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -669,8 +669,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)
|
|||
return -1;
|
||||
|
||||
/* pull GTP and UDP headers */
|
||||
skb_pull_data(skb,
|
||||
sizeof(struct gtp1_header_long) + sizeof(struct udphdr));
|
||||
if (!skb_pull_data(skb, sizeof(struct gtp1_header_long) +
|
||||
sizeof(struct udphdr)))
|
||||
return -1;
|
||||
|
||||
gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet));
|
||||
memset(gtp_pkt, 0, sizeof(struct gtp1u_packet));
|
||||
|
|
@ -826,13 +827,17 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
|
|||
if (!pskb_may_pull(skb, hdrlen))
|
||||
return -1;
|
||||
|
||||
gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr));
|
||||
|
||||
if (gtp1->flags & GTP1_F_EXTHDR &&
|
||||
gtp_parse_exthdrs(skb, &hdrlen) < 0)
|
||||
return -1;
|
||||
|
||||
if (gtp_inner_proto(skb, hdrlen, &inner_proto) < 0) {
|
||||
netdev_dbg(gtp->dev, "GTP packet does not encapsulate an IP packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr));
|
||||
|
||||
pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid),
|
||||
gtp_proto_to_family(inner_proto));
|
||||
if (!pctx) {
|
||||
|
|
@ -840,10 +845,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (gtp1->flags & GTP1_F_EXTHDR &&
|
||||
gtp_parse_exthdrs(skb, &hdrlen) < 0)
|
||||
return -1;
|
||||
|
||||
return gtp_rx(pctx, skb, hdrlen, gtp->role, inner_proto);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -731,18 +731,21 @@ static __init int mctp_i3c_mod_init(void)
|
|||
int rc;
|
||||
|
||||
rc = i3c_register_notifier(&mctp_i3c_notifier);
|
||||
if (rc < 0) {
|
||||
i3c_driver_unregister(&mctp_i3c_driver);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL);
|
||||
|
||||
rc = i3c_driver_register(&mctp_i3c_driver);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
goto err_unregister_notifier;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_notifier:
|
||||
i3c_unregister_notifier(&mctp_i3c_notifier);
|
||||
mctp_i3c_bus_remove_all();
|
||||
return rc;
|
||||
}
|
||||
|
||||
static __exit void mctp_i3c_mod_exit(void)
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ static void mctp_serial_push_header(struct mctp_serial *dev, u8 c)
|
|||
} else {
|
||||
dev->rxlen = c;
|
||||
dev->rxpos = 0;
|
||||
dev->rxstate = STATE_DATA;
|
||||
dev->rxstate = c > 0 ? STATE_DATA : STATE_TRAILER;
|
||||
dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ void ovpn_decrypt_post(void *data, int ret)
|
|||
}
|
||||
|
||||
/* keep track of last received authenticated packet for keepalive */
|
||||
WRITE_ONCE(peer->last_recv, ktime_get_real_seconds());
|
||||
WRITE_ONCE(peer->last_recv, ktime_get_boottime_seconds());
|
||||
|
||||
rcu_read_lock();
|
||||
sock = rcu_dereference(peer->sock);
|
||||
|
|
@ -294,7 +294,7 @@ void ovpn_encrypt_post(void *data, int ret)
|
|||
|
||||
ovpn_peer_stats_increment_tx(&peer->link_stats, orig_len);
|
||||
/* keep track of last sent packet for keepalive */
|
||||
WRITE_ONCE(peer->last_sent, ktime_get_real_seconds());
|
||||
WRITE_ONCE(peer->last_sent, ktime_get_boottime_seconds());
|
||||
/* skb passed down the stack - don't free it */
|
||||
skb = NULL;
|
||||
err_unlock:
|
||||
|
|
|
|||
|
|
@ -26,11 +26,12 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,
|
|||
struct llist_head *release_list)
|
||||
__releases(&ovpn->lock)
|
||||
{
|
||||
struct ovpn_peer *peer;
|
||||
struct ovpn_peer *peer, *next;
|
||||
|
||||
spin_unlock_bh(&ovpn->lock);
|
||||
|
||||
llist_for_each_entry(peer, release_list->first, release_entry) {
|
||||
llist_for_each_entry_safe(peer, next, release_list->first,
|
||||
release_entry) {
|
||||
ovpn_socket_release(peer);
|
||||
ovpn_peer_put(peer);
|
||||
}
|
||||
|
|
@ -44,7 +45,7 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,
|
|||
*/
|
||||
void ovpn_peer_keepalive_set(struct ovpn_peer *peer, u32 interval, u32 timeout)
|
||||
{
|
||||
time64_t now = ktime_get_real_seconds();
|
||||
time64_t now = ktime_get_boottime_seconds();
|
||||
|
||||
netdev_dbg(peer->ovpn->dev,
|
||||
"scheduling keepalive for peer %u: interval=%u timeout=%u\n",
|
||||
|
|
@ -1167,7 +1168,6 @@ static void ovpn_peer_release_p2p(struct ovpn_priv *ovpn, struct sock *sk,
|
|||
ovpn_sock = rcu_access_pointer(peer->sock);
|
||||
if (!ovpn_sock || ovpn_sock->sk != sk) {
|
||||
spin_unlock_bh(&ovpn->lock);
|
||||
ovpn_peer_put(peer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1285,8 +1285,10 @@ static time64_t ovpn_peer_keepalive_work_single(struct ovpn_peer *peer,
|
|||
netdev_dbg(peer->ovpn->dev,
|
||||
"sending keepalive to peer %u\n",
|
||||
peer->id);
|
||||
if (schedule_work(&peer->keepalive_work))
|
||||
ovpn_peer_hold(peer);
|
||||
if (WARN_ON(!ovpn_peer_hold(peer)))
|
||||
return 0;
|
||||
if (!schedule_work(&peer->keepalive_work))
|
||||
ovpn_peer_put(peer);
|
||||
}
|
||||
|
||||
if (next_run1 < next_run2)
|
||||
|
|
@ -1357,7 +1359,7 @@ void ovpn_peer_keepalive_work(struct work_struct *work)
|
|||
{
|
||||
struct ovpn_priv *ovpn = container_of(work, struct ovpn_priv,
|
||||
keepalive_work.work);
|
||||
time64_t next_run = 0, now = ktime_get_real_seconds();
|
||||
time64_t next_run = 0, now = ktime_get_boottime_seconds();
|
||||
LLIST_HEAD(release_list);
|
||||
|
||||
spin_lock_bh(&ovpn->lock);
|
||||
|
|
|
|||
|
|
@ -151,7 +151,8 @@ static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)
|
|||
/* take reference for deferred peer deletion. should never fail */
|
||||
if (WARN_ON(!ovpn_peer_hold(peer)))
|
||||
goto err_nopeer;
|
||||
schedule_work(&peer->tcp.defer_del_work);
|
||||
if (!schedule_work(&peer->tcp.defer_del_work))
|
||||
ovpn_peer_put(peer);
|
||||
ovpn_dev_dstats_rx_dropped(peer->ovpn->dev);
|
||||
err_nopeer:
|
||||
kfree_skb(skb);
|
||||
|
|
@ -283,7 +284,8 @@ static void ovpn_tcp_send_sock(struct ovpn_peer *peer, struct sock *sk)
|
|||
* stream therefore we abort the connection
|
||||
*/
|
||||
ovpn_peer_hold(peer);
|
||||
schedule_work(&peer->tcp.defer_del_work);
|
||||
if (!schedule_work(&peer->tcp.defer_del_work))
|
||||
ovpn_peer_put(peer);
|
||||
|
||||
/* we bail out immediately and keep tx_in_progress set
|
||||
* to true. This way we prevent more TX attempts
|
||||
|
|
|
|||
|
|
@ -1058,6 +1058,7 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
|
|||
|
||||
/* Reset link_state */
|
||||
state->link = false;
|
||||
state->an_complete = false;
|
||||
state->speed = SPEED_UNKNOWN;
|
||||
state->duplex = DUPLEX_UNKNOWN;
|
||||
state->pause = 0;
|
||||
|
|
@ -1069,6 +1070,8 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
state->an_complete = ret & DW_VR_MII_AN_STS_C37_ANCMPLT_INTR;
|
||||
|
||||
if (ret & DW_VR_MII_C37_ANSGM_SP_LNKSTS) {
|
||||
int speed_value;
|
||||
|
||||
|
|
@ -1086,35 +1089,14 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
|
|||
state->duplex = DUPLEX_FULL;
|
||||
else
|
||||
state->duplex = DUPLEX_HALF;
|
||||
} else if (ret == DW_VR_MII_AN_STS_C37_ANCMPLT_INTR) {
|
||||
int speed, duplex;
|
||||
|
||||
state->link = true;
|
||||
|
||||
speed = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMCR);
|
||||
if (speed < 0)
|
||||
return speed;
|
||||
|
||||
speed &= BMCR_SPEED100 | BMCR_SPEED1000;
|
||||
if (speed == BMCR_SPEED1000)
|
||||
state->speed = SPEED_1000;
|
||||
else if (speed == BMCR_SPEED100)
|
||||
state->speed = SPEED_100;
|
||||
else if (speed == 0)
|
||||
state->speed = SPEED_10;
|
||||
|
||||
duplex = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_ADVERTISE);
|
||||
if (duplex < 0)
|
||||
return duplex;
|
||||
|
||||
if (duplex & ADVERTISE_1000XFULL)
|
||||
state->duplex = DUPLEX_FULL;
|
||||
else if (duplex & ADVERTISE_1000XHALF)
|
||||
state->duplex = DUPLEX_HALF;
|
||||
|
||||
xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clear AN complete status or interrupt */
|
||||
if (state->an_complete)
|
||||
xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -753,7 +753,7 @@ static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes)
|
|||
err = phy_modify(phydev, MII_M1111_PHY_EXT_SR,
|
||||
MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr);
|
||||
if (err < 0)
|
||||
return extsr;
|
||||
return err;
|
||||
|
||||
return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR,
|
||||
BMCR_ANENABLE, bmcr);
|
||||
|
|
|
|||
|
|
@ -810,7 +810,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
case PPPIOCSMRU:
|
||||
if (get_user(val, p))
|
||||
break;
|
||||
ppp_recv_lock(ppp);
|
||||
ppp->mru = val;
|
||||
ppp_recv_unlock(ppp);
|
||||
err = 0;
|
||||
break;
|
||||
|
||||
|
|
@ -831,7 +833,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
|
||||
case PPPIOCGFLAGS:
|
||||
ppp_lock(ppp);
|
||||
val = ppp->flags | ppp->xstate | ppp->rstate;
|
||||
ppp_unlock(ppp);
|
||||
if (put_user(val, p))
|
||||
break;
|
||||
err = 0;
|
||||
|
|
@ -855,7 +859,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
case PPPIOCSDEBUG:
|
||||
if (get_user(val, p))
|
||||
break;
|
||||
ppp->debug = val;
|
||||
WRITE_ONCE(ppp->debug, val);
|
||||
err = 0;
|
||||
break;
|
||||
|
||||
|
|
@ -866,16 +870,16 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
|
||||
case PPPIOCGIDLE32:
|
||||
idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
|
||||
idle32.recv_idle = (jiffies - ppp->last_recv) / HZ;
|
||||
if (copy_to_user(argp, &idle32, sizeof(idle32)))
|
||||
idle32.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ;
|
||||
idle32.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ;
|
||||
if (copy_to_user(argp, &idle32, sizeof(idle32)))
|
||||
break;
|
||||
err = 0;
|
||||
break;
|
||||
|
||||
case PPPIOCGIDLE64:
|
||||
idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
|
||||
idle64.recv_idle = (jiffies - ppp->last_recv) / HZ;
|
||||
idle64.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ;
|
||||
idle64.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ;
|
||||
if (copy_to_user(argp, &idle64, sizeof(idle64)))
|
||||
break;
|
||||
err = 0;
|
||||
|
|
@ -916,7 +920,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
if (copy_to_user(argp, &npi, sizeof(npi)))
|
||||
break;
|
||||
} else {
|
||||
ppp->npmode[i] = npi.mode;
|
||||
WRITE_ONCE(ppp->npmode[i], npi.mode);
|
||||
/* we may be able to transmit more packets now (??) */
|
||||
netif_wake_queue(ppp->dev);
|
||||
}
|
||||
|
|
@ -1454,7 +1458,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
goto outf;
|
||||
|
||||
/* Drop, accept or reject the packet */
|
||||
switch (ppp->npmode[npi]) {
|
||||
switch (READ_ONCE(ppp->npmode[npi])) {
|
||||
case NPMODE_PASS:
|
||||
break;
|
||||
case NPMODE_QUEUE:
|
||||
|
|
@ -1482,7 +1486,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
|
||||
outf:
|
||||
kfree_skb(skb);
|
||||
++dev->stats.tx_dropped;
|
||||
DEV_STATS_INC(dev, tx_dropped);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1532,11 +1536,11 @@ ppp_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
|
|||
static void
|
||||
ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
|
||||
{
|
||||
stats64->rx_errors = dev->stats.rx_errors;
|
||||
stats64->tx_errors = dev->stats.tx_errors;
|
||||
stats64->rx_dropped = dev->stats.rx_dropped;
|
||||
stats64->tx_dropped = dev->stats.tx_dropped;
|
||||
stats64->rx_length_errors = dev->stats.rx_length_errors;
|
||||
stats64->rx_errors = DEV_STATS_READ(dev, rx_errors);
|
||||
stats64->tx_errors = DEV_STATS_READ(dev, tx_errors);
|
||||
stats64->rx_dropped = DEV_STATS_READ(dev, rx_dropped);
|
||||
stats64->tx_dropped = DEV_STATS_READ(dev, tx_dropped);
|
||||
stats64->rx_length_errors = DEV_STATS_READ(dev, rx_length_errors);
|
||||
dev_fetch_sw_netstats(stats64, dev->tstats);
|
||||
}
|
||||
|
||||
|
|
@ -1790,7 +1794,7 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb)
|
|||
*(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG);
|
||||
if (ppp->pass_filter &&
|
||||
bpf_prog_run(ppp->pass_filter, skb) == 0) {
|
||||
if (ppp->debug & 1)
|
||||
if (READ_ONCE(ppp->debug) & 1)
|
||||
netdev_printk(KERN_DEBUG, ppp->dev,
|
||||
"PPP: outbound frame "
|
||||
"not passed\n");
|
||||
|
|
@ -1800,11 +1804,11 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb)
|
|||
/* if this packet passes the active filter, record the time */
|
||||
if (!(ppp->active_filter &&
|
||||
bpf_prog_run(ppp->active_filter, skb) == 0))
|
||||
ppp->last_xmit = jiffies;
|
||||
WRITE_ONCE(ppp->last_xmit, jiffies);
|
||||
skb_pull(skb, 2);
|
||||
#else
|
||||
/* for data packets, record the time */
|
||||
ppp->last_xmit = jiffies;
|
||||
WRITE_ONCE(ppp->last_xmit, jiffies);
|
||||
#endif /* CONFIG_PPP_FILTER */
|
||||
}
|
||||
|
||||
|
|
@ -1889,7 +1893,7 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb)
|
|||
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
++ppp->dev->stats.tx_errors;
|
||||
DEV_STATS_INC(ppp->dev, tx_errors);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -2154,9 +2158,9 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
|
|||
noskb:
|
||||
spin_unlock(&pch->downl);
|
||||
err_linearize:
|
||||
if (ppp->debug & 1)
|
||||
if (READ_ONCE(ppp->debug) & 1)
|
||||
netdev_err(ppp->dev, "PPP: no memory (fragment)\n");
|
||||
++ppp->dev->stats.tx_errors;
|
||||
DEV_STATS_INC(ppp->dev, tx_errors);
|
||||
++ppp->nxseq;
|
||||
return 1; /* abandon the frame */
|
||||
}
|
||||
|
|
@ -2329,7 +2333,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
|
|||
if (!ppp_decompress_proto(skb)) {
|
||||
kfree_skb(skb);
|
||||
if (ppp) {
|
||||
++ppp->dev->stats.rx_length_errors;
|
||||
DEV_STATS_INC(ppp->dev, rx_length_errors);
|
||||
ppp_receive_error(ppp);
|
||||
}
|
||||
goto done;
|
||||
|
|
@ -2391,7 +2395,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
|
|||
static void
|
||||
ppp_receive_error(struct ppp *ppp)
|
||||
{
|
||||
++ppp->dev->stats.rx_errors;
|
||||
DEV_STATS_INC(ppp->dev, rx_errors);
|
||||
if (ppp->vj)
|
||||
slhc_toss(ppp->vj);
|
||||
}
|
||||
|
|
@ -2502,7 +2506,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
|
|||
*(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG);
|
||||
if (ppp->pass_filter &&
|
||||
bpf_prog_run(ppp->pass_filter, skb) == 0) {
|
||||
if (ppp->debug & 1)
|
||||
if (READ_ONCE(ppp->debug) & 1)
|
||||
netdev_printk(KERN_DEBUG, ppp->dev,
|
||||
"PPP: inbound frame "
|
||||
"not passed\n");
|
||||
|
|
@ -2511,14 +2515,14 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
|
|||
}
|
||||
if (!(ppp->active_filter &&
|
||||
bpf_prog_run(ppp->active_filter, skb) == 0))
|
||||
ppp->last_recv = jiffies;
|
||||
WRITE_ONCE(ppp->last_recv, jiffies);
|
||||
__skb_pull(skb, 2);
|
||||
} else
|
||||
#endif /* CONFIG_PPP_FILTER */
|
||||
ppp->last_recv = jiffies;
|
||||
WRITE_ONCE(ppp->last_recv, jiffies);
|
||||
|
||||
if ((ppp->dev->flags & IFF_UP) == 0 ||
|
||||
ppp->npmode[npi] != NPMODE_PASS) {
|
||||
READ_ONCE(ppp->npmode[npi]) != NPMODE_PASS) {
|
||||
kfree_skb(skb);
|
||||
} else {
|
||||
/* chop off protocol */
|
||||
|
|
@ -2658,7 +2662,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
|
|||
*/
|
||||
if (seq_before(seq, ppp->nextseq)) {
|
||||
kfree_skb(skb);
|
||||
++ppp->dev->stats.rx_dropped;
|
||||
DEV_STATS_INC(ppp->dev, rx_dropped);
|
||||
ppp_receive_error(ppp);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2694,7 +2698,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
|
|||
if (pskb_may_pull(skb, 2))
|
||||
ppp_receive_nonmp_frame(ppp, skb);
|
||||
else {
|
||||
++ppp->dev->stats.rx_length_errors;
|
||||
DEV_STATS_INC(ppp->dev, rx_length_errors);
|
||||
kfree_skb(skb);
|
||||
ppp_receive_error(ppp);
|
||||
}
|
||||
|
|
@ -2771,7 +2775,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
|
|||
seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
|
||||
minseq + 1: PPP_MP_CB(p)->sequence;
|
||||
|
||||
if (ppp->debug & 1)
|
||||
if (READ_ONCE(ppp->debug) & 1)
|
||||
netdev_printk(KERN_DEBUG, ppp->dev,
|
||||
"lost frag %u..%u\n",
|
||||
oldseq, seq-1);
|
||||
|
|
@ -2800,7 +2804,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
|
|||
if (lost == 0 && (PPP_MP_CB(p)->BEbits & E) &&
|
||||
(PPP_MP_CB(head)->BEbits & B)) {
|
||||
if (len > ppp->mrru + 2) {
|
||||
++ppp->dev->stats.rx_length_errors;
|
||||
DEV_STATS_INC(ppp->dev, rx_length_errors);
|
||||
netdev_printk(KERN_DEBUG, ppp->dev,
|
||||
"PPP: reconstructed packet"
|
||||
" is too long (%d)\n", len);
|
||||
|
|
@ -2820,7 +2824,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
|
|||
struct sk_buff *tmp2;
|
||||
|
||||
skb_queue_reverse_walk_from_safe(list, p, tmp2) {
|
||||
if (ppp->debug & 1)
|
||||
if (READ_ONCE(ppp->debug) & 1)
|
||||
netdev_printk(KERN_DEBUG, ppp->dev,
|
||||
"discarding frag %u\n",
|
||||
PPP_MP_CB(p)->sequence);
|
||||
|
|
@ -2842,7 +2846,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
|
|||
skb_queue_walk_safe(list, p, tmp) {
|
||||
if (p == head)
|
||||
break;
|
||||
if (ppp->debug & 1)
|
||||
if (READ_ONCE(ppp->debug) & 1)
|
||||
netdev_printk(KERN_DEBUG, ppp->dev,
|
||||
"discarding frag %u\n",
|
||||
PPP_MP_CB(p)->sequence);
|
||||
|
|
@ -2850,12 +2854,12 @@ ppp_mp_reconstruct(struct ppp *ppp)
|
|||
kfree_skb(p);
|
||||
}
|
||||
|
||||
if (ppp->debug & 1)
|
||||
if (READ_ONCE(ppp->debug) & 1)
|
||||
netdev_printk(KERN_DEBUG, ppp->dev,
|
||||
" missed pkts %u..%u\n",
|
||||
ppp->nextseq,
|
||||
PPP_MP_CB(head)->sequence-1);
|
||||
++ppp->dev->stats.rx_dropped;
|
||||
DEV_STATS_INC(ppp->dev, rx_dropped);
|
||||
ppp_receive_error(ppp);
|
||||
}
|
||||
|
||||
|
|
@ -3161,7 +3165,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
|
|||
if (!ppp->rc_state)
|
||||
break;
|
||||
if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len,
|
||||
ppp->file.index, 0, ppp->mru, ppp->debug)) {
|
||||
ppp->file.index, 0, ppp->mru,
|
||||
READ_ONCE(ppp->debug))) {
|
||||
ppp->rstate |= SC_DECOMP_RUN;
|
||||
ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR);
|
||||
}
|
||||
|
|
@ -3170,7 +3175,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
|
|||
if (!ppp->xc_state)
|
||||
break;
|
||||
if (ppp->xcomp->comp_init(ppp->xc_state, dp, len,
|
||||
ppp->file.index, 0, ppp->debug))
|
||||
ppp->file.index, 0,
|
||||
READ_ONCE(ppp->debug)))
|
||||
ppp->xstate |= SC_COMP_RUN;
|
||||
}
|
||||
break;
|
||||
|
|
@ -3322,8 +3328,8 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
|
|||
st->p.ppp_opackets += tx_packets;
|
||||
st->p.ppp_obytes += tx_bytes;
|
||||
}
|
||||
st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
|
||||
st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
|
||||
st->p.ppp_ierrors = DEV_STATS_READ(ppp->dev, rx_errors);
|
||||
st->p.ppp_oerrors = DEV_STATS_READ(ppp->dev, tx_errors);
|
||||
if (!vj)
|
||||
return;
|
||||
st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
|
||||
|
|
|
|||
|
|
@ -825,6 +825,7 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
|
|||
dev_hard_header(skb, dev, ETH_P_PPP_SES,
|
||||
po->pppoe_pa.remote, NULL, total_len);
|
||||
|
||||
ph = pppoe_hdr(skb);
|
||||
memcpy(ph, &hdr, sizeof(struct pppoe_hdr));
|
||||
|
||||
ph->length = htons(total_len);
|
||||
|
|
|
|||
|
|
@ -693,6 +693,8 @@ static void slip_receive_buf(struct tty_struct *tty, const u8 *cp, const u8 *fp,
|
|||
if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&sl->lock);
|
||||
|
||||
/* Read the characters out of the buffer */
|
||||
while (count--) {
|
||||
if (fp && *fp++) {
|
||||
|
|
@ -708,6 +710,8 @@ static void slip_receive_buf(struct tty_struct *tty, const u8 *cp, const u8 *fp,
|
|||
#endif
|
||||
slip_unesc(sl, *cp++);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&sl->lock);
|
||||
}
|
||||
|
||||
/************************************
|
||||
|
|
|
|||
|
|
@ -1530,7 +1530,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,
|
|||
struct ipv6hdr *ipv6;
|
||||
struct tcphdr *tcp;
|
||||
} hdr;
|
||||
BUG_ON(gdesc->rcd.tcp == 0);
|
||||
|
||||
/* v4/v6/tcp then describe the inner header, which we can't locate. */
|
||||
if ((le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT)) ||
|
||||
gdesc->rcd.tcp == 0)
|
||||
return 0;
|
||||
|
||||
maplen = skb_headlen(skb);
|
||||
if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen))
|
||||
|
|
@ -1544,15 +1548,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,
|
|||
|
||||
hdr.eth = eth_hdr(skb);
|
||||
if (gdesc->rcd.v4) {
|
||||
BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) &&
|
||||
hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP));
|
||||
if (hdr.eth->h_proto != htons(ETH_P_IP) &&
|
||||
hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP))
|
||||
return 0;
|
||||
|
||||
hdr.ptr += hlen;
|
||||
BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP);
|
||||
if (hdr.ipv4->protocol != IPPROTO_TCP)
|
||||
return 0;
|
||||
|
||||
hlen = hdr.ipv4->ihl << 2;
|
||||
hdr.ptr += hdr.ipv4->ihl << 2;
|
||||
} else if (gdesc->rcd.v6) {
|
||||
BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) &&
|
||||
hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6));
|
||||
if (hdr.eth->h_proto != htons(ETH_P_IPV6) &&
|
||||
hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6))
|
||||
return 0;
|
||||
|
||||
hdr.ptr += hlen;
|
||||
/* Use an estimated value, since we also need to handle
|
||||
* TSO case.
|
||||
|
|
|
|||
|
|
@ -4421,6 +4421,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
|
|||
struct vxlan_rdst *dst;
|
||||
int err;
|
||||
|
||||
if (!rtnl_dev_link_net_capable(dev, vxlan->net))
|
||||
return -EPERM;
|
||||
|
||||
dst = &vxlan->default_dst;
|
||||
err = vxlan_nl2conf(tb, data, dev, &conf, true, extack);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ struct vxlan_mdb_remote {
|
|||
};
|
||||
|
||||
#define VXLAN_SGRP_F_DELETE BIT(0)
|
||||
#define VXLAN_SGRP_F_NEW BIT(1)
|
||||
|
||||
struct vxlan_mdb_src_entry {
|
||||
struct hlist_node node;
|
||||
|
|
@ -844,6 +845,7 @@ vxlan_mdb_remote_src_add(const struct vxlan_mdb_config *cfg,
|
|||
ent = vxlan_mdb_remote_src_entry_add(remote, &src->addr);
|
||||
if (!ent)
|
||||
return -ENOMEM;
|
||||
ent->flags |= VXLAN_SGRP_F_NEW;
|
||||
} else if (!(cfg->nlflags & NLM_F_REPLACE)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Source entry already exists");
|
||||
return -EEXIST;
|
||||
|
|
@ -853,15 +855,16 @@ vxlan_mdb_remote_src_add(const struct vxlan_mdb_config *cfg,
|
|||
if (err)
|
||||
goto err_src_del;
|
||||
|
||||
/* Clear flags in case source entry was marked for deletion as part of
|
||||
* replace flow.
|
||||
/* Clear the deletion mark so the entry survives the replace sweep.
|
||||
* The new mark is retained until the whole operation succeeds.
|
||||
*/
|
||||
ent->flags = 0;
|
||||
ent->flags &= ~VXLAN_SGRP_F_DELETE;
|
||||
|
||||
return 0;
|
||||
|
||||
err_src_del:
|
||||
vxlan_mdb_remote_src_entry_del(ent);
|
||||
if (ent->flags & VXLAN_SGRP_F_NEW)
|
||||
vxlan_mdb_remote_src_entry_del(ent);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -889,11 +892,19 @@ static int vxlan_mdb_remote_srcs_add(const struct vxlan_mdb_config *cfg,
|
|||
goto err_src_del;
|
||||
}
|
||||
|
||||
hlist_for_each_entry(ent, &remote->src_list, node)
|
||||
ent->flags &= ~VXLAN_SGRP_F_NEW;
|
||||
|
||||
return 0;
|
||||
|
||||
err_src_del:
|
||||
hlist_for_each_entry_safe(ent, tmp, &remote->src_list, node)
|
||||
vxlan_mdb_remote_src_del(cfg->vxlan, &cfg->group, remote, ent);
|
||||
hlist_for_each_entry_safe(ent, tmp, &remote->src_list, node) {
|
||||
if (ent->flags & VXLAN_SGRP_F_NEW)
|
||||
vxlan_mdb_remote_src_del(cfg->vxlan, &cfg->group, remote,
|
||||
ent);
|
||||
else
|
||||
ent->flags &= ~VXLAN_SGRP_F_DELETE;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1069,7 +1080,7 @@ vxlan_mdb_remote_srcs_replace(const struct vxlan_mdb_config *cfg,
|
|||
|
||||
err = vxlan_mdb_remote_srcs_add(cfg, remote, extack);
|
||||
if (err)
|
||||
goto err_clear_delete;
|
||||
return err;
|
||||
|
||||
hlist_for_each_entry_safe(ent, tmp, &remote->src_list, node) {
|
||||
if (ent->flags & VXLAN_SGRP_F_DELETE)
|
||||
|
|
@ -1078,11 +1089,6 @@ vxlan_mdb_remote_srcs_replace(const struct vxlan_mdb_config *cfg,
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_clear_delete:
|
||||
hlist_for_each_entry(ent, &remote->src_list, node)
|
||||
ent->flags &= ~VXLAN_SGRP_F_DELETE;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vxlan_mdb_remote_replace(const struct vxlan_mdb_config *cfg,
|
||||
|
|
|
|||
|
|
@ -514,7 +514,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)
|
|||
if (card->irq)
|
||||
free_irq(card->irq, card);
|
||||
|
||||
wanxl_reset(card);
|
||||
if (card->plx)
|
||||
wanxl_reset(card);
|
||||
|
||||
for (i = 0; i < RX_QUEUE_LENGTH; i++)
|
||||
if (card->rx_skbs[i]) {
|
||||
|
|
|
|||
|
|
@ -706,6 +706,7 @@ static int ath10k_htt_rx_pop_paddr32_list(struct ath10k_htt *htt,
|
|||
if (!(__le32_to_cpu(rxd_attention->flags) &
|
||||
RX_ATTENTION_FLAGS_MSDU_DONE)) {
|
||||
ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n");
|
||||
__skb_queue_purge(list);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
|
@ -770,6 +771,7 @@ static int ath10k_htt_rx_pop_paddr64_list(struct ath10k_htt *htt,
|
|||
if (!(__le32_to_cpu(rxd_attention->flags) &
|
||||
RX_ATTENTION_FLAGS_MSDU_DONE)) {
|
||||
ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n");
|
||||
__skb_queue_purge(list);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -996,6 +996,7 @@ static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab)
|
|||
ret = ath11k_ahb_setup_msa_resources(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to setup msa resources\n");
|
||||
of_node_put(node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4618,6 +4618,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar,
|
|||
msdu_details = &msdu_link->msdu_link[0];
|
||||
|
||||
for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) {
|
||||
if (!i && FIELD_GET(BUFFER_ADDR_INFO0_ADDR,
|
||||
msdu_details[i].buf_addr_info.info0) == 0)
|
||||
break;
|
||||
if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR,
|
||||
msdu_details[i].buf_addr_info.info0) == 0) {
|
||||
msdu_desc_info = &msdu_details[i - 1].rx_msdu_info;
|
||||
|
|
|
|||
|
|
@ -199,6 +199,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
|
|||
val |= PCIE_SOC_GLOBAL_RESET_V;
|
||||
|
||||
ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
|
||||
/* Flush the posted write to the device */
|
||||
ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);
|
||||
|
||||
/* TODO: exact time to sleep is uncertain */
|
||||
delay = 10;
|
||||
|
|
@ -208,6 +210,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
|
|||
val &= ~PCIE_SOC_GLOBAL_RESET_V;
|
||||
|
||||
ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
|
||||
/* Flush the posted write to the device */
|
||||
ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);
|
||||
|
||||
mdelay(delay);
|
||||
|
||||
|
|
|
|||
|
|
@ -3294,9 +3294,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
|
|||
clear_bit(ATH11K_FLAG_CRASH_FLUSH,
|
||||
&ab->dev_flags);
|
||||
clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
|
||||
ath11k_core_qmi_firmware_ready(ab);
|
||||
set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
||||
|
||||
if (!test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) {
|
||||
ret = ath11k_core_qmi_firmware_ready(ab);
|
||||
if (ret) {
|
||||
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
||||
break;
|
||||
}
|
||||
set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
||||
}
|
||||
break;
|
||||
case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -274,11 +274,14 @@ int ath12k_dp_link_peer_rhash_tbl_init(struct ath12k_dp *dp)
|
|||
|
||||
void ath12k_dp_link_peer_rhash_tbl_destroy(struct ath12k_dp *dp)
|
||||
{
|
||||
mutex_lock(&dp->link_peer_rhash_tbl_lock);
|
||||
guard(mutex)(&dp->link_peer_rhash_tbl_lock);
|
||||
|
||||
if (!dp->rhead_peer_addr)
|
||||
return;
|
||||
|
||||
rhashtable_destroy(dp->rhead_peer_addr);
|
||||
kfree(dp->rhead_peer_addr);
|
||||
dp->rhead_peer_addr = NULL;
|
||||
mutex_unlock(&dp->link_peer_rhash_tbl_lock);
|
||||
}
|
||||
|
||||
static int ath12k_dp_link_peer_rhash_insert(struct ath12k_dp *dp,
|
||||
|
|
@ -570,6 +573,8 @@ int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
|
|||
peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
|
||||
|
||||
rcu_assign_pointer(dp_peer->link_peers[peer->link_id], peer);
|
||||
WRITE_ONCE(dp_peer->link_peers_map,
|
||||
READ_ONCE(dp_peer->link_peers_map) | BIT(peer->link_id));
|
||||
|
||||
rcu_assign_pointer(dp_hw->dp_peers[peerid_index], dp_peer);
|
||||
|
||||
|
|
@ -632,6 +637,8 @@ void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_
|
|||
peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
|
||||
|
||||
rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL);
|
||||
WRITE_ONCE(dp_peer->link_peers_map,
|
||||
READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id));
|
||||
|
||||
rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ struct ath12k_dp_peer {
|
|||
|
||||
/* Info used in MMIC verification of * RX fragments */
|
||||
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
|
||||
unsigned long link_peers_map;
|
||||
struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS];
|
||||
struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
|
||||
struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
|
||||
|
|
|
|||
|
|
@ -1384,10 +1384,9 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc
|
|||
|
||||
pubsta = peer ? peer->sta : NULL;
|
||||
|
||||
if (pubsta && pubsta->valid_links) {
|
||||
status->link_valid = 1;
|
||||
status->link_id = peer->hw_links[rxcb->hw_link_id];
|
||||
}
|
||||
status->link_valid = 0;
|
||||
if (pubsta && pubsta->valid_links)
|
||||
ath12k_hw_set_rx_link_id(dp->hw_params, peer, rxcb, status);
|
||||
|
||||
ath12k_dbg(dp->ab, ATH12K_DBG_DATA,
|
||||
"rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@
|
|||
#include "wmi.h"
|
||||
#include "hal.h"
|
||||
|
||||
struct ath12k_dp_peer;
|
||||
struct ath12k_skb_rxcb;
|
||||
struct ieee80211_rx_status;
|
||||
|
||||
/* Target configuration defines */
|
||||
|
||||
/* Num VDEVS per radio */
|
||||
|
|
@ -243,6 +247,9 @@ struct ath12k_hw_ops {
|
|||
bool (*dp_srng_is_tx_comp_ring)(int ring_num);
|
||||
bool (*is_frame_link_agnostic)(struct ath12k_link_vif *arvif,
|
||||
struct ieee80211_mgmt *mgmt);
|
||||
void (*set_rx_link_id)(struct ath12k_dp_peer *dp_peer,
|
||||
struct ath12k_skb_rxcb *rxcb,
|
||||
struct ieee80211_rx_status *status);
|
||||
};
|
||||
|
||||
static inline
|
||||
|
|
@ -273,6 +280,15 @@ static inline int ath12k_hw_mac_id_to_srng_id(const struct ath12k_hw_params *hw,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath12k_hw_set_rx_link_id(const struct ath12k_hw_params *hw,
|
||||
struct ath12k_dp_peer *dp_peer,
|
||||
struct ath12k_skb_rxcb *rxcb,
|
||||
struct ieee80211_rx_status *status)
|
||||
{
|
||||
if (hw->hw_ops->set_rx_link_id)
|
||||
hw->hw_ops->set_rx_link_id(dp_peer, rxcb, status);
|
||||
}
|
||||
|
||||
struct ath12k_fw_ie {
|
||||
__le32 id;
|
||||
__le32 len;
|
||||
|
|
|
|||
|
|
@ -1238,9 +1238,13 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
|
|||
/* cleanup dp peer */
|
||||
spin_lock_bh(&dp_hw->peer_lock);
|
||||
dp_peer = peer->dp_peer;
|
||||
peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
|
||||
rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL);
|
||||
rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL);
|
||||
if (dp_peer) {
|
||||
peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
|
||||
rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL);
|
||||
WRITE_ONCE(dp_peer->link_peers_map,
|
||||
READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id));
|
||||
rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL);
|
||||
}
|
||||
spin_unlock_bh(&dp_hw->peer_lock);
|
||||
|
||||
ath12k_dp_link_peer_rhash_delete(dp, peer);
|
||||
|
|
|
|||
|
|
@ -188,6 +188,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab)
|
|||
val |= PCIE_SOC_GLOBAL_RESET_V;
|
||||
|
||||
ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
|
||||
/* Flush the posted write to the device */
|
||||
ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
|
||||
|
||||
/* TODO: exact time to sleep is uncertain */
|
||||
delay = 10;
|
||||
|
|
@ -197,6 +199,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab)
|
|||
val &= ~PCIE_SOC_GLOBAL_RESET_V;
|
||||
|
||||
ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
|
||||
/* Flush the posted write to the device */
|
||||
ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
|
||||
|
||||
mdelay(delay);
|
||||
|
||||
|
|
|
|||
|
|
@ -453,6 +453,9 @@ int ath12k_link_sta_rhash_tbl_init(struct ath12k_base *ab)
|
|||
|
||||
void ath12k_link_sta_rhash_tbl_destroy(struct ath12k_base *ab)
|
||||
{
|
||||
if (!ab->rhead_sta_addr)
|
||||
return;
|
||||
|
||||
rhashtable_destroy(ab->rhead_sta_addr);
|
||||
kfree(ab->rhead_sta_addr);
|
||||
ab->rhead_sta_addr = NULL;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "dp_rx.h"
|
||||
#include "../dp_peer.h"
|
||||
#include "../dp_tx.h"
|
||||
#include "../peer.h"
|
||||
#include "hal_qcn9274.h"
|
||||
|
|
@ -2315,3 +2316,35 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
|
|||
|
||||
return tlv_tag == HAL_RX_MPDU_START;
|
||||
}
|
||||
|
||||
void
|
||||
ath12k_wifi7_dp_rx_set_link_id_qcn9274(struct ath12k_dp_peer *dp_peer,
|
||||
struct ath12k_skb_rxcb *rxcb,
|
||||
struct ieee80211_rx_status *status)
|
||||
{
|
||||
status->link_valid = 1;
|
||||
status->link_id = dp_peer->hw_links[rxcb->hw_link_id];
|
||||
}
|
||||
|
||||
void
|
||||
ath12k_wifi7_dp_rx_set_link_id_wcn7850(struct ath12k_dp_peer *dp_peer,
|
||||
struct ath12k_skb_rxcb *rxcb,
|
||||
struct ieee80211_rx_status *status)
|
||||
{
|
||||
struct ath12k_dp_link_peer *link_peer;
|
||||
unsigned long links_map;
|
||||
int i;
|
||||
|
||||
RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
|
||||
"ath12k set rx link id called without rcu lock");
|
||||
|
||||
links_map = READ_ONCE(dp_peer->link_peers_map);
|
||||
for_each_set_bit(i, &links_map, ATH12K_NUM_MAX_LINKS) {
|
||||
link_peer = rcu_dereference(dp_peer->link_peers[i]);
|
||||
if (link_peer && link_peer->peer_id == rxcb->peer_id) {
|
||||
status->link_valid = 1;
|
||||
status->link_id = link_peer->link_id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,4 +57,10 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
|
|||
struct hal_rx_desc *rx_desc);
|
||||
int ath12k_wifi7_dp_rx_tid_delete_handler(struct ath12k_base *ab,
|
||||
struct ath12k_dp_rx_tid_rxq *rx_tid);
|
||||
void ath12k_wifi7_dp_rx_set_link_id_qcn9274(struct ath12k_dp_peer *dp_peer,
|
||||
struct ath12k_skb_rxcb *rxcb,
|
||||
struct ieee80211_rx_status *status);
|
||||
void ath12k_wifi7_dp_rx_set_link_id_wcn7850(struct ath12k_dp_peer *dp_peer,
|
||||
struct ath12k_skb_rxcb *rxcb,
|
||||
struct ieee80211_rx_status *status);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ static const struct ath12k_hw_ops qcn9274_ops = {
|
|||
.get_ring_selector = ath12k_wifi7_hw_get_ring_selector_qcn9274,
|
||||
.dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_qcn9274,
|
||||
.is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_qcn9274,
|
||||
.set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_qcn9274,
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_ops wcn7850_ops = {
|
||||
|
|
@ -168,6 +169,7 @@ static const struct ath12k_hw_ops wcn7850_ops = {
|
|||
.get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850,
|
||||
.dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850,
|
||||
.is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850,
|
||||
.set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850,
|
||||
};
|
||||
|
||||
static const struct ath12k_hw_ops qcc2072_ops = {
|
||||
|
|
@ -178,6 +180,7 @@ static const struct ath12k_hw_ops qcc2072_ops = {
|
|||
.get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850,
|
||||
.dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850,
|
||||
.is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850,
|
||||
.set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850,
|
||||
};
|
||||
|
||||
#define ATH12K_TX_RING_MASK_0 0x1
|
||||
|
|
|
|||
|
|
@ -1723,13 +1723,15 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no,
|
|||
|
||||
rxtid = &aggr_conn->rx_tid[tid];
|
||||
|
||||
if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX)
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n",
|
||||
__func__, win_sz, tid);
|
||||
|
||||
if (rxtid->aggr)
|
||||
aggr_delete_tid_state(aggr_conn, tid);
|
||||
|
||||
if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n",
|
||||
__func__, win_sz, tid);
|
||||
return;
|
||||
}
|
||||
|
||||
rxtid->seq_next = seq_no;
|
||||
hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q);
|
||||
rxtid->hold_q = kzalloc(hold_q_size, GFP_KERNEL);
|
||||
|
|
@ -1828,7 +1830,7 @@ void aggr_reset_state(struct aggr_info_conn *aggr_conn)
|
|||
return;
|
||||
|
||||
if (aggr_conn->timer_scheduled) {
|
||||
timer_delete(&aggr_conn->timer);
|
||||
timer_delete_sync(&aggr_conn->timer);
|
||||
aggr_conn->timer_scheduled = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
|
|||
|
||||
evt = (struct wmi_tx_complete_event *) datap;
|
||||
|
||||
if (len < sizeof(*evt)) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d\n",
|
||||
len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len < sizeof(*evt) + evt->num_msg * sizeof(struct tx_complete_msg_v1)) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d for %u msgs\n",
|
||||
len, evt->num_msg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n",
|
||||
evt->num_msg, evt->msg_len, evt->msg_type);
|
||||
|
||||
|
|
@ -862,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len,
|
|||
|
||||
ev = (struct wmi_connect_event *) datap;
|
||||
|
||||
if (len < sizeof(*ev) + ev->beacon_ie_len +
|
||||
ev->assoc_req_len + ev->assoc_resp_len) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"connect event: IE lengths %u+%u+%u exceed buffer %d\n",
|
||||
ev->beacon_ie_len, ev->assoc_req_len,
|
||||
ev->assoc_resp_len, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (vif->nw_type == AP_NETWORK) {
|
||||
/* AP mode start/STA connected event */
|
||||
struct net_device *dev = vif->ndev;
|
||||
|
|
|
|||
|
|
@ -1215,15 +1215,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev,
|
|||
ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name,
|
||||
&hif_dev->udev->dev, GFP_KERNEL,
|
||||
hif_dev, ath9k_hif_usb_firmware_cb);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Async request for firmware %s failed\n",
|
||||
hif_dev->fw_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n",
|
||||
hif_dev->fw_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)
|
|||
spin_lock(&ar->cmd_lock);
|
||||
if (ar->readbuf) {
|
||||
if (len >= 4)
|
||||
memcpy(ar->readbuf, buffer + 4, len - 4);
|
||||
memcpy(ar->readbuf, buffer + 4,
|
||||
min_t(u32, len - 4, ar->readlen));
|
||||
|
||||
ar->readbuf = NULL;
|
||||
}
|
||||
|
|
@ -917,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
|
|||
}
|
||||
}
|
||||
|
||||
skb_put_data(ar->rx_failover, tbuf, tlen);
|
||||
skb_put_data(ar->rx_failover, tbuf,
|
||||
min_t(unsigned int, tlen,
|
||||
ar->rx_failover_missing));
|
||||
ar->rx_failover_missing -= tlen;
|
||||
|
||||
if (ar->rx_failover_missing <= 0) {
|
||||
|
|
|
|||
|
|
@ -692,7 +692,7 @@ void carl9170_tx_process_status(struct ar9170 *ar,
|
|||
unsigned int i;
|
||||
|
||||
for (i = 0; i < cmd->hdr.ext; i++) {
|
||||
if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) {
|
||||
if (WARN_ON(i >= (cmd->hdr.len / 2))) {
|
||||
print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE,
|
||||
(void *) cmd, cmd->hdr.len + 4);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1521,13 +1521,16 @@ static inline int at76_guess_freq(struct at76_priv *priv)
|
|||
|
||||
if (ieee80211_is_probe_resp(hdr->frame_control)) {
|
||||
el_off = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
|
||||
el = ((struct ieee80211_mgmt *)hdr)->u.probe_resp.variable;
|
||||
} else if (ieee80211_is_beacon(hdr->frame_control)) {
|
||||
el_off = offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
||||
el = ((struct ieee80211_mgmt *)hdr)->u.beacon.variable;
|
||||
} else {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (len < el_off)
|
||||
goto exit;
|
||||
|
||||
el = priv->rx_skb->data + el_off;
|
||||
len -= el_off;
|
||||
|
||||
el = cfg80211_find_ie(WLAN_EID_DS_PARAMS, el, len);
|
||||
|
|
|
|||
|
|
@ -911,6 +911,7 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
|
|||
return ret;
|
||||
}
|
||||
switch (sdiodev->func2->device) {
|
||||
case SDIO_DEVICE_ID_BROADCOM_43752:
|
||||
case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
|
||||
f2_blksz = SDIO_4373_FUNC2_BLOCKSIZE;
|
||||
break;
|
||||
|
|
@ -1069,6 +1070,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
|||
bus_if = kzalloc_obj(*bus_if);
|
||||
if (!bus_if)
|
||||
return -ENOMEM;
|
||||
mutex_init(&bus_if->bus_reset_lock);
|
||||
sdiodev = kzalloc_obj(*sdiodev);
|
||||
if (!sdiodev) {
|
||||
kfree(bus_if);
|
||||
|
|
@ -1130,6 +1132,14 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
|
|||
if (func->num != 1)
|
||||
return;
|
||||
|
||||
/* Drain bus_reset before the shared brcmf_sdiod_remove()
|
||||
* teardown, which the SDIO reset callback also reaches. The
|
||||
* data worker can arm bus_reset via brcmf_fw_crashed(); cancel
|
||||
* it first.
|
||||
*/
|
||||
brcmf_sdio_cancel_datawork(sdiodev->bus);
|
||||
brcmf_bus_cancel_reset_work(bus_if);
|
||||
|
||||
/* only proceed with rest of cleanup if func 1 */
|
||||
brcmf_sdiod_remove(sdiodev);
|
||||
|
||||
|
|
@ -1204,6 +1214,8 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
|
|||
} else {
|
||||
/* power will be cut so remove device, probe again in resume */
|
||||
brcmf_sdiod_intr_unregister(sdiodev);
|
||||
brcmf_sdio_cancel_datawork(sdiodev->bus);
|
||||
brcmf_bus_cancel_reset_work(bus_if);
|
||||
ret = brcmf_sdiod_remove(sdiodev);
|
||||
if (ret)
|
||||
brcmf_err("Failed to remove device on suspend\n");
|
||||
|
|
@ -1229,6 +1241,8 @@ static int brcmf_ops_sdio_resume(struct device *dev)
|
|||
ret = brcmf_sdiod_probe(sdiodev);
|
||||
if (ret)
|
||||
brcmf_err("Failed to probe device on resume\n");
|
||||
else
|
||||
brcmf_bus_allow_reset_work(bus_if);
|
||||
} else {
|
||||
if (sdiodev->wowl_enabled && sdiodev->settings->bus.sdio.oob_irq_supported)
|
||||
disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include "debug.h"
|
||||
|
||||
/* IDs of the 6 default common rings of msgbuf protocol */
|
||||
|
|
@ -179,6 +180,8 @@ struct brcmf_bus {
|
|||
enum brcmf_fwvendor fwvid;
|
||||
bool always_use_fws_queue;
|
||||
bool wowl_supported;
|
||||
bool removing; /* device removal in progress; quiesce async work */
|
||||
struct mutex bus_reset_lock;
|
||||
|
||||
const struct brcmf_bus_ops *ops;
|
||||
struct brcmf_bus_msgbuf *msgbuf;
|
||||
|
|
@ -186,6 +189,9 @@ struct brcmf_bus {
|
|||
struct list_head list;
|
||||
};
|
||||
|
||||
void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if);
|
||||
void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if);
|
||||
|
||||
/*
|
||||
* callback wrappers
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2146,7 +2146,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
|
|||
sme->crypto.akm_suites[0]);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
|
||||
} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_1X_SHA256)) {
|
||||
switch (sme->crypto.akm_suites[0]) {
|
||||
case WLAN_AKM_SUITE_8021X:
|
||||
val = WPA2_AUTH_UNSPECIFIED;
|
||||
|
|
|
|||
|
|
@ -1167,6 +1167,35 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Serialize arming from debugfs reset and brcmf_fw_crashed() against
|
||||
* teardown. The remove path sets ->removing and drains the work while
|
||||
* holding bus_reset_lock, so a racing armer is either drained or skips it.
|
||||
*/
|
||||
static void brcmf_bus_schedule_reset(struct brcmf_bus *bus_if)
|
||||
{
|
||||
mutex_lock(&bus_if->bus_reset_lock);
|
||||
if (bus_if->drvr && bus_if->drvr->bus_reset.func && !bus_if->removing)
|
||||
schedule_work(&bus_if->drvr->bus_reset);
|
||||
mutex_unlock(&bus_if->bus_reset_lock);
|
||||
}
|
||||
|
||||
void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if)
|
||||
{
|
||||
mutex_lock(&bus_if->bus_reset_lock);
|
||||
bus_if->removing = true;
|
||||
if (bus_if->drvr)
|
||||
cancel_work_sync(&bus_if->drvr->bus_reset);
|
||||
mutex_unlock(&bus_if->bus_reset_lock);
|
||||
}
|
||||
|
||||
void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if)
|
||||
{
|
||||
mutex_lock(&bus_if->bus_reset_lock);
|
||||
bus_if->removing = false;
|
||||
mutex_unlock(&bus_if->bus_reset_lock);
|
||||
}
|
||||
|
||||
static void brcmf_core_bus_reset(struct work_struct *work)
|
||||
{
|
||||
struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
|
||||
|
|
@ -1187,7 +1216,7 @@ static ssize_t bus_reset_write(struct file *file, const char __user *user_buf,
|
|||
if (value != 1)
|
||||
return -EINVAL;
|
||||
|
||||
schedule_work(&drvr->bus_reset);
|
||||
brcmf_bus_schedule_reset(drvr->bus_if);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
@ -1417,14 +1446,23 @@ void brcmf_dev_coredump(struct device *dev)
|
|||
void brcmf_fw_crashed(struct device *dev)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_pub *drvr;
|
||||
|
||||
/* May fire before brcmf_attach() wires up drvr, or after removal
|
||||
* has cleared it; guard the derefs below (and the arming gate in
|
||||
* brcmf_bus_schedule_reset() already checks drvr/->removing).
|
||||
*/
|
||||
if (!bus_if)
|
||||
return;
|
||||
drvr = bus_if->drvr;
|
||||
if (!drvr)
|
||||
return;
|
||||
|
||||
bphy_err(drvr, "Firmware has halted or crashed\n");
|
||||
|
||||
brcmf_dev_coredump(dev);
|
||||
|
||||
if (drvr->bus_reset.func)
|
||||
schedule_work(&drvr->bus_reset);
|
||||
brcmf_bus_schedule_reset(bus_if);
|
||||
}
|
||||
|
||||
void brcmf_detach(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -1383,16 +1383,20 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
|
|||
static void
|
||||
brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)
|
||||
{
|
||||
if (devinfo->shared.scratch)
|
||||
if (devinfo->shared.scratch) {
|
||||
dma_free_coherent(&devinfo->pdev->dev,
|
||||
BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
|
||||
devinfo->shared.scratch,
|
||||
devinfo->shared.scratch_dmahandle);
|
||||
if (devinfo->shared.ringupd)
|
||||
devinfo->shared.scratch = NULL;
|
||||
}
|
||||
if (devinfo->shared.ringupd) {
|
||||
dma_free_coherent(&devinfo->pdev->dev,
|
||||
BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
|
||||
devinfo->shared.ringupd,
|
||||
devinfo->shared.ringupd_dmahandle);
|
||||
devinfo->shared.ringupd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
|
||||
|
|
@ -2499,6 +2503,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
mutex_init(&bus->bus_reset_lock);
|
||||
bus->msgbuf = kzalloc_obj(*bus->msgbuf);
|
||||
if (!bus->msgbuf) {
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -2594,6 +2599,11 @@ brcmf_pcie_remove(struct pci_dev *pdev)
|
|||
if (devinfo->ci)
|
||||
brcmf_pcie_intr_disable(devinfo);
|
||||
|
||||
if (devinfo->irq_allocated)
|
||||
synchronize_irq(pdev->irq);
|
||||
|
||||
brcmf_bus_cancel_reset_work(bus);
|
||||
|
||||
brcmf_detach(&pdev->dev);
|
||||
brcmf_free(&pdev->dev);
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user