mirror of
https://github.com/torvalds/linux.git
synced 2026-09-11 20:13:02 +02:00
Nothing too exciting, usual stream of fixes.
Including fixes from Netfilter, Bluetooth and WPAN.
Current release - new code bugs:
- Bluetooth: hci_sync: fix not setting CE length properly
- eth: enic: match mailbox replies to request numbers
Previous releases - regressions:
- tunnels: drop stale dst when building an ICMP error for PMTUD
- ipv6: null-check fib6_node before accessing in __ip6_del_rt_siblings()
(bug in the rtnl_lock -> RCU conversion)
- eth: bnxt_en: fix crashes on Thor2 due to OOB coalescing buffer accesses
- eth: bnxt_en: prevent queue stop with deferred completions
Previous releases - always broken:
- eth: ice: don't dereference pointers from TP_printk()
- eth: fix OOB writes on ethtool flow rule dump in 3 drivers
- eth: mlx5: fix FEC configuration with RS_544_514_INTERLEAVED_QUAD
- dsa: tag_brcm: legacy FCS: request needed tailroom
Misc:
- net: cap tx_queue_len at S16_MAX to prevent oversized ring alloc
- ipv6: flowlabel: cap duplicate leases per socket
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmqi3pQACgkQMUZtbf5S
IrvUIg//X9nIxY2F5PzJ5jD9p5ccXrQMLe7kT5AW2tP5PDC8d5PIv4Q5XzFKQPU7
XElAUKvBxmofwU2lqILYGi8AeUpqHZtKPY7XzKeqd6i72KOD6mGzzYNijqttBXcM
vFVtIeKExXjAwvNc2as1SeXVEAAAkBtrCFuMNHMq0C56yK4md/XVkCDHaJkomNit
geke1U8gut3rZddWKxp4WDbL8Wmx9yM0uDMBznO/+cwITObA0Hme3IgRndglzz7n
n4Ih+EG4tRrD3kUf6oePzKQ47cd+qnSVlVTCZUwB5E/HKqWJFXxSN4Sv+mez0sAS
rrI5hl+luNKUYrZ8/jiNlvajgAL4+AYpCKPDJbXrOW+z+x4BC2VYZBAHLoUr5ZAq
Z5OYU9SgD1oGntqkI8mAEiRTEu+4gjhIEhjENHEzqdjUogaBIp7MWwCrNBAnFWvs
2McmNfZZMVhxKpyYnndUStsVQySVPASb0CXeqTIO6PJsAp/HBjoMYKYKPhhwk0Gp
lE8zHjEnPVofRfXfT+oZnbS8is2nC9FjBy9ksIGcC7vyTOdPsoIBoB8JY0x/INRM
SOJvyxrdnVkMjiBejkdOa5X9HbD1cA/NVyzT2WEaZBGPmIqfNBgUIOxnXD4CShuy
9zX8qtHsUmmYxPteF30Uhfe0kyLQ9OnjUz2Bl++EruxpIE3+i48=
=f9J9
-----END PGP SIGNATURE-----
Merge tag 'net-7.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Nothing too exciting, usual stream of fixes. Including fixes from
Netfilter, Bluetooth and WPAN.
Current release - new code bugs:
- Bluetooth: hci_sync: fix not setting CE length properly
- eth: enic: match mailbox replies to request numbers
Previous releases - regressions:
- tunnels: drop stale dst when building an ICMP error for PMTUD
- ipv6: null-check fib6_node before accessing in __ip6_del_rt_siblings()
(bug in the rtnl_lock -> RCU conversion)
- eth: bnxt_en:
- fix crashes on Thor2 due to OOB coalescing buffer accesses
- prevent queue stop with deferred completions
Previous releases - always broken:
- eth:
- ice: don't dereference pointers from TP_printk()
- fix OOB writes on ethtool flow rule dump in 3 drivers
- mlx5: fix FEC configuration with RS_544_514_INTERLEAVED_QUAD
- dsa: tag_brcm: legacy FCS: request needed tailroom
Misc:
- net: cap tx_queue_len at S16_MAX to prevent oversized ring alloc
- ipv6: flowlabel: cap duplicate leases per socket"
* tag 'net-7.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (164 commits)
selftests: tc-testing: test action batch failure cleanup
net/sched: act_api: release all action references on NEWACTION failure
openvswitch: fix wrong flag value in get_ipv6_ext_hdrs()
ipmr: account multicast table and route memory
net: phy: dp83td510: handle the active-high LED polarity mode
net: macb: initialize PTP state before registering clock
net: hsr: enable promiscuous mode on interlink port with fwd offload
ipv6: fix fib6 walker UAF on seq stop
net: stmmac: fix TX descriptor availability check for TSO traffic
net/rds: fix tcp stream corruption with large pages
net: mana: restore the XDP program pointer when pre-allocation fails
net: phy: dp83867: handle the active-high LED polarity mode
octeontx2-af: fix PF/CGX debugfs PCI bus lookup
net: net_failover: Fix the deadlock in net_failover_slave_name_change()
net: phy: mediatek-ge: disable EEE on the MT7530 PHY
tcp: reject non zerocopy devmem tx
net: ethernet: mtk_eth_soc: populate lpi_interfaces to fix EEE support
net: dsa: mt7530: populate lpi_interfaces to fix EEE support
net: hinic: fix mailbox segment buffer overflow
net: sun4i-emac: fix missing of_node_put() for phy_node
...
This commit is contained in:
commit
7844502343
3
.mailmap
3
.mailmap
|
|
@ -551,6 +551,9 @@ Li Yang <leoyang.li@nxp.com> <leo@zh-kernel.org>
|
|||
Lior David <quic_liord@quicinc.com> <liord@codeaurora.org>
|
||||
Loic Poulain <loic.poulain@oss.qualcomm.com> <loic.poulain@linaro.org>
|
||||
Loic Poulain <loic.poulain@oss.qualcomm.com> <loic.poulain@intel.com>
|
||||
Lorenzo Bianconi <lorenzo@kernel.org> <lorenzo.bianconi@redhat.com>
|
||||
Lorenzo Bianconi <lorenzo@kernel.org> <lorenzo.bianconi@st.com>
|
||||
Lorenzo Bianconi <lorenzo@kernel.org> <lorenzo.bianconi83@gmail.com>
|
||||
Lorenzo Pieralisi <lpieralisi@kernel.org> <lorenzo.pieralisi@arm.com>
|
||||
Lorenzo Stoakes <ljs@kernel.org> <lstoakes@gmail.com>
|
||||
Lorenzo Stoakes <ljs@kernel.org> <lorenzo.stoakes@oracle.com>
|
||||
|
|
|
|||
|
|
@ -898,6 +898,8 @@ attribute-sets:
|
|||
-
|
||||
name: txqlen
|
||||
type: u32
|
||||
checks:
|
||||
max: 32767
|
||||
-
|
||||
name: map
|
||||
type: binary
|
||||
|
|
|
|||
|
|
@ -25336,8 +25336,8 @@ F: Documentation/networking/timestamping.rst
|
|||
F: include/linux/net_tstamp.h
|
||||
F: include/uapi/linux/net_tstamp.h
|
||||
F: tools/testing/selftests/bpf/*/net_timestamping*
|
||||
F: tools/testing/selftests/drivers/net/so_txtime.*
|
||||
F: tools/testing/selftests/net/*timestamp*
|
||||
F: tools/testing/selftests/net/so_txtime.c
|
||||
|
||||
SOEKRIS NET48XX LED SUPPORT
|
||||
M: Chris Boot <bootc@bootc.net>
|
||||
|
|
|
|||
|
|
@ -1099,7 +1099,7 @@ static void btintel_pcie_msix_tx_handle(struct btintel_pcie_data *data)
|
|||
|
||||
urbd0 = &txq->urbd0s[cr_tia];
|
||||
|
||||
if (urbd0->tfd_index > txq->count)
|
||||
if (urbd0->tfd_index >= txq->count)
|
||||
return;
|
||||
|
||||
cr_tia = (cr_tia + 1) % txq->count;
|
||||
|
|
@ -1599,7 +1599,9 @@ static int btintel_pcie_submit_rx_work(struct btintel_pcie_data *data, u8 status
|
|||
rfh_hdr = buf;
|
||||
|
||||
len = rfh_hdr->packet_len;
|
||||
if (len <= 0) {
|
||||
if (len == 0 || len > BTINTEL_PCIE_BUFFER_SIZE - sizeof(*rfh_hdr)) {
|
||||
bt_dev_err(data->hdev, "Invalid packet_len %d (max %zu)", len,
|
||||
BTINTEL_PCIE_BUFFER_SIZE - sizeof(*rfh_hdr));
|
||||
ret = -EINVAL;
|
||||
goto resubmit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1374,16 +1374,6 @@ int btmtk_usb_setup(struct hci_dev *hdev)
|
|||
break;
|
||||
case 0x7922:
|
||||
case 0x7925:
|
||||
/*
|
||||
* A remote wakeup could cause the device completely unresponsive, and
|
||||
* recovering from such a state needs a power cycle.
|
||||
*
|
||||
* Since the remote wakeup capability is super broken, just disable it
|
||||
* to get rid of the troubles. The device can still be autosuspended
|
||||
* when the bluetooth interface is closed.
|
||||
*/
|
||||
device_set_wakeup_capable(&btmtk_data->udev->dev, false);
|
||||
fallthrough;
|
||||
case 0x7961:
|
||||
case 0x7902:
|
||||
case 0x6639:
|
||||
|
|
@ -1587,5 +1577,6 @@ MODULE_FIRMWARE(FIRMWARE_MT7663);
|
|||
MODULE_FIRMWARE(FIRMWARE_MT7668);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7922);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7961);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7920);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7925);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7927);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define FIRMWARE_MT7922 "mediatek/BT_RAM_CODE_MT7922_1_1_hdr.bin"
|
||||
#define FIRMWARE_MT7902 "mediatek/BT_RAM_CODE_MT7902_1_1_hdr.bin"
|
||||
#define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
|
||||
#define FIRMWARE_MT7920 "mediatek/BT_RAM_CODE_MT7961_1a_2_hdr.bin"
|
||||
#define FIRMWARE_MT7925 "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin"
|
||||
#define FIRMWARE_MT7927 "mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin"
|
||||
|
||||
|
|
|
|||
|
|
@ -188,7 +188,10 @@ static int btqcomsmd_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
hci_free_dev:
|
||||
rpmsg_destroy_ept(btq->cmd_channel);
|
||||
rpmsg_destroy_ept(btq->acl_channel);
|
||||
hci_free_dev(hdev);
|
||||
return ret;
|
||||
destroy_cmd_channel:
|
||||
rpmsg_destroy_ept(btq->cmd_channel);
|
||||
destroy_acl_channel:
|
||||
|
|
@ -202,10 +205,11 @@ static void btqcomsmd_remove(struct platform_device *pdev)
|
|||
struct btqcomsmd *btq = platform_get_drvdata(pdev);
|
||||
|
||||
hci_unregister_dev(btq->hdev);
|
||||
hci_free_dev(btq->hdev);
|
||||
|
||||
rpmsg_destroy_ept(btq->cmd_channel);
|
||||
rpmsg_destroy_ept(btq->acl_channel);
|
||||
|
||||
hci_free_dev(btq->hdev);
|
||||
}
|
||||
|
||||
static const struct of_device_id btqcomsmd_of_match[] = {
|
||||
|
|
|
|||
|
|
@ -591,7 +591,7 @@ static int rtlbt_parse_firmware_v2(struct hci_dev *hdev,
|
|||
* headers.
|
||||
*/
|
||||
if (!key_id)
|
||||
break;
|
||||
continue;
|
||||
rc = btrtl_parse_section(hdev, btrtl_dev, opcode,
|
||||
ptr, section_len);
|
||||
break;
|
||||
|
|
@ -600,8 +600,7 @@ static int rtlbt_parse_firmware_v2(struct hci_dev *hdev,
|
|||
ptr, section_len);
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (rc < 0) {
|
||||
rtl_dev_err(hdev, "RTL: Parse section (%u) err %d",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
* Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
|
||||
*/
|
||||
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
|
@ -980,6 +981,8 @@ struct btqca_data {
|
|||
#define BTUSB_USE_ALT3_FOR_WBS 15
|
||||
#define BTUSB_ALT6_CONTINUOUS_TX 16
|
||||
#define BTUSB_HW_SSR_ACTIVE 17
|
||||
#define BTUSB_WAKEUP_BROKEN 18
|
||||
#define BTUSB_RESET 19
|
||||
|
||||
struct btusb_data {
|
||||
struct hci_dev *hdev;
|
||||
|
|
@ -1054,13 +1057,15 @@ static void btusb_reset(struct hci_dev *hdev)
|
|||
int err;
|
||||
|
||||
data = hci_get_drvdata(hdev);
|
||||
/* This is not an unbalanced PM reference since the device will reset */
|
||||
err = usb_autopm_get_interface(data->intf);
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_and_set_bit(BTUSB_RESET, &data->flags))
|
||||
usb_autopm_put_interface_no_suspend(data->intf);
|
||||
|
||||
bt_dev_err(hdev, "Resetting usb device.");
|
||||
usb_queue_reset_device(data->intf);
|
||||
}
|
||||
|
|
@ -2092,18 +2097,24 @@ static int btusb_close(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
cancel_delayed_work(&data->rx_work);
|
||||
cancel_work_sync(&data->work);
|
||||
cancel_work_sync(&data->waker);
|
||||
|
||||
skb_queue_purge(&data->acl_q);
|
||||
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
||||
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
|
||||
clear_bit(BTUSB_DIAG_RUNNING, &data->flags);
|
||||
|
||||
btusb_stop_traffic(data);
|
||||
|
||||
/* rx_work must only be canceled once the URBs that can rearm it are
|
||||
* gone, and it must be canceled synchronously since btusb_disconnect()
|
||||
* frees the btusb_data it dereferences right after hci_unregister_dev().
|
||||
*/
|
||||
cancel_delayed_work_sync(&data->rx_work);
|
||||
|
||||
skb_queue_purge(&data->acl_q);
|
||||
|
||||
btusb_free_frags(data);
|
||||
|
||||
err = usb_autopm_get_interface(data->intf);
|
||||
|
|
@ -2129,7 +2140,7 @@ static int btusb_flush(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
cancel_delayed_work(&data->rx_work);
|
||||
cancel_delayed_work_sync(&data->rx_work);
|
||||
|
||||
skb_queue_purge(&data->acl_q);
|
||||
|
||||
|
|
@ -2923,8 +2934,11 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
|
|||
}
|
||||
|
||||
err = usb_autopm_get_interface(data->intf);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err);
|
||||
clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Release MediaTek ISO data interface */
|
||||
btusb_mtk_release_iso_intf(hdev);
|
||||
|
|
@ -2946,6 +2960,11 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
|
|||
|
||||
err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id);
|
||||
|
||||
if (test_and_set_bit(BTUSB_RESET, &data->flags)) {
|
||||
bt_dev_err(hdev, "last usb reset failed? Resetting again");
|
||||
usb_autopm_put_interface_no_suspend(data->intf);
|
||||
}
|
||||
|
||||
usb_queue_reset_device(data->intf);
|
||||
clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
|
||||
|
||||
|
|
@ -2969,10 +2988,25 @@ static int btusb_send_frame_mtk(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
|
||||
static inline bool platform_is_ryzen(void)
|
||||
{
|
||||
#ifdef CONFIG_X86
|
||||
return boot_cpu_has(X86_FEATURE_ZEN);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool is_direct_child_of_root_hub(struct usb_device *udev)
|
||||
{
|
||||
return udev->parent == udev->bus->root_hub;
|
||||
}
|
||||
|
||||
static int btusb_mtk_setup(struct hci_dev *hdev)
|
||||
{
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
|
||||
int err;
|
||||
|
||||
/* MediaTek WMT vendor cmd requiring below USB resources to
|
||||
* complete the handshake.
|
||||
|
|
@ -2989,7 +3023,40 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
|
|||
btusb_mtk_claim_iso_intf(data);
|
||||
}
|
||||
|
||||
return btmtk_usb_setup(hdev);
|
||||
err = btmtk_usb_setup(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (btmtk_data->dev_id) {
|
||||
case 0x7922:
|
||||
case 0x7925:
|
||||
/*
|
||||
* All reports seen to be relevant to Ryzen-based laptops. These
|
||||
* NICs are usually used as OEM components thanks to some sort
|
||||
* of reference designs.
|
||||
*
|
||||
* Their popularity on other platforms is unclear. While there
|
||||
* is still a chance that the quirk may exist on other
|
||||
* platforms, be cautious and only apply the quirk to direct
|
||||
* children of Ryzen platforms's root hubs for the time being.
|
||||
*
|
||||
* In most cases the root hub is on the SoC or PCH, which needs
|
||||
* the quirk. Unfortunately, this can't distinguish root hubs on
|
||||
* PCIe add-in cards. Such roughness should be acceptable, as
|
||||
* PCIe USB controller add-in cards are less commonly used
|
||||
* nowadays. On the other hand, applying the quirk doesn't hurt
|
||||
* any functionalities either, as the device can still be used
|
||||
* as a wakeup source if desired.
|
||||
*
|
||||
* Theoretically, we could retrieve the root hub's PCI vendor ID
|
||||
* with some hierarchy magic, but that's too intrusive...
|
||||
*/
|
||||
if (platform_is_ryzen() && is_direct_child_of_root_hub(data->udev))
|
||||
set_bit(BTUSB_WAKEUP_BROKEN, &data->flags);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btusb_mtk_shutdown(struct hci_dev *hdev)
|
||||
|
|
@ -4540,6 +4607,9 @@ static void btusb_disconnect(struct usb_interface *intf)
|
|||
if (data->reset_gpio)
|
||||
gpiod_put(data->reset_gpio);
|
||||
|
||||
if (test_and_clear_bit(BTUSB_RESET, &data->flags))
|
||||
usb_autopm_put_interface_no_suspend(data->intf);
|
||||
|
||||
if (intf == data->intf) {
|
||||
if (data->isoc)
|
||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||
|
|
@ -4565,11 +4635,26 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
|
||||
BT_DBG("intf %p", intf);
|
||||
|
||||
/* Don't auto-suspend if there are connections or discovery in
|
||||
* progress; external suspend calls shall never fail.
|
||||
/*
|
||||
* It is reported that remote wakeup events could sometimes cause some
|
||||
* adapters completely unresponsive. Resetting the xHCI root hub doesn't
|
||||
* help at all, and recovering from such a state needs a power cycle.
|
||||
* Since disabling remote wakeup simply causes the USB core to gate
|
||||
* runtime autosuspend as well due to needs_remote_wakeup == 1, let's do
|
||||
* this ourselves to make our life easier. The interface can be safely
|
||||
* autosuspended as long as remote wakeup is disabled, i.e., after
|
||||
* closing the HCI device.
|
||||
*
|
||||
* Don't auto-suspend if there are connections or discovery in progress.
|
||||
*
|
||||
* External suspend calls shall never fail. Specifically, a device with
|
||||
* broken remote wakeup may still take the advantage of remote wakeup in
|
||||
* order to wake up the system from sleep if userspace has enabled it as
|
||||
* a wakeup source.
|
||||
*/
|
||||
if (PMSG_IS_AUTO(message) &&
|
||||
(hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
|
||||
((test_bit(BTUSB_WAKEUP_BROKEN, &data->flags) && data->intf->needs_remote_wakeup) ||
|
||||
hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
|
||||
return -EBUSY;
|
||||
|
||||
if (data->suspend_count++)
|
||||
|
|
|
|||
|
|
@ -251,13 +251,19 @@ static int __init dibs_init(void)
|
|||
|
||||
rc = class_register(&dibs_class);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto err;
|
||||
|
||||
rc = dibs_loopback_init();
|
||||
if (rc)
|
||||
pr_err("%s fails with %d\n", __func__, rc);
|
||||
goto err_unregister;
|
||||
|
||||
return rc;
|
||||
|
||||
err_unregister:
|
||||
class_unregister(&dibs_class);
|
||||
err:
|
||||
pr_err("%s fails with %d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit dibs_exit(void)
|
||||
|
|
|
|||
|
|
@ -678,9 +678,15 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
|
|||
if (arp->op_code == htons(ARPOP_REPLY)) {
|
||||
/* the arp must be sent on the selected rx channel */
|
||||
tx_slave = rlb_choose_channel(skb, bond, arp);
|
||||
if (tx_slave)
|
||||
if (tx_slave &&
|
||||
!ether_addr_equal_64bits(arp->mac_src,
|
||||
tx_slave->dev->dev_addr)) {
|
||||
if (unlikely(skb_cow_head(skb, 0)))
|
||||
return NULL;
|
||||
arp = (struct arp_pkt *)skb_network_header(skb);
|
||||
bond_hw_addr_copy(arp->mac_src, tx_slave->dev->dev_addr,
|
||||
tx_slave->dev->addr_len);
|
||||
}
|
||||
netdev_dbg(bond->dev, "(slave %s): Server sent ARP Reply packet\n",
|
||||
tx_slave ? tx_slave->dev->name : "NULL");
|
||||
} else if (arp->op_code == htons(ARPOP_REQUEST)) {
|
||||
|
|
@ -1340,7 +1346,6 @@ static netdev_tx_t bond_do_alb_xmit(struct sk_buff *skb, struct bonding *bond,
|
|||
struct slave *tx_slave)
|
||||
{
|
||||
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
|
||||
struct ethhdr *eth_data = eth_hdr(skb);
|
||||
|
||||
if (!tx_slave) {
|
||||
/* unbalanced or unassigned, send through primary */
|
||||
|
|
@ -1351,7 +1356,9 @@ static netdev_tx_t bond_do_alb_xmit(struct sk_buff *skb, struct bonding *bond,
|
|||
|
||||
if (tx_slave && bond_slave_can_tx(tx_slave)) {
|
||||
if (tx_slave != rcu_access_pointer(bond->curr_active_slave)) {
|
||||
ether_addr_copy(eth_data->h_source,
|
||||
if (unlikely(skb_cow_head(skb, 0)))
|
||||
return bond_tx_drop(bond->dev, skb);
|
||||
ether_addr_copy(skb_eth_hdr(skb)->h_source,
|
||||
tx_slave->dev->dev_addr);
|
||||
}
|
||||
|
||||
|
|
@ -1375,8 +1382,7 @@ struct slave *bond_xmit_tlb_slave_get(struct bonding *bond,
|
|||
struct ethhdr *eth_data;
|
||||
u32 hash_index;
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
eth_data = eth_hdr(skb);
|
||||
eth_data = skb_eth_hdr(skb);
|
||||
|
||||
/* Do not TX balance any multicast or broadcast */
|
||||
if (!is_multicast_ether_addr(eth_data->h_dest)) {
|
||||
|
|
@ -1428,8 +1434,7 @@ struct slave *bond_xmit_alb_slave_get(struct bonding *bond,
|
|||
u32 hash_index = 0;
|
||||
int hash_size = 0;
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
eth_data = eth_hdr(skb);
|
||||
eth_data = skb_eth_hdr(skb);
|
||||
|
||||
switch (ntohs(skb->protocol)) {
|
||||
case ETH_P_IP: {
|
||||
|
|
|
|||
|
|
@ -1088,6 +1088,8 @@ static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv,
|
|||
unsigned int index = 1, rules_cnt = 0;
|
||||
|
||||
for_each_set_bit_from(index, priv->cfp.unique, priv->num_cfp_rules) {
|
||||
if (rules_cnt == nfc->rule_cnt)
|
||||
return -EMSGSIZE;
|
||||
rule_locs[rules_cnt] = index;
|
||||
rules_cnt++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
#define GSWIP_MDIO_PHY_FDUP_DIS 0x0600
|
||||
#define GSWIP_MDIO_PHY_FCONTX_MASK 0x0180
|
||||
#define GSWIP_MDIO_PHY_FCONTX_AUTO 0x0000
|
||||
#define GSWIP_MDIO_PHY_FCONTX_EN 0x0100
|
||||
#define GSWIP_MDIO_PHY_FCONTX_EN 0x0080
|
||||
#define GSWIP_MDIO_PHY_FCONTX_DIS 0x0180
|
||||
#define GSWIP_MDIO_PHY_FCONRX_MASK 0x0060
|
||||
#define GSWIP_MDIO_PHY_FCONRX_AUTO 0x0000
|
||||
|
|
|
|||
|
|
@ -3172,23 +3172,31 @@ static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
|
|||
|
||||
config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
|
||||
|
||||
priv->info->mac_port_get_caps(ds, port, config);
|
||||
|
||||
/* The EN7528 GPHYs report EEE capability, but negotiating EEE with
|
||||
* common link partners (e.g. Realtek GbE NICs) results in an unstable
|
||||
* link with dropped frames. Leave the LPI capabilities empty so that
|
||||
* phylink disables EEE on these PHYs and refuses to enable it from
|
||||
* userspace.
|
||||
*/
|
||||
if (priv->id != ID_EN7528) {
|
||||
if (priv->id != ID_EN7528 &&
|
||||
config->mac_capabilities & (MAC_100FD | MAC_1000FD)) {
|
||||
u32 eeecr = mt7530_read(priv, MT753X_PMEEECR_P(port));
|
||||
|
||||
config->lpi_capabilities = MAC_100FD | MAC_1000FD | MAC_2500FD;
|
||||
/* LPI above 1 Gbps is not supported */
|
||||
config->lpi_capabilities = config->mac_capabilities &
|
||||
(MAC_100FD | MAC_1000FD);
|
||||
phy_interface_copy(config->lpi_interfaces,
|
||||
config->supported_interfaces);
|
||||
__clear_bit(PHY_INTERFACE_MODE_2500BASEX,
|
||||
config->lpi_interfaces);
|
||||
|
||||
/* tx_lpi_timer should be in microseconds. The time units for
|
||||
* LPI threshold are unspecified.
|
||||
*/
|
||||
config->lpi_timer_default = FIELD_GET(LPI_THRESH_MASK, eeecr);
|
||||
}
|
||||
|
||||
priv->info->mac_port_get_caps(ds, port, config);
|
||||
}
|
||||
|
||||
static int mt753x_pcs_validate(struct phylink_pcs *pcs,
|
||||
|
|
|
|||
|
|
@ -2438,6 +2438,7 @@ static int mv88e6xxx_get_rxnfc(struct dsa_switch *ds, int port,
|
|||
struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct mv88e6xxx_policy *policy;
|
||||
u32 cnt = 0;
|
||||
int err;
|
||||
int id;
|
||||
|
||||
|
|
@ -2463,11 +2464,18 @@ static int mv88e6xxx_get_rxnfc(struct dsa_switch *ds, int port,
|
|||
break;
|
||||
case ETHTOOL_GRXCLSRLALL:
|
||||
rxnfc->data = 0;
|
||||
rxnfc->rule_cnt = 0;
|
||||
idr_for_each_entry(&chip->policies, policy, id)
|
||||
if (policy->port == port)
|
||||
rule_locs[rxnfc->rule_cnt++] = id;
|
||||
err = 0;
|
||||
idr_for_each_entry(&chip->policies, policy, id) {
|
||||
if (policy->port != port)
|
||||
continue;
|
||||
if (cnt == rxnfc->rule_cnt) {
|
||||
err = -EMSGSIZE;
|
||||
break;
|
||||
}
|
||||
rule_locs[cnt++] = id;
|
||||
}
|
||||
if (!err)
|
||||
rxnfc->rule_cnt = cnt;
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
|
|
|
|||
|
|
@ -1067,6 +1067,7 @@ static int emac_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
out_release_sram:
|
||||
of_node_put(db->phy_node);
|
||||
sunxi_sram_release(&pdev->dev);
|
||||
out_clk_disable_unprepare:
|
||||
clk_disable_unprepare(db->clk);
|
||||
|
|
@ -1094,6 +1095,7 @@ static void emac_remove(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
unregister_netdev(ndev);
|
||||
of_node_put(db->phy_node);
|
||||
sunxi_sram_release(&pdev->dev);
|
||||
clk_disable_unprepare(db->clk);
|
||||
irq_dispose_mapping(ndev->irq);
|
||||
|
|
|
|||
|
|
@ -171,8 +171,10 @@ pdsc_legacy_firmware_update(struct pdsc *pdsc,
|
|||
|
||||
dev_info(pdsc->dev, "Installing firmware\n");
|
||||
|
||||
if (!pdsc->cmd_regs)
|
||||
if (!pdsc->cmd_regs) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "BARs not mapped");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
dl = priv_to_devlink(pdsc);
|
||||
devlink_flash_update_status_notify(dl, "Preparing to flash",
|
||||
|
|
@ -198,6 +200,12 @@ pdsc_legacy_firmware_update(struct pdsc *pdsc,
|
|||
|
||||
copy_sz = min_t(unsigned int, buf_sz, fw->size - offset);
|
||||
mutex_lock(&pdsc->devcmd_lock);
|
||||
if (!pdsc->cmd_regs) {
|
||||
mutex_unlock(&pdsc->devcmd_lock);
|
||||
err = -ENXIO;
|
||||
NL_SET_ERR_MSG_MOD(extack, "Device reset during flash");
|
||||
goto err_out;
|
||||
}
|
||||
memcpy_toio(&pdsc->cmd_regs->data, fw->data + offset, copy_sz);
|
||||
err = pdsc_devcmd_fw_download_locked(pdsc, data_addr,
|
||||
offset, copy_sz);
|
||||
|
|
|
|||
|
|
@ -513,8 +513,12 @@ static void pdsc_reset_prepare(struct pci_dev *pdev)
|
|||
pdsc_auxbus_dev_del(pdsc, pdsc, &pdsc->padev);
|
||||
}
|
||||
|
||||
pdsc_unmap_bars(pdsc);
|
||||
pci_release_regions(pdev);
|
||||
if (!pdev->is_virtfn) {
|
||||
mutex_lock(&pdsc->devcmd_lock);
|
||||
pdsc_unmap_bars(pdsc);
|
||||
mutex_unlock(&pdsc->devcmd_lock);
|
||||
pci_release_regions(pdev);
|
||||
}
|
||||
if (pci_is_enabled(pdev))
|
||||
pci_disable_device(pdev);
|
||||
pdsc_deferred_dma_free(pdsc);
|
||||
|
|
@ -543,7 +547,9 @@ static void pdsc_reset_done(struct pci_dev *pdev)
|
|||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&pdsc->devcmd_lock);
|
||||
err = pdsc_map_bars(pdsc);
|
||||
mutex_unlock(&pdsc->devcmd_lock);
|
||||
if (err)
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,8 +148,9 @@ static int tx_spb_ring_full(struct bcmasp_intf *intf, int cnt)
|
|||
int next_index, i;
|
||||
|
||||
/* Check if we have enough room for cnt descriptors */
|
||||
next_index = intf->tx_spb_index;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
next_index = incr_ring(intf->tx_spb_index, DESC_RING_COUNT);
|
||||
next_index = incr_ring(next_index, DESC_RING_COUNT);
|
||||
if (next_index == intf->tx_spb_clean_index)
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -301,6 +302,7 @@ static netdev_tx_t bcmasp_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
txcb->bytes_sent = total_bytes;
|
||||
dma_unmap_addr_set(txcb, dma_addr, mapping);
|
||||
dma_unmap_len_set(txcb, dma_len, size);
|
||||
txcb->last = false;
|
||||
if (!i) {
|
||||
desc->flags |= DESC_SOF;
|
||||
if (csum_hw)
|
||||
|
|
|
|||
|
|
@ -462,6 +462,16 @@ u16 bnxt_xmit_get_cfa_action(struct sk_buff *skb)
|
|||
static void bnxt_txr_db_kick(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
u16 prod)
|
||||
{
|
||||
/* If the most recent BD has its completion suppressed, unset the bit
|
||||
* so that a completion is generated, otherwise nothing is left to
|
||||
* clean the ring and wake the queue.
|
||||
*/
|
||||
if (txr->kick_txbd0) {
|
||||
txr->kick_txbd0->tx_bd_len_flags_type &=
|
||||
cpu_to_le32(~TX_BD_FLAGS_NO_CMPL);
|
||||
txr->kick_txbd0 = NULL;
|
||||
}
|
||||
|
||||
/* Sync BD data before updating doorbell */
|
||||
wmb();
|
||||
bnxt_db_write(bp, &txr->tx_db, prod);
|
||||
|
|
@ -485,7 +495,6 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
struct bnxt_sw_tx_bd *tx_buf;
|
||||
__le32 lflags = 0;
|
||||
skb_frag_t *frag;
|
||||
netdev_tx_t ret;
|
||||
|
||||
i = skb_get_queue_mapping(skb);
|
||||
if (unlikely(i >= bp->tx_nr_rings)) {
|
||||
|
|
@ -509,11 +518,22 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
if (skb_is_gso(skb) &&
|
||||
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) &&
|
||||
!(bp->flags & BNXT_FLAG_UDP_GSO_CAP)) {
|
||||
ret = bnxt_sw_udp_gso_xmit(bp, txr, txq, skb);
|
||||
if (txr->kick_pending)
|
||||
int rc = bnxt_sw_udp_gso_xmit(bp, txr, txq, skb);
|
||||
|
||||
/* if SW USO queued a packet, the doorbell will be written
|
||||
* below and there is no reason to track the last BD with
|
||||
* suppressed completions
|
||||
*/
|
||||
if (rc > 0)
|
||||
txr->kick_txbd0 = NULL;
|
||||
|
||||
/* if a packet was queued by SW USO or a doorbell was pending
|
||||
* from a previous xmit that was deferred, write the doorbell.
|
||||
*/
|
||||
if (rc > 0 || txr->kick_pending)
|
||||
bnxt_txr_db_kick(bp, txr, txr->tx_prod);
|
||||
|
||||
return ret;
|
||||
return rc < 0 ? NETDEV_TX_BUSY : NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
free_size = bnxt_tx_avail(bp, txr);
|
||||
|
|
@ -751,23 +771,23 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
prod = NEXT_TX(prod);
|
||||
WRITE_ONCE(txr->tx_prod, prod);
|
||||
|
||||
txr->kick_txbd0 = NULL;
|
||||
if (!netdev_xmit_more() || netif_xmit_stopped(txq)) {
|
||||
bnxt_txr_db_kick(bp, txr, prod);
|
||||
} else {
|
||||
if (free_size >= bp->tx_wake_thresh)
|
||||
if (free_size >= bp->tx_wake_thresh) {
|
||||
txbd0->tx_bd_len_flags_type |=
|
||||
cpu_to_le32(TX_BD_FLAGS_NO_CMPL);
|
||||
txr->kick_txbd0 = txbd0;
|
||||
}
|
||||
txr->kick_pending = 1;
|
||||
}
|
||||
|
||||
tx_done:
|
||||
|
||||
if (unlikely(bnxt_tx_avail(bp, txr) <= MAX_SKB_FRAGS + 1)) {
|
||||
if (netdev_xmit_more() && !tx_buf->is_push) {
|
||||
txbd0->tx_bd_len_flags_type &=
|
||||
cpu_to_le32(~TX_BD_FLAGS_NO_CMPL);
|
||||
if (txr->kick_pending)
|
||||
bnxt_txr_db_kick(bp, txr, prod);
|
||||
}
|
||||
|
||||
netif_txq_try_stop(txq, bnxt_tx_avail(bp, txr),
|
||||
bp->tx_wake_thresh);
|
||||
|
|
@ -1514,14 +1534,16 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u16 bnxt_alloc_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id)
|
||||
static u16 bnxt_alloc_agg_idx(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
|
||||
u16 agg_id)
|
||||
{
|
||||
struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map;
|
||||
u16 idx = agg_id & MAX_TPA_P5_MASK;
|
||||
u16 idx = agg_id & (bp->max_tpa_roundup_size - 1);
|
||||
|
||||
if (test_bit(idx, map->agg_idx_bmap)) {
|
||||
idx = find_first_zero_bit(map->agg_idx_bmap, MAX_TPA_P5);
|
||||
if (idx >= MAX_TPA_P5)
|
||||
idx = find_first_zero_bit(map->agg_idx_bmap,
|
||||
bp->max_tpa_roundup_size);
|
||||
if (idx >= bp->max_tpa_roundup_size)
|
||||
return INVALID_HW_RING_ID;
|
||||
}
|
||||
__set_bit(idx, map->agg_idx_bmap);
|
||||
|
|
@ -1586,7 +1608,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
|
|||
|
||||
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
|
||||
agg_id = TPA_START_AGG_ID_P5(tpa_start);
|
||||
agg_id = bnxt_alloc_agg_idx(rxr, agg_id);
|
||||
agg_id = bnxt_alloc_agg_idx(bp, rxr, agg_id);
|
||||
if (unlikely(agg_id == INVALID_HW_RING_ID)) {
|
||||
netdev_warn(bp->dev, "Unable to allocate agg ID for ring %d, agg 0x%x\n",
|
||||
rxr->bnapi->index,
|
||||
|
|
@ -3584,7 +3606,7 @@ static void bnxt_free_one_tpa_info_data(struct bnxt *bp,
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bp->max_tpa; i++) {
|
||||
for (i = 0; i < bp->max_tpa_roundup_size; i++) {
|
||||
struct bnxt_tpa_info *tpa_info = &rxr->rx_tpa[i];
|
||||
u8 *data = tpa_info->data;
|
||||
|
||||
|
|
@ -3781,7 +3803,7 @@ static void bnxt_free_one_tpa_info(struct bnxt *bp,
|
|||
kfree(rxr->rx_tpa_idx_map);
|
||||
rxr->rx_tpa_idx_map = NULL;
|
||||
if (rxr->rx_tpa) {
|
||||
for (i = 0; i < bp->max_tpa; i++) {
|
||||
for (i = 0; i < bp->max_tpa_roundup_size; i++) {
|
||||
kfree(rxr->rx_tpa[i].agg_arr);
|
||||
rxr->rx_tpa[i].agg_arr = NULL;
|
||||
}
|
||||
|
|
@ -3807,13 +3829,14 @@ static int bnxt_alloc_one_tpa_info(struct bnxt *bp,
|
|||
struct rx_agg_cmp *agg;
|
||||
int i;
|
||||
|
||||
rxr->rx_tpa = kzalloc_objs(struct bnxt_tpa_info, bp->max_tpa);
|
||||
rxr->rx_tpa = kzalloc_objs(struct bnxt_tpa_info,
|
||||
bp->max_tpa_roundup_size);
|
||||
if (!rxr->rx_tpa)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS))
|
||||
return 0;
|
||||
for (i = 0; i < bp->max_tpa; i++) {
|
||||
for (i = 0; i < bp->max_tpa_roundup_size; i++) {
|
||||
agg = kzalloc_objs(*agg, MAX_SKB_FRAGS);
|
||||
if (!agg)
|
||||
return -ENOMEM;
|
||||
|
|
@ -3832,6 +3855,9 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)
|
|||
|
||||
bp->max_tpa = MAX_TPA;
|
||||
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
|
||||
/* TPA is not supported at all, so there is nothing to
|
||||
* allocate.
|
||||
*/
|
||||
if (!bp->max_tpa_v2)
|
||||
return 0;
|
||||
bp->max_tpa = min_t(u16, bp->max_tpa_v2, MAX_TPA_P5);
|
||||
|
|
@ -3839,6 +3865,7 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)
|
|||
if (bp->max_tpa <= 32 && BNXT_CHIP_P5(bp) && !BNXT_NPAR(bp))
|
||||
bp->max_tpa = MAX_TPA_P5;
|
||||
}
|
||||
bp->max_tpa_roundup_size = roundup_pow_of_two(bp->max_tpa);
|
||||
|
||||
for (i = 0; i < bp->rx_nr_rings; i++) {
|
||||
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
|
||||
|
|
@ -4551,7 +4578,7 @@ static int bnxt_alloc_one_tpa_info_data(struct bnxt *bp,
|
|||
u8 *data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bp->max_tpa; i++) {
|
||||
for (i = 0; i < bp->max_tpa_roundup_size; i++) {
|
||||
data = __bnxt_alloc_rx_frag(bp, &mapping, rxr,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
|
|
@ -5006,7 +5033,8 @@ void bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
|
|||
bnxt_get_max_rings(bp, &rx, &tx, true);
|
||||
if (rx > 1) {
|
||||
bp->flags &= ~BNXT_FLAG_NO_AGG_RINGS;
|
||||
bp->dev->hw_features |= NETIF_F_LRO;
|
||||
if (BNXT_SUPPORTS_TPA(bp))
|
||||
bp->dev->hw_features |= NETIF_F_LRO;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5427,6 +5455,8 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
|
|||
txr->tx_prod = 0;
|
||||
txr->tx_cons = 0;
|
||||
txr->tx_hw_cons = 0;
|
||||
txr->kick_pending = 0;
|
||||
txr->kick_txbd0 = NULL;
|
||||
}
|
||||
|
||||
rxr = bnapi->rx_ring;
|
||||
|
|
@ -11340,8 +11370,13 @@ static int bnxt_shutdown_nic(struct bnxt *bp, bool irq_re_init)
|
|||
|
||||
static int bnxt_init_nic(struct bnxt *bp, bool irq_re_init)
|
||||
{
|
||||
int rc;
|
||||
|
||||
bnxt_init_cp_rings(bp);
|
||||
bnxt_init_rx_rings(bp);
|
||||
rc = bnxt_init_rx_rings(bp);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
bnxt_init_tx_rings(bp);
|
||||
bnxt_init_ring_grps(bp, irq_re_init);
|
||||
bnxt_init_vnics(bp);
|
||||
|
|
@ -11772,6 +11807,8 @@ static int bnxt_tx_queue_start(struct bnxt *bp, int idx)
|
|||
txr->tx_prod = 0;
|
||||
txr->tx_cons = 0;
|
||||
txr->tx_hw_cons = 0;
|
||||
txr->kick_pending = 0;
|
||||
txr->kick_txbd0 = NULL;
|
||||
start_tx:
|
||||
WRITE_ONCE(txr->dev_state, 0);
|
||||
synchronize_net();
|
||||
|
|
@ -14603,7 +14640,14 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
|
|||
rxr->rx_sw_agg_prod = 0;
|
||||
rxr->rx_next_cons = 0;
|
||||
rxr->bnapi->in_reset = false;
|
||||
bnxt_alloc_one_rx_ring(bp, i);
|
||||
rc = bnxt_alloc_one_rx_ring(bp, i);
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev, "RX ring reset failed to allocate buffers, rc = %d, falling back to global reset\n",
|
||||
rc);
|
||||
bnxt_reset_task(bp, true);
|
||||
bnxt_rtnl_unlock_sp(bp);
|
||||
return;
|
||||
}
|
||||
cpr = &rxr->bnapi->cp_ring;
|
||||
cpr->sw_stats->rx.rx_resets++;
|
||||
if (bp->flags & BNXT_FLAG_AGG_RINGS)
|
||||
|
|
@ -16332,6 +16376,8 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
|
|||
clone->need_head_pool = false;
|
||||
clone->rx_page_size = qcfg->rx_page_size;
|
||||
clone->rx_agg_bmap = NULL;
|
||||
clone->rx_tpa = NULL;
|
||||
clone->rx_tpa_idx_map = NULL;
|
||||
|
||||
rc = bnxt_alloc_rx_page_pool(bp, clone, rxr->page_pool->p.nid);
|
||||
if (rc)
|
||||
|
|
@ -16375,11 +16421,16 @@ static int bnxt_queue_mem_alloc(struct net_device *dev,
|
|||
bnxt_alloc_one_rx_ring_skb(bp, clone, idx);
|
||||
if (bp->flags & BNXT_FLAG_AGG_RINGS)
|
||||
bnxt_alloc_one_rx_ring_netmem(bp, clone, idx);
|
||||
if (bp->flags & BNXT_FLAG_TPA)
|
||||
bnxt_alloc_one_tpa_info_data(bp, clone);
|
||||
if (bp->flags & BNXT_FLAG_TPA) {
|
||||
rc = bnxt_alloc_one_tpa_info_data(bp, clone);
|
||||
if (rc)
|
||||
goto err_free_rx_ring_skbs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_rx_ring_skbs:
|
||||
bnxt_free_one_rx_ring_skbs(bp, clone);
|
||||
err_free_tpa_info:
|
||||
bnxt_free_one_tpa_info(bp, clone);
|
||||
err_free_rx_agg_ring:
|
||||
|
|
|
|||
|
|
@ -789,7 +789,6 @@ struct nqe_cn {
|
|||
|
||||
#define MAX_TPA 64
|
||||
#define MAX_TPA_P5 256
|
||||
#define MAX_TPA_P5_MASK (MAX_TPA_P5 - 1)
|
||||
#define MAX_TPA_SEGS_P5 0x3f
|
||||
|
||||
#if (BNXT_PAGE_SHIFT == 16)
|
||||
|
|
@ -993,6 +992,7 @@ struct bnxt_tx_ring_info {
|
|||
u16 txq_index;
|
||||
u8 tx_napi_idx;
|
||||
u8 kick_pending;
|
||||
struct tx_bd *kick_txbd0;
|
||||
struct bnxt_db_info tx_db;
|
||||
|
||||
struct tx_bd *tx_desc_ring[MAX_TX_PAGES];
|
||||
|
|
@ -2380,6 +2380,7 @@ struct bnxt {
|
|||
|
||||
u16 max_tpa_v2;
|
||||
u16 max_tpa;
|
||||
u16 max_tpa_roundup_size;
|
||||
u32 rx_buf_size;
|
||||
u32 rx_buf_use_size; /* useable size */
|
||||
u16 rx_offset;
|
||||
|
|
|
|||
|
|
@ -31,10 +31,14 @@ static u32 bnxt_sw_gso_lhint(unsigned int len)
|
|||
return TX_BD_FLAGS_LHINT_2048_AND_LARGER;
|
||||
}
|
||||
|
||||
netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
|
||||
struct bnxt_tx_ring_info *txr,
|
||||
struct netdev_queue *txq,
|
||||
struct sk_buff *skb)
|
||||
/* Transmit an skb requiring software UDP segmentation.
|
||||
*
|
||||
* Returns 1 if the skb was queued and new BDs were produced, 0 if the skb
|
||||
* was dropped, or -1 if the ring is full and the skb should be retried.
|
||||
* The caller owns the doorbell for all three cases.
|
||||
*/
|
||||
int bnxt_sw_udp_gso_xmit(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
struct netdev_queue *txq, struct sk_buff *skb)
|
||||
{
|
||||
unsigned int last_unmap_len __maybe_unused = 0;
|
||||
dma_addr_t last_unmap_addr __maybe_unused = 0;
|
||||
|
|
@ -69,7 +73,7 @@ netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
|
|||
if (unlikely(bnxt_tx_avail(bp, txr) < bds_needed)) {
|
||||
netif_txq_try_stop(txq, bnxt_tx_avail(bp, txr),
|
||||
bp->tx_wake_thresh);
|
||||
return NETDEV_TX_BUSY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* BD backpressure alone cannot prevent overwriting in-flight
|
||||
|
|
@ -77,7 +81,7 @@ netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
|
|||
*/
|
||||
if (!netif_txq_maybe_stop(txq, bnxt_inline_avail(txr),
|
||||
num_segs, num_segs))
|
||||
return NETDEV_TX_BUSY;
|
||||
return -1;
|
||||
|
||||
if (unlikely(tso_dma_map_init(&map, &pdev->dev, skb, hdr_len)))
|
||||
goto drop;
|
||||
|
|
@ -223,16 +227,15 @@ netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
|
|||
netdev_tx_sent_queue(txq, skb->len);
|
||||
|
||||
WRITE_ONCE(txr->tx_prod, prod);
|
||||
txr->kick_pending = 1;
|
||||
|
||||
if (unlikely(bnxt_tx_avail(bp, txr) <= bp->tx_wake_thresh))
|
||||
netif_txq_try_stop(txq, bnxt_tx_avail(bp, txr),
|
||||
bp->tx_wake_thresh);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
return 1;
|
||||
|
||||
drop:
|
||||
dev_kfree_skb_any(skb);
|
||||
dev_core_stats_tx_dropped_inc(bp->dev);
|
||||
return NETDEV_TX_OK;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@ static inline int bnxt_min_tx_desc_cnt(struct bnxt *bp,
|
|||
return BNXT_MIN_TX_DESC_CNT;
|
||||
}
|
||||
|
||||
netdev_tx_t bnxt_sw_udp_gso_xmit(struct bnxt *bp,
|
||||
struct bnxt_tx_ring_info *txr,
|
||||
struct netdev_queue *txq,
|
||||
struct sk_buff *skb);
|
||||
int bnxt_sw_udp_gso_xmit(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
|
||||
struct netdev_queue *txq, struct sk_buff *skb);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1164,6 +1164,8 @@ static int macb_mii_init(struct macb *bp)
|
|||
if (err)
|
||||
goto err_out_unregister_bus;
|
||||
|
||||
of_node_put(mdio_np);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_unregister_bus:
|
||||
|
|
@ -4300,9 +4302,9 @@ static int macb_taprio_setup_replace(struct net_device *netdev,
|
|||
u64 total_on_time = 0, start_time_sec = 0, start_time = conf->base_time;
|
||||
u32 configured_queues = 0, speed = 0, start_time_nsec;
|
||||
struct macb_queue_enst_config *enst_queue;
|
||||
struct tc_taprio_sched_entry *entry;
|
||||
struct ethtool_link_ksettings kset = {};
|
||||
struct macb *bp = netdev_priv(netdev);
|
||||
struct ethtool_link_ksettings kset;
|
||||
struct tc_taprio_sched_entry *entry;
|
||||
struct macb_queue *queue;
|
||||
u32 queue_mask;
|
||||
u8 queue_id;
|
||||
|
|
@ -4329,8 +4331,8 @@ static int macb_taprio_setup_replace(struct net_device *netdev,
|
|||
}
|
||||
|
||||
speed = kset.base.speed;
|
||||
if (unlikely(speed <= 0)) {
|
||||
netdev_err(netdev, "Invalid speed: %d\n", speed);
|
||||
if (unlikely(speed == SPEED_UNKNOWN || !speed)) {
|
||||
netdev_err(netdev, "Invalid speed %d, link-down?\n", speed);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -5881,6 +5883,7 @@ static int macb_probe(struct platform_device *pdev)
|
|||
}
|
||||
spin_lock_init(&bp->lock);
|
||||
spin_lock_init(&bp->stats_lock);
|
||||
spin_lock_init(&bp->tsu_clk_lock);
|
||||
|
||||
/* setup capabilities */
|
||||
macb_configure_caps(bp, macb_config);
|
||||
|
|
@ -5976,8 +5979,11 @@ static int macb_probe(struct platform_device *pdev)
|
|||
macb_free_tieoff(bp);
|
||||
|
||||
err_out_unregister_mdio:
|
||||
mdiobus_unregister(bp->mii_bus);
|
||||
mdiobus_free(bp->mii_bus);
|
||||
if (bp->mii_bus) {
|
||||
mdiobus_unregister(bp->mii_bus);
|
||||
mdiobus_free(bp->mii_bus);
|
||||
}
|
||||
phylink_destroy(bp->phylink);
|
||||
|
||||
err_out_phy_exit:
|
||||
phy_exit(bp->phy);
|
||||
|
|
@ -6006,8 +6012,10 @@ static void macb_remove(struct platform_device *pdev)
|
|||
unregister_netdev(netdev);
|
||||
macb_free_tieoff(bp);
|
||||
phy_exit(bp->phy);
|
||||
mdiobus_unregister(bp->mii_bus);
|
||||
mdiobus_free(bp->mii_bus);
|
||||
if (bp->mii_bus) {
|
||||
mdiobus_unregister(bp->mii_bus);
|
||||
mdiobus_free(bp->mii_bus);
|
||||
}
|
||||
|
||||
device_set_wakeup_enable(&bp->pdev->dev, 0);
|
||||
cancel_delayed_work_sync(&bp->tx_lpi_work);
|
||||
|
|
|
|||
|
|
@ -334,6 +334,7 @@ void gem_ptp_init(struct net_device *netdev)
|
|||
bp->tsu_rate = bp->ptp_info->get_tsu_rate(bp);
|
||||
bp->ptp_clock_info.max_adj = bp->ptp_info->get_ptp_max_adj();
|
||||
gem_ptp_init_timer(bp);
|
||||
gem_ptp_init_tsu(bp);
|
||||
bp->ptp_clock = ptp_clock_register(&bp->ptp_clock_info, &netdev->dev);
|
||||
if (IS_ERR(bp->ptp_clock)) {
|
||||
pr_err("ptp clock register failed: %ld\n",
|
||||
|
|
@ -345,10 +346,6 @@ void gem_ptp_init(struct net_device *netdev)
|
|||
return;
|
||||
}
|
||||
|
||||
spin_lock_init(&bp->tsu_clk_lock);
|
||||
|
||||
gem_ptp_init_tsu(bp);
|
||||
|
||||
dev_info(&bp->pdev->dev, "%s ptp clock registered.\n",
|
||||
GEM_PTP_TIMER_NAME);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,6 +137,12 @@ struct enic_port_profile {
|
|||
u8 mac_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
enum enic_vf_link_state {
|
||||
ENIC_VF_LINK_STATE_UNKNOWN,
|
||||
ENIC_VF_LINK_STATE_DOWN,
|
||||
ENIC_VF_LINK_STATE_UP,
|
||||
};
|
||||
|
||||
/* enic_rfs_fltr_node - rfs filter node in hash table
|
||||
* @@keys: IPv4 5 tuple
|
||||
* @flow_id: flow_id of clsf filter provided by kernel
|
||||
|
|
@ -312,19 +318,25 @@ struct enic {
|
|||
unsigned int admin_msg_count; /* current depth of admin_msg_list */
|
||||
void (*admin_rq_handler)(struct enic *enic, void *buf,
|
||||
unsigned int len);
|
||||
/* The PF is authoritative for a V2 VF's carrier. Keep the last
|
||||
* notification across an ordinary netdev close/open and serialize it
|
||||
* against the open/stop carrier transition.
|
||||
*/
|
||||
spinlock_t vf_link_state_lock;
|
||||
enum enic_vf_link_state vf_link_state;
|
||||
bool vf_link_running;
|
||||
|
||||
/* MBOX protocol state — mbox_lock serializes admin WQ sends */
|
||||
struct mutex mbox_lock;
|
||||
u64 mbox_msg_num;
|
||||
/* MBOX request-reply state. mbox_expected_reply is written and
|
||||
* cleared by the process-context request helpers (capability/register/
|
||||
* unregister) and only read by the admin_msg_work receive handlers, so
|
||||
* it is annotated with READ_ONCE()/WRITE_ONCE() rather than locked:
|
||||
* only one request is in flight at a time (requesters run under RTNL or
|
||||
* single-threaded probe/remove), so each request is serialized and its
|
||||
* reply completes mbox_comp before the next request is issued.
|
||||
/* MBOX request-reply state. Existing request callers allow only one
|
||||
* request in flight. The state lock arbitrates reply acceptance against
|
||||
* timeout invalidation, while mbox_comp publishes the accepted result to
|
||||
* the requester.
|
||||
*/
|
||||
struct completion mbox_comp;
|
||||
spinlock_t mbox_state_lock; /* protects expected reply state */
|
||||
u64 mbox_expected_msg_num;
|
||||
u8 mbox_expected_reply;
|
||||
bool mbox_initialized;
|
||||
|
||||
|
|
|
|||
|
|
@ -1800,6 +1800,8 @@ static int enic_open(struct net_device *netdev)
|
|||
|
||||
enic_notify_timer_start(enic);
|
||||
enic_rfs_timer_start(enic);
|
||||
if (enic_is_sriov_vf_v2(enic))
|
||||
enic_mbox_vf_link_state_set_running(enic, true);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -1853,7 +1855,10 @@ static int enic_stop(struct net_device *netdev)
|
|||
for (i = 0; i < enic->rq_count; i++)
|
||||
napi_disable(&enic->napi[i]);
|
||||
|
||||
netif_carrier_off(netdev);
|
||||
if (enic_is_sriov_vf_v2(enic))
|
||||
enic_mbox_vf_link_state_set_running(enic, false);
|
||||
else
|
||||
netif_carrier_off(netdev);
|
||||
if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
|
||||
for (i = 0; i < enic->wq_count; i++)
|
||||
napi_disable(&enic->napi[enic_cq_wq(enic, i)]);
|
||||
|
|
@ -2201,9 +2206,10 @@ static void enic_admin_chan_reopen(struct enic *enic)
|
|||
{
|
||||
int err;
|
||||
|
||||
/* Install the MBOX receive handler and reset the sequence number
|
||||
* before opening the channel, so the handler is in place before the
|
||||
* admin interrupt is unmasked and no early completion is dropped.
|
||||
/* Install the MBOX receive handler and clear pending reply state before
|
||||
* opening the channel, so the handler is in place before the admin
|
||||
* interrupt is unmasked and no early completion is dropped. Keep the
|
||||
* sequence number monotonic across channel generations.
|
||||
*/
|
||||
enic_mbox_init(enic);
|
||||
|
||||
|
|
@ -2215,7 +2221,7 @@ static void enic_admin_chan_reopen(struct enic *enic)
|
|||
* registration over a dead channel.
|
||||
*/
|
||||
if (enic_is_sriov_vf_v2(enic))
|
||||
enic->vf_registered = false;
|
||||
WRITE_ONCE(enic->vf_registered, false);
|
||||
|
||||
err = enic_admin_channel_open(enic);
|
||||
if (err) {
|
||||
|
|
@ -2271,6 +2277,8 @@ static void enic_reset(struct work_struct *work)
|
|||
enic_admin_channel_close(enic);
|
||||
|
||||
enic_stop(enic->netdev);
|
||||
if (enic_is_sriov_vf_v2(enic))
|
||||
enic_mbox_vf_link_state_reset(enic);
|
||||
|
||||
enic_dev_soft_reset(enic);
|
||||
enic_reset_addr_lists(enic);
|
||||
|
|
@ -2315,6 +2323,8 @@ static void enic_tx_hang_reset(struct work_struct *work)
|
|||
|
||||
enic_dev_hang_notify(enic);
|
||||
enic_stop(enic->netdev);
|
||||
if (enic_is_sriov_vf_v2(enic))
|
||||
enic_mbox_vf_link_state_reset(enic);
|
||||
|
||||
enic_dev_hang_reset(enic);
|
||||
enic_reset_addr_lists(enic);
|
||||
|
|
@ -3015,6 +3025,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
enic = netdev_priv(netdev);
|
||||
enic->netdev = netdev;
|
||||
enic->pdev = pdev;
|
||||
spin_lock_init(&enic->vf_link_state_lock);
|
||||
|
||||
/* Setup PCI resources
|
||||
*/
|
||||
|
|
@ -3339,7 +3350,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
err_out_admin_close:
|
||||
if (enic_is_sriov_vf_v2(enic)) {
|
||||
if (enic->vf_registered) {
|
||||
if (READ_ONCE(enic->vf_registered)) {
|
||||
int unreg_err = enic_mbox_vf_unregister(enic);
|
||||
|
||||
if (unreg_err)
|
||||
|
|
@ -3392,7 +3403,7 @@ static void enic_remove(struct pci_dev *pdev)
|
|||
* touching a netdev that is being torn down.
|
||||
*/
|
||||
if (enic_is_sriov_vf_v2(enic)) {
|
||||
if (enic->vf_registered) {
|
||||
if (READ_ONCE(enic->vf_registered)) {
|
||||
int unreg_err = enic_mbox_vf_unregister(enic);
|
||||
|
||||
if (unreg_err)
|
||||
|
|
|
|||
|
|
@ -18,22 +18,25 @@
|
|||
#define ENIC_MBOX_POLL_TIMEOUT_US 5000000
|
||||
#define ENIC_MBOX_POLL_INTERVAL_US 100
|
||||
|
||||
static void enic_mbox_fill_hdr(struct enic *enic, struct enic_mbox_hdr *hdr,
|
||||
u8 msg_type, u16 dst_vnic_id, u16 msg_len)
|
||||
static void enic_mbox_fill_hdr(struct enic_mbox_hdr *hdr, u8 msg_type,
|
||||
u16 dst_vnic_id, u16 msg_len, u64 msg_num)
|
||||
{
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
hdr->dst_vnic_id = cpu_to_le16(dst_vnic_id);
|
||||
hdr->msg_type = msg_type;
|
||||
hdr->msg_len = cpu_to_le16(msg_len);
|
||||
hdr->msg_num = cpu_to_le64(++enic->mbox_msg_num);
|
||||
hdr->msg_num = cpu_to_le64(msg_num);
|
||||
}
|
||||
|
||||
int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
|
||||
void *payload, u16 payload_len)
|
||||
static int enic_mbox_send_msg_id(struct enic *enic, u8 msg_type,
|
||||
u16 dst_vnic_id, void *payload,
|
||||
u16 payload_len, u64 msg_num, bool reuse_msg_num,
|
||||
u8 expected_reply)
|
||||
{
|
||||
size_t total_len = sizeof(struct enic_mbox_hdr) + payload_len;
|
||||
struct vnic_wq *wq = &enic->admin_wq;
|
||||
struct wq_enet_desc *desc;
|
||||
bool reply_expected = false;
|
||||
unsigned long timeout;
|
||||
dma_addr_t dma_addr;
|
||||
u16 vlan_tag;
|
||||
|
|
@ -68,7 +71,21 @@ int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
enic_mbox_fill_hdr(enic, buf, msg_type, dst_vnic_id, total_len);
|
||||
/* Replies reuse the initiating message number. Requests and
|
||||
* notifications allocate a new one.
|
||||
*/
|
||||
if (!reuse_msg_num)
|
||||
msg_num = ++enic->mbox_msg_num;
|
||||
if (expected_reply) {
|
||||
reinit_completion(&enic->mbox_comp);
|
||||
spin_lock_bh(&enic->mbox_state_lock);
|
||||
enic->mbox_expected_reply = expected_reply;
|
||||
enic->mbox_expected_msg_num = msg_num;
|
||||
spin_unlock_bh(&enic->mbox_state_lock);
|
||||
reply_expected = true;
|
||||
}
|
||||
|
||||
enic_mbox_fill_hdr(buf, msg_type, dst_vnic_id, total_len, msg_num);
|
||||
if (payload_len) {
|
||||
void *dst = buf + sizeof(struct enic_mbox_hdr);
|
||||
|
||||
|
|
@ -139,18 +156,66 @@ int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
|
|||
"MBOX send msg_type %u dst %u vlan %u err %d\n",
|
||||
msg_type, dst_vnic_id, vlan_tag, err);
|
||||
unlock:
|
||||
if (err && reply_expected) {
|
||||
spin_lock_bh(&enic->mbox_state_lock);
|
||||
if (enic->mbox_expected_reply == expected_reply &&
|
||||
enic->mbox_expected_msg_num == msg_num) {
|
||||
enic->mbox_expected_reply = 0;
|
||||
enic->mbox_expected_msg_num = 0;
|
||||
}
|
||||
spin_unlock_bh(&enic->mbox_state_lock);
|
||||
}
|
||||
mutex_unlock(&enic->mbox_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
|
||||
void *payload, u16 payload_len)
|
||||
{
|
||||
return enic_mbox_send_msg_id(enic, msg_type, dst_vnic_id, payload,
|
||||
payload_len, 0, false, 0);
|
||||
}
|
||||
|
||||
static int enic_mbox_send_reply(struct enic *enic, u8 msg_type,
|
||||
u16 dst_vnic_id, void *payload, u16 payload_len,
|
||||
u64 msg_num)
|
||||
{
|
||||
return enic_mbox_send_msg_id(enic, msg_type, dst_vnic_id, payload,
|
||||
payload_len, msg_num, true, 0);
|
||||
}
|
||||
|
||||
static int enic_mbox_vf_send_request(struct enic *enic, u8 request_type,
|
||||
u8 expected_reply, void *payload,
|
||||
u16 payload_len)
|
||||
{
|
||||
return enic_mbox_send_msg_id(enic, request_type, ENIC_MBOX_DST_PF,
|
||||
payload, payload_len, 0, false,
|
||||
expected_reply);
|
||||
}
|
||||
|
||||
static int enic_mbox_wait_reply(struct enic *enic, unsigned long timeout_ms)
|
||||
{
|
||||
unsigned long left;
|
||||
int err = 0;
|
||||
|
||||
left = wait_for_completion_timeout(&enic->mbox_comp,
|
||||
msecs_to_jiffies(timeout_ms));
|
||||
if (left)
|
||||
return 0;
|
||||
|
||||
return left ? 0 : -ETIMEDOUT;
|
||||
/* Invalidate a request that the handler has not already accepted. A
|
||||
* delayed reply cannot match a later request because message numbers are
|
||||
* monotonic across channel reopen.
|
||||
*/
|
||||
spin_lock_bh(&enic->mbox_state_lock);
|
||||
if (enic->mbox_expected_reply) {
|
||||
enic->mbox_expected_reply = 0;
|
||||
enic->mbox_expected_msg_num = 0;
|
||||
err = -ETIMEDOUT;
|
||||
}
|
||||
spin_unlock_bh(&enic->mbox_state_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int enic_mbox_send_link_state(struct enic *enic, u16 vf_id, u32 link_state)
|
||||
|
|
@ -178,8 +243,8 @@ static int enic_mbox_pf_handle_capability(struct enic *enic, void *msg,
|
|||
reply.reply.ret_major = cpu_to_le16(0);
|
||||
reply.version = cpu_to_le32(ENIC_MBOX_CAP_VERSION_1);
|
||||
|
||||
return enic_mbox_send_msg(enic, ENIC_MBOX_VF_CAPABILITY_REPLY, vf_id,
|
||||
&reply, sizeof(reply));
|
||||
return enic_mbox_send_reply(enic, ENIC_MBOX_VF_CAPABILITY_REPLY, vf_id,
|
||||
&reply, sizeof(reply), msg_num);
|
||||
}
|
||||
|
||||
static int enic_mbox_pf_handle_register(struct enic *enic, void *msg,
|
||||
|
|
@ -208,8 +273,8 @@ static int enic_mbox_pf_handle_register(struct enic *enic, void *msg,
|
|||
}
|
||||
|
||||
reply.reply.ret_major = cpu_to_le16(0);
|
||||
err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_REGISTER_REPLY, vf_id,
|
||||
&reply, sizeof(reply));
|
||||
err = enic_mbox_send_reply(enic, ENIC_MBOX_VF_REGISTER_REPLY, vf_id,
|
||||
&reply, sizeof(reply), msg_num);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -253,8 +318,8 @@ static int enic_mbox_pf_handle_unregister(struct enic *enic, void *msg,
|
|||
enic->vf_state[vf_id].registered = false;
|
||||
|
||||
reply.reply.ret_major = cpu_to_le16(0);
|
||||
err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_UNREGISTER_REPLY, vf_id,
|
||||
&reply, sizeof(reply));
|
||||
err = enic_mbox_send_reply(enic, ENIC_MBOX_VF_UNREGISTER_REPLY, vf_id,
|
||||
&reply, sizeof(reply), msg_num);
|
||||
|
||||
if (net_ratelimit())
|
||||
netdev_info(enic->netdev,
|
||||
|
|
@ -324,105 +389,116 @@ static void enic_mbox_pf_process_msg(struct enic *enic,
|
|||
hdr->msg_type, vf_id, err);
|
||||
}
|
||||
|
||||
static void enic_mbox_vf_handle_capability_reply(struct enic *enic,
|
||||
void *payload)
|
||||
static void enic_mbox_vf_handle_reply(struct enic *enic, u8 reply_type,
|
||||
void *payload, u64 msg_num)
|
||||
{
|
||||
struct enic_mbox_vf_capability_reply_msg *reply = payload;
|
||||
struct enic_mbox_generic_reply *reply = payload;
|
||||
u16 ret_major = le16_to_cpu(reply->ret_major);
|
||||
u64 expected_msg_num;
|
||||
u8 expected_type;
|
||||
|
||||
if (READ_ONCE(enic->mbox_expected_reply) != ENIC_MBOX_VF_CAPABILITY_REPLY) {
|
||||
spin_lock_bh(&enic->mbox_state_lock);
|
||||
expected_type = enic->mbox_expected_reply;
|
||||
expected_msg_num = enic->mbox_expected_msg_num;
|
||||
if (expected_type != reply_type || expected_msg_num != msg_num) {
|
||||
spin_unlock_bh(&enic->mbox_state_lock);
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: stale capability reply (expected %u), drop\n",
|
||||
READ_ONCE(enic->mbox_expected_reply));
|
||||
"MBOX: stale reply %u/%llu (expected %u/%llu), drop\n",
|
||||
reply_type, (unsigned long long)msg_num,
|
||||
expected_type, (unsigned long long)expected_msg_num);
|
||||
return;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(reply->reply.ret_major) == 0)
|
||||
enic->pf_cap_version = le32_to_cpu(reply->version);
|
||||
else
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: PF rejected capability request: %u/%u\n",
|
||||
le16_to_cpu(reply->reply.ret_major),
|
||||
le16_to_cpu(reply->reply.ret_minor));
|
||||
if (!ret_major) {
|
||||
switch (reply_type) {
|
||||
case ENIC_MBOX_VF_CAPABILITY_REPLY: {
|
||||
struct enic_mbox_vf_capability_reply_msg *cap = payload;
|
||||
|
||||
WRITE_ONCE(enic->pf_cap_version,
|
||||
le32_to_cpu(cap->version));
|
||||
break;
|
||||
}
|
||||
case ENIC_MBOX_VF_REGISTER_REPLY:
|
||||
WRITE_ONCE(enic->vf_registered, true);
|
||||
break;
|
||||
case ENIC_MBOX_VF_UNREGISTER_REPLY:
|
||||
WRITE_ONCE(enic->vf_registered, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enic->mbox_expected_reply = 0;
|
||||
enic->mbox_expected_msg_num = 0;
|
||||
complete(&enic->mbox_comp);
|
||||
spin_unlock_bh(&enic->mbox_state_lock);
|
||||
|
||||
if (ret_major)
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: PF rejected reply type %u: %u/%u\n",
|
||||
reply_type, ret_major,
|
||||
le16_to_cpu(reply->ret_minor));
|
||||
}
|
||||
|
||||
static void enic_mbox_vf_handle_register_reply(struct enic *enic,
|
||||
void *payload)
|
||||
{
|
||||
struct enic_mbox_vf_register_reply_msg *reply = payload;
|
||||
|
||||
if (READ_ONCE(enic->mbox_expected_reply) != ENIC_MBOX_VF_REGISTER_REPLY) {
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: stale register reply (expected %u), drop\n",
|
||||
READ_ONCE(enic->mbox_expected_reply));
|
||||
return;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(reply->reply.ret_major)) {
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: VF register rejected by PF: %u/%u\n",
|
||||
le16_to_cpu(reply->reply.ret_major),
|
||||
le16_to_cpu(reply->reply.ret_minor));
|
||||
} else {
|
||||
enic->vf_registered = true;
|
||||
}
|
||||
complete(&enic->mbox_comp);
|
||||
}
|
||||
|
||||
static void enic_mbox_vf_handle_unregister_reply(struct enic *enic,
|
||||
void *payload)
|
||||
{
|
||||
struct enic_mbox_vf_register_reply_msg *reply = payload;
|
||||
|
||||
if (READ_ONCE(enic->mbox_expected_reply) != ENIC_MBOX_VF_UNREGISTER_REPLY) {
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: stale unregister reply (expected %u), drop\n",
|
||||
READ_ONCE(enic->mbox_expected_reply));
|
||||
return;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(reply->reply.ret_major)) {
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: VF unregister rejected by PF: %u/%u\n",
|
||||
le16_to_cpu(reply->reply.ret_major),
|
||||
le16_to_cpu(reply->reply.ret_minor));
|
||||
} else {
|
||||
enic->vf_registered = false;
|
||||
}
|
||||
complete(&enic->mbox_comp);
|
||||
}
|
||||
|
||||
static void enic_mbox_vf_handle_link_state(struct enic *enic, void *payload)
|
||||
static void enic_mbox_vf_handle_link_state(struct enic *enic, void *payload,
|
||||
u64 msg_num)
|
||||
{
|
||||
struct enic_mbox_pf_link_state_notif_msg *notif = payload;
|
||||
struct enic_mbox_pf_link_state_ack_msg ack = {};
|
||||
u32 link_state = le32_to_cpu(notif->link_state);
|
||||
int err;
|
||||
|
||||
switch (le32_to_cpu(notif->link_state)) {
|
||||
spin_lock_bh(&enic->vf_link_state_lock);
|
||||
switch (link_state) {
|
||||
case ENIC_MBOX_LINK_STATE_ENABLE:
|
||||
if (!netif_carrier_ok(enic->netdev))
|
||||
enic->vf_link_state = ENIC_VF_LINK_STATE_UP;
|
||||
if (enic->vf_link_running &&
|
||||
!netif_carrier_ok(enic->netdev))
|
||||
netif_carrier_on(enic->netdev);
|
||||
netdev_dbg(enic->netdev, "MBOX: link state -> UP\n");
|
||||
break;
|
||||
case ENIC_MBOX_LINK_STATE_DISABLE:
|
||||
if (netif_carrier_ok(enic->netdev))
|
||||
enic->vf_link_state = ENIC_VF_LINK_STATE_DOWN;
|
||||
if (enic->vf_link_running &&
|
||||
netif_carrier_ok(enic->netdev))
|
||||
netif_carrier_off(enic->netdev);
|
||||
netdev_dbg(enic->netdev, "MBOX: link state -> DOWN\n");
|
||||
break;
|
||||
default:
|
||||
netdev_warn(enic->netdev, "MBOX: unknown link state %u\n",
|
||||
le32_to_cpu(notif->link_state));
|
||||
link_state);
|
||||
ack.ack.ret_major = cpu_to_le16(ENIC_MBOX_ERR_GENERIC);
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(&enic->vf_link_state_lock);
|
||||
|
||||
err = enic_mbox_send_msg(enic, ENIC_MBOX_PF_LINK_STATE_ACK,
|
||||
ENIC_MBOX_DST_PF, &ack, sizeof(ack));
|
||||
err = enic_mbox_send_reply(enic, ENIC_MBOX_PF_LINK_STATE_ACK,
|
||||
ENIC_MBOX_DST_PF, &ack, sizeof(ack), msg_num);
|
||||
if (err && net_ratelimit())
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: failed to send link state ACK: %d\n", err);
|
||||
}
|
||||
|
||||
void enic_mbox_vf_link_state_reset(struct enic *enic)
|
||||
{
|
||||
spin_lock_bh(&enic->vf_link_state_lock);
|
||||
enic->vf_link_state = ENIC_VF_LINK_STATE_UNKNOWN;
|
||||
if (enic->vf_link_running && netif_carrier_ok(enic->netdev))
|
||||
netif_carrier_off(enic->netdev);
|
||||
spin_unlock_bh(&enic->vf_link_state_lock);
|
||||
}
|
||||
|
||||
void enic_mbox_vf_link_state_set_running(struct enic *enic, bool running)
|
||||
{
|
||||
spin_lock_bh(&enic->vf_link_state_lock);
|
||||
enic->vf_link_running = running;
|
||||
if (running && enic->vf_link_state == ENIC_VF_LINK_STATE_UP) {
|
||||
if (!netif_carrier_ok(enic->netdev))
|
||||
netif_carrier_on(enic->netdev);
|
||||
} else if (netif_carrier_ok(enic->netdev)) {
|
||||
netif_carrier_off(enic->netdev);
|
||||
}
|
||||
spin_unlock_bh(&enic->vf_link_state_lock);
|
||||
}
|
||||
|
||||
static bool enic_mbox_vf_payload_ok(struct enic *enic, u8 msg_type,
|
||||
u16 payload_len, size_t min_len)
|
||||
{
|
||||
|
|
@ -439,6 +515,8 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
|
|||
struct enic_mbox_hdr *hdr, void *payload,
|
||||
u16 payload_len)
|
||||
{
|
||||
u64 msg_num = le64_to_cpu(hdr->msg_num);
|
||||
|
||||
switch (hdr->msg_type) {
|
||||
case ENIC_MBOX_VF_CAPABILITY_REPLY: {
|
||||
size_t exp = sizeof(struct enic_mbox_vf_capability_reply_msg);
|
||||
|
|
@ -446,7 +524,7 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
|
|||
if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type,
|
||||
payload_len, exp))
|
||||
return;
|
||||
enic_mbox_vf_handle_capability_reply(enic, payload);
|
||||
enic_mbox_vf_handle_reply(enic, hdr->msg_type, payload, msg_num);
|
||||
break;
|
||||
}
|
||||
case ENIC_MBOX_VF_REGISTER_REPLY: {
|
||||
|
|
@ -455,7 +533,7 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
|
|||
if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type,
|
||||
payload_len, exp))
|
||||
return;
|
||||
enic_mbox_vf_handle_register_reply(enic, payload);
|
||||
enic_mbox_vf_handle_reply(enic, hdr->msg_type, payload, msg_num);
|
||||
break;
|
||||
}
|
||||
case ENIC_MBOX_VF_UNREGISTER_REPLY: {
|
||||
|
|
@ -464,7 +542,7 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
|
|||
if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type,
|
||||
payload_len, exp))
|
||||
return;
|
||||
enic_mbox_vf_handle_unregister_reply(enic, payload);
|
||||
enic_mbox_vf_handle_reply(enic, hdr->msg_type, payload, msg_num);
|
||||
break;
|
||||
}
|
||||
case ENIC_MBOX_PF_LINK_STATE_NOTIF: {
|
||||
|
|
@ -473,7 +551,7 @@ static void enic_mbox_vf_process_msg(struct enic *enic,
|
|||
if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type,
|
||||
payload_len, exp))
|
||||
return;
|
||||
enic_mbox_vf_handle_link_state(enic, payload);
|
||||
enic_mbox_vf_handle_link_state(enic, payload, msg_num);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -542,32 +620,31 @@ static void enic_mbox_recv_handler(struct enic *enic, void *buf,
|
|||
int enic_mbox_vf_capability_check(struct enic *enic)
|
||||
{
|
||||
struct enic_mbox_vf_capability_msg req = {};
|
||||
u32 version;
|
||||
int err;
|
||||
|
||||
enic->pf_cap_version = 0;
|
||||
reinit_completion(&enic->mbox_comp);
|
||||
WRITE_ONCE(enic->mbox_expected_reply, ENIC_MBOX_VF_CAPABILITY_REPLY);
|
||||
WRITE_ONCE(enic->pf_cap_version, 0);
|
||||
req.version = cpu_to_le32(ENIC_MBOX_CAP_VERSION_1);
|
||||
|
||||
err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_CAPABILITY_REQUEST,
|
||||
ENIC_MBOX_DST_PF, &req, sizeof(req));
|
||||
if (err) {
|
||||
WRITE_ONCE(enic->mbox_expected_reply, 0);
|
||||
err = enic_mbox_vf_send_request(enic,
|
||||
ENIC_MBOX_VF_CAPABILITY_REQUEST,
|
||||
ENIC_MBOX_VF_CAPABILITY_REPLY,
|
||||
&req, sizeof(req));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = enic_mbox_wait_reply(enic, 3000);
|
||||
WRITE_ONCE(enic->mbox_expected_reply, 0);
|
||||
version = READ_ONCE(enic->pf_cap_version);
|
||||
if (err) {
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: no capability reply from PF\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (enic->pf_cap_version < ENIC_MBOX_CAP_VERSION_1) {
|
||||
if (version < ENIC_MBOX_CAP_VERSION_1) {
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: PF rejected capability request or reported unsupported version %u\n",
|
||||
enic->pf_cap_version);
|
||||
version);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
|
@ -576,28 +653,25 @@ int enic_mbox_vf_capability_check(struct enic *enic)
|
|||
|
||||
int enic_mbox_vf_register(struct enic *enic)
|
||||
{
|
||||
bool registered;
|
||||
int err;
|
||||
|
||||
enic->vf_registered = false;
|
||||
reinit_completion(&enic->mbox_comp);
|
||||
WRITE_ONCE(enic->mbox_expected_reply, ENIC_MBOX_VF_REGISTER_REPLY);
|
||||
WRITE_ONCE(enic->vf_registered, false);
|
||||
|
||||
err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_REGISTER_REQUEST,
|
||||
ENIC_MBOX_DST_PF, NULL, 0);
|
||||
if (err) {
|
||||
WRITE_ONCE(enic->mbox_expected_reply, 0);
|
||||
err = enic_mbox_vf_send_request(enic, ENIC_MBOX_VF_REGISTER_REQUEST,
|
||||
ENIC_MBOX_VF_REGISTER_REPLY, NULL, 0);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = enic_mbox_wait_reply(enic, 3000);
|
||||
WRITE_ONCE(enic->mbox_expected_reply, 0);
|
||||
registered = READ_ONCE(enic->vf_registered);
|
||||
if (err) {
|
||||
netdev_warn(enic->netdev,
|
||||
"MBOX: VF registration with PF timed out\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!enic->vf_registered)
|
||||
if (!registered)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
|
|
@ -605,43 +679,48 @@ int enic_mbox_vf_register(struct enic *enic)
|
|||
|
||||
int enic_mbox_vf_unregister(struct enic *enic)
|
||||
{
|
||||
bool registered;
|
||||
int err;
|
||||
|
||||
if (!enic->vf_registered)
|
||||
if (!READ_ONCE(enic->vf_registered))
|
||||
return 0;
|
||||
|
||||
reinit_completion(&enic->mbox_comp);
|
||||
WRITE_ONCE(enic->mbox_expected_reply, ENIC_MBOX_VF_UNREGISTER_REPLY);
|
||||
|
||||
err = enic_mbox_send_msg(enic, ENIC_MBOX_VF_UNREGISTER_REQUEST,
|
||||
ENIC_MBOX_DST_PF, NULL, 0);
|
||||
if (err) {
|
||||
WRITE_ONCE(enic->mbox_expected_reply, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = enic_mbox_wait_reply(enic, 3000);
|
||||
WRITE_ONCE(enic->mbox_expected_reply, 0);
|
||||
err = enic_mbox_vf_send_request(enic,
|
||||
ENIC_MBOX_VF_UNREGISTER_REQUEST,
|
||||
ENIC_MBOX_VF_UNREGISTER_REPLY,
|
||||
NULL, 0);
|
||||
if (err)
|
||||
return err;
|
||||
if (enic->vf_registered)
|
||||
|
||||
err = enic_mbox_wait_reply(enic, 3000);
|
||||
registered = READ_ONCE(enic->vf_registered);
|
||||
if (err)
|
||||
return err;
|
||||
if (registered)
|
||||
return -EACCES;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void enic_mbox_init(struct enic *enic)
|
||||
{
|
||||
/* mbox_lock and mbox_comp must be initialized exactly once per
|
||||
bool reinit = enic->mbox_initialized;
|
||||
|
||||
/* MBOX locks and mbox_comp must be initialized exactly once per
|
||||
* device lifetime; the PF sriov_configure path can re-enter this
|
||||
* on each enable cycle where these primitives are already set up.
|
||||
*/
|
||||
if (!enic->mbox_initialized) {
|
||||
if (!reinit) {
|
||||
mutex_init(&enic->mbox_lock);
|
||||
init_completion(&enic->mbox_comp);
|
||||
spin_lock_init(&enic->mbox_state_lock);
|
||||
enic->mbox_msg_num = 0;
|
||||
enic->mbox_initialized = true;
|
||||
} else {
|
||||
reinit_completion(&enic->mbox_comp);
|
||||
}
|
||||
enic->mbox_msg_num = 0;
|
||||
spin_lock_bh(&enic->mbox_state_lock);
|
||||
enic->mbox_expected_reply = 0;
|
||||
enic->mbox_expected_msg_num = 0;
|
||||
spin_unlock_bh(&enic->mbox_state_lock);
|
||||
enic->admin_rq_handler = enic_mbox_recv_handler;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ void enic_mbox_init(struct enic *enic);
|
|||
int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id,
|
||||
void *payload, u16 payload_len);
|
||||
int enic_mbox_send_link_state(struct enic *enic, u16 vf_id, u32 link_state);
|
||||
void enic_mbox_vf_link_state_reset(struct enic *enic);
|
||||
void enic_mbox_vf_link_state_set_running(struct enic *enic, bool running);
|
||||
int enic_mbox_vf_capability_check(struct enic *enic);
|
||||
int enic_mbox_vf_register(struct enic *enic);
|
||||
int enic_mbox_vf_unregister(struct enic *enic);
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ struct gemini_ethernet_port {
|
|||
unsigned int rx_coalesce_nsecs;
|
||||
struct sk_buff *rx_skb;
|
||||
unsigned int rx_frag_nr;
|
||||
bool rx_dropping;
|
||||
|
||||
unsigned int freeq_refill;
|
||||
struct gmac_txq txq[TX_QUEUE_NUM];
|
||||
|
|
@ -1439,7 +1440,8 @@ static struct sk_buff *gmac_skb_if_good_frame(struct gemini_ethernet_port *port,
|
|||
return skb;
|
||||
}
|
||||
|
||||
static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
|
||||
static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget,
|
||||
unsigned int *freeq_consumed)
|
||||
{
|
||||
struct gemini_ethernet_port *port = netdev_priv(netdev);
|
||||
unsigned short m = (1 << port->rxq_order) - 1;
|
||||
|
|
@ -1447,9 +1449,12 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
|
|||
void __iomem *ptr_reg = port->rxq_rwptr;
|
||||
unsigned int frag_nr = port->rx_frag_nr;
|
||||
struct sk_buff *skb = port->rx_skb;
|
||||
unsigned int consumed = 0;
|
||||
unsigned int frame_len, frag_len;
|
||||
struct gmac_rxdesc *rx = NULL;
|
||||
struct gmac_queue_page *gpage;
|
||||
unsigned int received = 0;
|
||||
bool dropping = port->rx_dropping;
|
||||
union gmac_rxdesc_0 word0;
|
||||
union gmac_rxdesc_1 word1;
|
||||
union gmac_rxdesc_3 word3;
|
||||
|
|
@ -1471,6 +1476,7 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
|
|||
w = rw.bits.wptr;
|
||||
|
||||
while (budget && w != r) {
|
||||
page = NULL;
|
||||
rx = port->rxq_ring + r;
|
||||
word0 = rx->word0;
|
||||
word1 = rx->word1;
|
||||
|
|
@ -1479,11 +1485,22 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
|
|||
|
||||
r++;
|
||||
r &= m;
|
||||
consumed++;
|
||||
|
||||
frag_len = word0.bits.buffer_size;
|
||||
frame_len = word1.bits.byte_count;
|
||||
page_offs = mapping & ~PAGE_MASK;
|
||||
|
||||
if (word3.bits32 & SOF_BIT) {
|
||||
if (skb) {
|
||||
napi_free_frags(&port->napi);
|
||||
port->stats.rx_dropped++;
|
||||
skb = NULL;
|
||||
frag_nr = 0;
|
||||
}
|
||||
dropping = false;
|
||||
}
|
||||
|
||||
if (!mapping) {
|
||||
netdev_err(netdev,
|
||||
"rxq[%u]: HW BUG: zero DMA desc\n", r);
|
||||
|
|
@ -1494,24 +1511,11 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
|
|||
gpage = gmac_get_queue_page(geth, port, mapping + PAGE_SIZE);
|
||||
if (!gpage) {
|
||||
dev_err(geth->dev, "could not find mapping\n");
|
||||
port->stats.rx_dropped++;
|
||||
if (skb) {
|
||||
napi_free_frags(&port->napi);
|
||||
skb = NULL;
|
||||
frag_nr = 0;
|
||||
}
|
||||
continue;
|
||||
goto err_drop;
|
||||
}
|
||||
page = gpage->page;
|
||||
|
||||
if (word3.bits32 & SOF_BIT) {
|
||||
if (skb) {
|
||||
napi_free_frags(&port->napi);
|
||||
port->stats.rx_dropped++;
|
||||
skb = NULL;
|
||||
frag_nr = 0;
|
||||
}
|
||||
|
||||
skb = gmac_skb_if_good_frame(port, word0, frame_len);
|
||||
if (!skb)
|
||||
goto err_drop;
|
||||
|
|
@ -1521,8 +1525,7 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
|
|||
frag_nr = 0;
|
||||
|
||||
} else if (!skb) {
|
||||
put_page(page);
|
||||
continue;
|
||||
goto err_drop;
|
||||
}
|
||||
|
||||
if (word3.bits32 & EOF_BIT)
|
||||
|
|
@ -1545,9 +1548,8 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
|
|||
napi_gro_frags(&port->napi);
|
||||
skb = NULL;
|
||||
frag_nr = 0;
|
||||
--budget;
|
||||
}
|
||||
continue;
|
||||
goto next_desc;
|
||||
|
||||
err_drop:
|
||||
if (skb) {
|
||||
|
|
@ -1556,16 +1558,29 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
|
|||
frag_nr = 0;
|
||||
}
|
||||
|
||||
if (mapping)
|
||||
if (page)
|
||||
put_page(page);
|
||||
|
||||
port->stats.rx_dropped++;
|
||||
if (!dropping) {
|
||||
port->stats.rx_dropped++;
|
||||
dropping = true;
|
||||
}
|
||||
|
||||
next_desc:
|
||||
/* Final or single-descriptor fragment, advance things */
|
||||
if (word3.bits32 & EOF_BIT) {
|
||||
budget--;
|
||||
received++;
|
||||
dropping = false;
|
||||
}
|
||||
}
|
||||
|
||||
port->rx_skb = skb;
|
||||
port->rx_frag_nr = frag_nr;
|
||||
port->rx_dropping = dropping;
|
||||
*freeq_consumed = consumed;
|
||||
writew(r, ptr_reg);
|
||||
return budget;
|
||||
return received;
|
||||
}
|
||||
|
||||
static int gmac_napi_poll(struct napi_struct *napi, int budget)
|
||||
|
|
@ -1573,26 +1588,27 @@ static int gmac_napi_poll(struct napi_struct *napi, int budget)
|
|||
struct gemini_ethernet_port *port = netdev_priv(napi->dev);
|
||||
struct gemini_ethernet *geth = port->geth;
|
||||
unsigned int freeq_threshold;
|
||||
unsigned int freeq_consumed;
|
||||
unsigned int received;
|
||||
|
||||
freeq_threshold = 1 << (geth->freeq_order - 1);
|
||||
u64_stats_update_begin(&port->rx_stats_syncp);
|
||||
|
||||
received = gmac_rx(napi->dev, budget);
|
||||
if (received < budget) {
|
||||
napi_gro_flush(napi, false);
|
||||
napi_complete_done(napi, received);
|
||||
gmac_enable_rx_irq(napi->dev, 1);
|
||||
received = gmac_rx(napi->dev, budget, &freeq_consumed);
|
||||
if (received < budget)
|
||||
++port->rx_napi_exits;
|
||||
}
|
||||
|
||||
port->freeq_refill += (budget - received);
|
||||
u64_stats_update_end(&port->rx_stats_syncp);
|
||||
|
||||
port->freeq_refill += freeq_consumed;
|
||||
if (port->freeq_refill > freeq_threshold) {
|
||||
port->freeq_refill -= freeq_threshold;
|
||||
geth_fill_freeq(geth, true);
|
||||
}
|
||||
|
||||
u64_stats_update_end(&port->rx_stats_syncp);
|
||||
if (received < budget && napi_complete_done(napi, received))
|
||||
gmac_enable_rx_irq(napi->dev, 1);
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
|
|
@ -1893,6 +1909,7 @@ static int gmac_stop(struct net_device *netdev)
|
|||
napi_disable(&port->napi);
|
||||
port->rx_skb = NULL;
|
||||
port->rx_frag_nr = 0;
|
||||
port->rx_dropping = false;
|
||||
|
||||
gmac_enable_irq(netdev, 0);
|
||||
gmac_cleanup_rxq(netdev);
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ enum hinic_mbox_tx_status {
|
|||
|
||||
#define SEQ_ID_START_VAL 0
|
||||
#define SEQ_ID_MAX_VAL 42
|
||||
#define MBOX_LAST_SEG_MAX_LEN (MBOX_MAX_BUF_SZ - SEQ_ID_MAX_VAL * MBOX_SEG_LEN)
|
||||
|
||||
#define NO_DMA_ATTRIBUTE_VAL 0
|
||||
|
||||
|
|
@ -372,7 +373,8 @@ recv_pf_from_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
|
|||
static bool check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox *recv_mbox,
|
||||
u8 seq_id, u8 seg_len)
|
||||
{
|
||||
if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN)
|
||||
if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN ||
|
||||
(seq_id == SEQ_ID_MAX_VAL && seg_len > MBOX_LAST_SEG_MAX_LEN))
|
||||
return false;
|
||||
|
||||
if (seq_id == 0) {
|
||||
|
|
|
|||
|
|
@ -1051,14 +1051,13 @@ int ice_init_hw(struct ice_hw *hw)
|
|||
|
||||
hw->evb_veb = true;
|
||||
|
||||
/* init xarray for identifying scheduling nodes uniquely */
|
||||
xa_init_flags(&hw->port_info->sched_node_ids, XA_FLAGS_ALLOC);
|
||||
xa_init_flags(&hw->sched_node_ids, XA_FLAGS_ALLOC);
|
||||
|
||||
/* Query the allocated resources for Tx scheduler */
|
||||
status = ice_sched_query_res_alloc(hw);
|
||||
if (status) {
|
||||
ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n");
|
||||
goto err_unroll_alloc;
|
||||
goto err_unroll_xarray;
|
||||
}
|
||||
ice_sched_get_psm_clk_freq(hw);
|
||||
|
||||
|
|
@ -1146,6 +1145,8 @@ int ice_init_hw(struct ice_hw *hw)
|
|||
ice_cleanup_fltr_mgmt_struct(hw);
|
||||
err_unroll_sched:
|
||||
ice_sched_cleanup_all(hw);
|
||||
err_unroll_xarray:
|
||||
xa_destroy(&hw->sched_node_ids);
|
||||
err_unroll_alloc:
|
||||
devm_kfree(ice_hw_to_dev(hw), hw->port_info);
|
||||
err_unroll_cqinit:
|
||||
|
|
@ -1186,6 +1187,8 @@ void ice_deinit_hw(struct ice_hw *hw)
|
|||
|
||||
/* Clear VSI contexts if not already cleared */
|
||||
ice_clear_all_vsi_ctx(hw);
|
||||
|
||||
xa_destroy(&hw->sched_node_ids);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
|
|||
|
||||
devm_kfree(ice_hw_to_dev(hw), node->children);
|
||||
kfree(node->name);
|
||||
xa_erase(&pi->sched_node_ids, node->id);
|
||||
xa_erase(&hw->sched_node_ids, node->id);
|
||||
devm_kfree(ice_hw_to_dev(hw), node);
|
||||
}
|
||||
|
||||
|
|
@ -977,7 +977,7 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
|
|||
if (!new_node->name)
|
||||
return -ENOMEM;
|
||||
|
||||
status = xa_alloc(&pi->sched_node_ids, &new_node->id, NULL, XA_LIMIT(0, UINT_MAX),
|
||||
status = xa_alloc(&hw->sched_node_ids, &new_node->id, NULL, XA_LIMIT(0, UINT_MAX),
|
||||
GFP_KERNEL);
|
||||
if (status) {
|
||||
ice_debug(hw, ICE_DBG_SCHED, "xa_alloc failed for sched node status =%d\n",
|
||||
|
|
|
|||
|
|
@ -63,23 +63,33 @@
|
|||
DECLARE_EVENT_CLASS(ice_rx_dim_template,
|
||||
TP_PROTO(struct ice_q_vector *q_vector, struct dim *dim),
|
||||
TP_ARGS(q_vector, dim),
|
||||
TP_STRUCT__entry(__field(struct ice_q_vector *, q_vector)
|
||||
__field(struct dim *, dim)
|
||||
TP_STRUCT__entry(__field(u16, q_index)
|
||||
__field(u8, state)
|
||||
__field(u8, profile_ix)
|
||||
__field(u8, tune_state)
|
||||
__field(u8, steps_right)
|
||||
__field(u8, steps_left)
|
||||
__field(u8, tired)
|
||||
__string(devname, q_vector->rx.rx_ring->netdev->name)),
|
||||
|
||||
TP_fast_assign(__entry->q_vector = q_vector;
|
||||
__entry->dim = dim;
|
||||
TP_fast_assign(__entry->q_index = q_vector->rx.rx_ring->q_index;
|
||||
__entry->state = dim->state;
|
||||
__entry->profile_ix = dim->profile_ix;
|
||||
__entry->tune_state = dim->tune_state;
|
||||
__entry->steps_right = dim->steps_right;
|
||||
__entry->steps_left = dim->steps_left;
|
||||
__entry->tired = dim->tired;
|
||||
__assign_str(devname);),
|
||||
|
||||
TP_printk("netdev: %s Rx-Q: %d dim-state: %d dim-profile: %d dim-tune: %d dim-st-right: %d dim-st-left: %d dim-tired: %d",
|
||||
__get_str(devname),
|
||||
__entry->q_vector->rx.rx_ring->q_index,
|
||||
__entry->dim->state,
|
||||
__entry->dim->profile_ix,
|
||||
__entry->dim->tune_state,
|
||||
__entry->dim->steps_right,
|
||||
__entry->dim->steps_left,
|
||||
__entry->dim->tired)
|
||||
__entry->q_index,
|
||||
__entry->state,
|
||||
__entry->profile_ix,
|
||||
__entry->tune_state,
|
||||
__entry->steps_right,
|
||||
__entry->steps_left,
|
||||
__entry->tired)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ice_rx_dim_template, ice_rx_dim_work,
|
||||
|
|
@ -90,23 +100,33 @@ DEFINE_EVENT(ice_rx_dim_template, ice_rx_dim_work,
|
|||
DECLARE_EVENT_CLASS(ice_tx_dim_template,
|
||||
TP_PROTO(struct ice_q_vector *q_vector, struct dim *dim),
|
||||
TP_ARGS(q_vector, dim),
|
||||
TP_STRUCT__entry(__field(struct ice_q_vector *, q_vector)
|
||||
__field(struct dim *, dim)
|
||||
TP_STRUCT__entry(__field(u16, q_index)
|
||||
__field(u8, state)
|
||||
__field(u8, profile_ix)
|
||||
__field(u8, tune_state)
|
||||
__field(u8, steps_right)
|
||||
__field(u8, steps_left)
|
||||
__field(u8, tired)
|
||||
__string(devname, q_vector->tx.tx_ring->netdev->name)),
|
||||
|
||||
TP_fast_assign(__entry->q_vector = q_vector;
|
||||
__entry->dim = dim;
|
||||
TP_fast_assign(__entry->q_index = q_vector->tx.tx_ring->q_index;
|
||||
__entry->state = dim->state;
|
||||
__entry->profile_ix = dim->profile_ix;
|
||||
__entry->tune_state = dim->tune_state;
|
||||
__entry->steps_right = dim->steps_right;
|
||||
__entry->steps_left = dim->steps_left;
|
||||
__entry->tired = dim->tired;
|
||||
__assign_str(devname);),
|
||||
|
||||
TP_printk("netdev: %s Tx-Q: %d dim-state: %d dim-profile: %d dim-tune: %d dim-st-right: %d dim-st-left: %d dim-tired: %d",
|
||||
__get_str(devname),
|
||||
__entry->q_vector->tx.tx_ring->q_index,
|
||||
__entry->dim->state,
|
||||
__entry->dim->profile_ix,
|
||||
__entry->dim->tune_state,
|
||||
__entry->dim->steps_right,
|
||||
__entry->dim->steps_left,
|
||||
__entry->dim->tired)
|
||||
__entry->q_index,
|
||||
__entry->state,
|
||||
__entry->profile_ix,
|
||||
__entry->tune_state,
|
||||
__entry->steps_right,
|
||||
__entry->steps_left,
|
||||
__entry->tired)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ice_tx_dim_template, ice_tx_dim_work,
|
||||
|
|
|
|||
|
|
@ -765,7 +765,6 @@ struct ice_port_info {
|
|||
/* List contain profile ID(s) and other params per layer */
|
||||
struct list_head rl_prof_list[ICE_AQC_TOPO_MAX_LEVEL_NUM];
|
||||
struct ice_qos_cfg qos_cfg;
|
||||
struct xarray sched_node_ids;
|
||||
u8 is_vf:1;
|
||||
u8 is_custom_tx_enabled:1;
|
||||
};
|
||||
|
|
@ -930,6 +929,7 @@ struct ice_hw {
|
|||
u8 sw_entry_point_layer;
|
||||
u16 max_children[ICE_AQC_TOPO_MAX_LEVEL_NUM];
|
||||
struct list_head agg_list; /* lists all aggregator */
|
||||
struct xarray sched_node_ids;
|
||||
|
||||
struct ice_vsi_ctx *vsi_ctx[ICE_MAX_VSI];
|
||||
u8 evb_veb; /* true for VEB, false for VEPA */
|
||||
|
|
|
|||
|
|
@ -106,6 +106,11 @@ static int idpf_dev_init(struct idpf_adapter *adapter,
|
|||
*/
|
||||
static void idpf_decfg_device(struct idpf_adapter *adapter)
|
||||
{
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
|
||||
if (pcie_ptm_enabled(pdev))
|
||||
pci_disable_ptm(pdev);
|
||||
|
||||
libie_pci_unmap_all_mmio_regions(&adapter->ctlq_ctx.mmio_info);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3299,6 +3299,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
|
|||
struct libeth_rx_pt decoded)
|
||||
{
|
||||
u16 rsc_segments, rsc_seg_len;
|
||||
u16 l3_start = 0;
|
||||
bool ipv4, ipv6;
|
||||
int len;
|
||||
|
||||
|
|
@ -3321,7 +3322,10 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
|
|||
NAPI_GRO_CB(skb)->count = rsc_segments;
|
||||
skb_shinfo(skb)->gso_size = rsc_seg_len;
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
if (unlikely(eth_type_vlan(skb->protocol)))
|
||||
l3_start = VLAN_HLEN;
|
||||
|
||||
skb_set_network_header(skb, l3_start);
|
||||
|
||||
if (ipv4) {
|
||||
struct iphdr *ipv4h = ip_hdr(skb);
|
||||
|
|
@ -3329,7 +3333,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
|
|||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
|
||||
|
||||
/* Reset and set transport header offset in skb */
|
||||
skb_set_transport_header(skb, sizeof(struct iphdr));
|
||||
skb_set_transport_header(skb, l3_start + sizeof(struct iphdr));
|
||||
len = skb->len - skb_transport_offset(skb);
|
||||
|
||||
/* Compute the TCP pseudo header checksum*/
|
||||
|
|
@ -3339,7 +3343,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
|
|||
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
|
||||
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
|
||||
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
|
||||
skb_set_transport_header(skb, l3_start + sizeof(struct ipv6hdr));
|
||||
len = skb->len - skb_transport_offset(skb);
|
||||
tcp_hdr(skb)->check =
|
||||
~tcp_v6_check(len, &ipv6h->saddr, &ipv6h->daddr, 0);
|
||||
|
|
@ -4145,6 +4149,26 @@ static void idpf_vport_intr_ena_irq_all(struct idpf_vport *vport,
|
|||
writel(rsrc->noirq_dyn_ctl_ena, rsrc->noirq_dyn_ctl);
|
||||
}
|
||||
|
||||
/**
|
||||
* idpf_vport_intr_dis_dim_all - Disable DIM work for all q_vectors
|
||||
* @rsrc: pointer to queue and vector resources
|
||||
*
|
||||
* The DIM works are embedded in the q_vector array that
|
||||
* idpf_vport_intr_rel() frees, and the poll arms them after
|
||||
* napi_complete_done() has already cleared NAPI_STATE_SCHED. Disable
|
||||
* rather than just cancel, so that a poll tail still running past
|
||||
* napi_disable() cannot queue them again behind the drain.
|
||||
*/
|
||||
static void idpf_vport_intr_dis_dim_all(struct idpf_q_vec_rsrc *rsrc)
|
||||
{
|
||||
for (u16 v_idx = 0; v_idx < rsrc->num_q_vectors; v_idx++) {
|
||||
struct idpf_q_vector *q_vector = &rsrc->q_vectors[v_idx];
|
||||
|
||||
disable_work_sync(&q_vector->tx_dim.work);
|
||||
disable_work_sync(&q_vector->rx_dim.work);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* idpf_vport_intr_deinit - Release all vector associations for the vport
|
||||
* @vport: main vport structure
|
||||
|
|
@ -4155,6 +4179,7 @@ void idpf_vport_intr_deinit(struct idpf_vport *vport,
|
|||
{
|
||||
idpf_vport_intr_dis_irq_all(rsrc);
|
||||
idpf_vport_intr_napi_dis_all(rsrc);
|
||||
idpf_vport_intr_dis_dim_all(rsrc);
|
||||
idpf_vport_intr_napi_del_all(rsrc);
|
||||
idpf_vport_intr_rel_irq(vport, rsrc);
|
||||
}
|
||||
|
|
@ -4235,7 +4260,6 @@ static void idpf_vport_intr_napi_ena_all(struct idpf_q_vec_rsrc *rsrc)
|
|||
for (u16 q_idx = 0; q_idx < rsrc->num_q_vectors; q_idx++) {
|
||||
struct idpf_q_vector *q_vector = &rsrc->q_vectors[q_idx];
|
||||
|
||||
idpf_init_dim(q_vector);
|
||||
napi_enable(&q_vector->napi);
|
||||
}
|
||||
}
|
||||
|
|
@ -4578,6 +4602,8 @@ int idpf_vport_intr_alloc(struct idpf_vport *vport,
|
|||
q_coal = &user_config->q_coalesce[v_idx];
|
||||
q_vector->vport = vport;
|
||||
|
||||
idpf_init_dim(q_vector);
|
||||
|
||||
q_vector->tx_itr_value = q_coal->tx_coalesce_usecs;
|
||||
q_vector->tx_intr_mode = q_coal->tx_intr_mode;
|
||||
q_vector->tx_itr_idx = VIRTCHNL2_ITR_IDX_1;
|
||||
|
|
|
|||
|
|
@ -1417,6 +1417,16 @@ static int mcs_x2p_calibration(struct mcs *mcs)
|
|||
int i, err = 0;
|
||||
u64 val;
|
||||
|
||||
/* Clear any stale calibration state left by firmware/bootloader.
|
||||
* Some firmware versions may leave MCSX_MIL_GLOBAL bit 5 set,
|
||||
* preventing the hardware from detecting the rising edge needed to
|
||||
* trigger X2P calibration.
|
||||
*/
|
||||
val = mcs_reg_read(mcs, MCSX_MIL_GLOBAL);
|
||||
val &= ~BIT_ULL(5);
|
||||
mcs_reg_write(mcs, MCSX_MIL_GLOBAL, val);
|
||||
usleep_range(100, 200);
|
||||
|
||||
/* set X2P calibration */
|
||||
val = mcs_reg_read(mcs, MCSX_MIL_GLOBAL);
|
||||
val |= BIT_ULL(5);
|
||||
|
|
|
|||
|
|
@ -829,19 +829,25 @@ static int rvu_dbg_rvu_pf_cgx_map_display(struct seq_file *filp, void *unused)
|
|||
int pf, domain, blkid;
|
||||
u8 cgx_id, lmac_id;
|
||||
u16 pcifunc;
|
||||
u8 start;
|
||||
|
||||
domain = 2;
|
||||
domain = pci_domain_nr(rvu->pdev->bus);
|
||||
mac_ops = get_mac_ops(rvu_first_cgx_pdata(rvu));
|
||||
/* There can be no CGX devices at all */
|
||||
if (!mac_ops)
|
||||
return 0;
|
||||
seq_printf(filp, "PCI dev\t\tRVU PF Func\tNIX block\t%s\tLMAC\tCHAN\n",
|
||||
mac_ops->name);
|
||||
|
||||
/* All the PF devices are on contiguous PCI bus numbers, but the PF0(AF)
|
||||
* may not start from 1 always. Hence get domain and bus from PCI device.
|
||||
*/
|
||||
start = rvu->pdev->bus->number;
|
||||
for (pf = 0; pf < rvu->hw->total_pfs; pf++) {
|
||||
if (!is_pf_cgxmapped(rvu, pf))
|
||||
continue;
|
||||
|
||||
pdev = pci_get_domain_bus_and_slot(domain, pf + 1, 0);
|
||||
pdev = pci_get_domain_bus_and_slot(domain, pf + start, 0);
|
||||
if (!pdev)
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -235,13 +235,63 @@ static int otx2_qos_txschq_set_parent_topology(struct otx2_nic *pfvf,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int otx2_qos_reset_schq_topology(struct otx2_nic *pfvf, u16 lvl,
|
||||
u16 schq)
|
||||
{
|
||||
struct mbox *mbox = &pfvf->mbox;
|
||||
struct nix_txschq_config *cfg;
|
||||
int rc;
|
||||
|
||||
if (lvl < NIX_TXSCH_LVL_TL4 || lvl >= NIX_TXSCH_LVL_TL1)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&mbox->lock);
|
||||
|
||||
cfg = otx2_mbox_alloc_msg_nix_txschq_cfg(mbox);
|
||||
if (!cfg) {
|
||||
mutex_unlock(&mbox->lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cfg->lvl = lvl;
|
||||
cfg->num_regs = 1;
|
||||
|
||||
if (lvl == NIX_TXSCH_LVL_TL4)
|
||||
cfg->reg[0] = NIX_AF_TL4X_TOPOLOGY(schq);
|
||||
else if (lvl == NIX_TXSCH_LVL_TL3)
|
||||
cfg->reg[0] = NIX_AF_TL3X_TOPOLOGY(schq);
|
||||
else if (lvl == NIX_TXSCH_LVL_TL2)
|
||||
cfg->reg[0] = NIX_AF_TL2X_TOPOLOGY(schq);
|
||||
|
||||
cfg->regval[0] = 0;
|
||||
|
||||
rc = otx2_sync_mbox_msg(mbox);
|
||||
|
||||
mutex_unlock(&mbox->lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void otx2_qos_free_hw_schq(struct otx2_nic *pfvf, u16 lvl, u16 schq)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = otx2_qos_reset_schq_topology(pfvf, lvl, schq);
|
||||
if (err)
|
||||
netdev_warn(pfvf->netdev,
|
||||
"QoS: failed to reset topology for schq %u at level %u: %d\n",
|
||||
schq, lvl, err);
|
||||
|
||||
otx2_txschq_free_one(pfvf, lvl, schq);
|
||||
}
|
||||
|
||||
static void otx2_qos_free_hw_node_schq(struct otx2_nic *pfvf,
|
||||
struct otx2_qos_node *parent)
|
||||
{
|
||||
struct otx2_qos_node *node;
|
||||
|
||||
list_for_each_entry_reverse(node, &parent->child_schq_list, list)
|
||||
otx2_txschq_free_one(pfvf, node->level, node->schq);
|
||||
otx2_qos_free_hw_schq(pfvf, node->level, node->schq);
|
||||
}
|
||||
|
||||
static void otx2_qos_free_hw_node(struct otx2_nic *pfvf,
|
||||
|
|
@ -252,7 +302,7 @@ static void otx2_qos_free_hw_node(struct otx2_nic *pfvf,
|
|||
list_for_each_entry_safe(node, tmp, &parent->child_list, list) {
|
||||
otx2_qos_free_hw_node(pfvf, node);
|
||||
otx2_qos_free_hw_node_schq(pfvf, node);
|
||||
otx2_txschq_free_one(pfvf, node->level, node->schq);
|
||||
otx2_qos_free_hw_schq(pfvf, node->level, node->schq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -266,7 +316,7 @@ static void otx2_qos_free_hw_cfg(struct otx2_nic *pfvf,
|
|||
otx2_qos_free_hw_node_schq(pfvf, node);
|
||||
|
||||
/* free node hw mappings */
|
||||
otx2_txschq_free_one(pfvf, node->level, node->schq);
|
||||
otx2_qos_free_hw_schq(pfvf, node->level, node->schq);
|
||||
|
||||
mutex_unlock(&pfvf->qos.qos_lock);
|
||||
}
|
||||
|
|
@ -913,7 +963,7 @@ static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg)
|
|||
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
|
||||
for (idx = 0; idx < cfg->schq[lvl]; idx++) {
|
||||
schq = cfg->schq_list[lvl][idx];
|
||||
otx2_txschq_free_one(pfvf, lvl, schq);
|
||||
otx2_qos_free_hw_schq(pfvf, lvl, schq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -921,7 +971,7 @@ static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg)
|
|||
for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {
|
||||
if (cfg->schq_index_used[lvl][idx]) {
|
||||
schq = cfg->schq_contig_list[lvl][idx];
|
||||
otx2_txschq_free_one(pfvf, lvl, schq);
|
||||
otx2_qos_free_hw_schq(pfvf, lvl, schq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4828,7 +4828,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
|
|||
phy_interface_t phy_mode;
|
||||
struct phylink *phylink;
|
||||
struct mtk_mac *mac;
|
||||
int id, err;
|
||||
int id, err, i;
|
||||
int txqs = 1;
|
||||
u32 val;
|
||||
|
||||
|
|
@ -4907,8 +4907,8 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
|
|||
mac->phylink_config.type = PHYLINK_NETDEV;
|
||||
mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
|
||||
MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
|
||||
mac->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD |
|
||||
MAC_2500FD;
|
||||
/* LPI above 1 Gbps is not supported */
|
||||
mac->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD;
|
||||
mac->phylink_config.lpi_timer_default = 1000;
|
||||
|
||||
/* MT7623 gmac0 is now missing its speed-specific PLL configuration
|
||||
|
|
@ -4966,6 +4966,18 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
|
|||
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
mac->phylink_config.supported_interfaces);
|
||||
|
||||
/* LPI wake-up timing is only verified on MTK_GMAC_EEE SoCs */
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC_EEE)) {
|
||||
phy_interface_copy(mac->phylink_config.lpi_interfaces,
|
||||
mac->phylink_config.supported_interfaces);
|
||||
__clear_bit(PHY_INTERFACE_MODE_2500BASEX,
|
||||
mac->phylink_config.lpi_interfaces);
|
||||
for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
|
||||
if (mtk_interface_mode_is_xgmii(eth, i))
|
||||
__clear_bit(i,
|
||||
mac->phylink_config.lpi_interfaces);
|
||||
}
|
||||
|
||||
phylink = phylink_create(&mac->phylink_config,
|
||||
of_fwnode_handle(mac->of_node),
|
||||
phy_mode, mac_ops);
|
||||
|
|
|
|||
|
|
@ -994,6 +994,7 @@ enum mkt_eth_capabilities {
|
|||
MTK_U3_COPHY_V2_BIT,
|
||||
MTK_SRAM_BIT,
|
||||
MTK_36BIT_DMA_BIT,
|
||||
MTK_GMAC_EEE_BIT,
|
||||
|
||||
/* MUX BITS*/
|
||||
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
|
||||
|
|
@ -1034,6 +1035,7 @@ enum mkt_eth_capabilities {
|
|||
#define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT)
|
||||
#define MTK_SRAM BIT_ULL(MTK_SRAM_BIT)
|
||||
#define MTK_36BIT_DMA BIT_ULL(MTK_36BIT_DMA_BIT)
|
||||
#define MTK_GMAC_EEE BIT_ULL(MTK_GMAC_EEE_BIT)
|
||||
|
||||
#define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \
|
||||
BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
|
||||
|
|
@ -1117,7 +1119,7 @@ enum mkt_eth_capabilities {
|
|||
#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
|
||||
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
|
||||
MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
|
||||
MTK_RSTCTRL_PPE1 | MTK_SRAM)
|
||||
MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_GMAC_EEE)
|
||||
|
||||
#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
|
||||
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
|
||||
|
|
|
|||
|
|
@ -557,6 +557,7 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
|
|||
u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
|
||||
int sz = MLX5_ST_SZ_BYTES(pplm_reg);
|
||||
u16 fec_policy_auto = 0;
|
||||
bool fec_set = false;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
|
|
@ -569,9 +570,6 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
|
|||
if (fec_policy >= (1 << MLX5E_FEC_LLRS_272_257_1) && !fec_50g_per_lane)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (fec_policy && !mlx5e_fec_in_caps(dev, fec_policy))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
MLX5_SET(pplm_reg, in, local_port, 1);
|
||||
err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
|
||||
if (err)
|
||||
|
|
@ -591,12 +589,17 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
|
|||
mlx5e_get_fec_cap_field(out, &fec_caps, i);
|
||||
|
||||
/* policy supported for link speed */
|
||||
if (fec_caps & conf_fec)
|
||||
if (fec_caps & conf_fec) {
|
||||
mlx5e_fec_admin_field(out, &conf_fec, 1, i);
|
||||
else
|
||||
/* set FEC to auto*/
|
||||
fec_set = true;
|
||||
} else {
|
||||
/* set FEC to auto */
|
||||
mlx5e_fec_admin_field(out, &fec_policy_auto, 1, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (fec_policy && !fec_set)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return mlx5_core_access_reg(dev, out, sz, out, sz, MLX5_REG_PPLM, 0, 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,4 +66,8 @@ enum {
|
|||
MLX5E_FEC_LLRS_272_257_1 = 9,
|
||||
};
|
||||
|
||||
#define MLX5E_FEC_RS_MASK (BIT(MLX5E_FEC_RS_528_514) | \
|
||||
BIT(MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD) | \
|
||||
BIT(MLX5E_FEC_RS_544_514))
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -311,12 +311,15 @@ sample_restore_get(struct mlx5e_tc_psample *tc_psample, u32 obj_id,
|
|||
static void
|
||||
sample_restore_put(struct mlx5e_tc_psample *tc_psample, struct mlx5e_sample_restore *restore)
|
||||
{
|
||||
bool last;
|
||||
|
||||
mutex_lock(&tc_psample->restore_lock);
|
||||
if (--restore->count == 0)
|
||||
last = --restore->count == 0;
|
||||
if (last)
|
||||
hash_del(&restore->hlist);
|
||||
mutex_unlock(&tc_psample->restore_lock);
|
||||
|
||||
if (!restore->count) {
|
||||
if (last) {
|
||||
mlx5_del_flow_rules(restore->rule);
|
||||
mlx5_modify_header_dealloc(tc_psample->esw->dev, restore->modify_hdr);
|
||||
kfree(restore);
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC &&
|
||||
if (priv->dcbx.tc_tsa[i] == IEEE_8021QAZ_TSA_ETS &&
|
||||
tc_group[i] == (MLX5E_LOWEST_PRIO_GROUP + 1))
|
||||
is_zero_bw_ets_tc = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -1002,9 +1002,9 @@ static u32 pplm2ethtool_fec(u_long fec_mode, unsigned long size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MLX5E_ADVERTISE_SUPPORTED_FEC(mlx5_fec, ethtool_fec) \
|
||||
#define MLX5E_ADVERTISE_SUPPORTED_FEC(fec_mask, ethtool_fec) \
|
||||
do { \
|
||||
if (mlx5e_fec_in_caps(dev, 1 << (mlx5_fec))) \
|
||||
if (mlx5e_fec_in_caps(dev, fec_mask)) \
|
||||
__set_bit(ethtool_fec, \
|
||||
link_ksettings->link_modes.supported);\
|
||||
} while (0)
|
||||
|
|
@ -1013,6 +1013,7 @@ static const u32 pplm_fec_2_ethtool_linkmodes[] = {
|
|||
[MLX5E_FEC_NOFEC] = ETHTOOL_LINK_MODE_FEC_NONE_BIT,
|
||||
[MLX5E_FEC_FIRECODE] = ETHTOOL_LINK_MODE_FEC_BASER_BIT,
|
||||
[MLX5E_FEC_RS_528_514] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
|
||||
[MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
|
||||
[MLX5E_FEC_RS_544_514] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
|
||||
[MLX5E_FEC_LLRS_272_257_1] = ETHTOOL_LINK_MODE_FEC_LLRS_BIT,
|
||||
};
|
||||
|
|
@ -1029,13 +1030,13 @@ static int get_fec_supported_advertised(struct mlx5_core_dev *dev,
|
|||
if (err)
|
||||
return (err == -EOPNOTSUPP) ? 0 : err;
|
||||
|
||||
MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_NOFEC,
|
||||
MLX5E_ADVERTISE_SUPPORTED_FEC(BIT(MLX5E_FEC_NOFEC),
|
||||
ETHTOOL_LINK_MODE_FEC_NONE_BIT);
|
||||
MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_FIRECODE,
|
||||
MLX5E_ADVERTISE_SUPPORTED_FEC(BIT(MLX5E_FEC_FIRECODE),
|
||||
ETHTOOL_LINK_MODE_FEC_BASER_BIT);
|
||||
MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_RS_528_514,
|
||||
MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_RS_MASK,
|
||||
ETHTOOL_LINK_MODE_FEC_RS_BIT);
|
||||
MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_LLRS_272_257_1,
|
||||
MLX5E_ADVERTISE_SUPPORTED_FEC(BIT(MLX5E_FEC_LLRS_272_257_1),
|
||||
ETHTOOL_LINK_MODE_FEC_LLRS_BIT);
|
||||
|
||||
active_fec_long = active_fec;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
#include "lib/vxlan.h"
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "diag/en_rep_tracepoint.h"
|
||||
#include "diag/reporter_vnic.h"
|
||||
#include "en_accel/ipsec.h"
|
||||
#include "en/tc/int_port.h"
|
||||
#include "en/ptp.h"
|
||||
|
|
@ -1439,51 +1438,6 @@ static unsigned int mlx5e_ul_rep_stats_grps_num(struct mlx5e_priv *priv)
|
|||
return ARRAY_SIZE(mlx5e_ul_rep_stats_grps);
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5e_rep_vnic_reporter_diagnose(struct devlink_health_reporter *reporter,
|
||||
struct devlink_fmsg *fmsg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5e_rep_priv *rpriv = devlink_health_reporter_priv(reporter);
|
||||
struct mlx5_eswitch_rep *rep = rpriv->rep;
|
||||
|
||||
mlx5_reporter_vnic_diagnose_counters(rep->esw->dev, fmsg, rep->vport,
|
||||
true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct devlink_health_reporter_ops mlx5_rep_vnic_reporter_ops = {
|
||||
.name = "vnic",
|
||||
.diagnose = mlx5e_rep_vnic_reporter_diagnose,
|
||||
};
|
||||
|
||||
static void mlx5e_rep_vnic_reporter_create(struct mlx5e_priv *priv,
|
||||
struct devlink_port *dl_port)
|
||||
{
|
||||
struct mlx5e_rep_priv *rpriv = priv->ppriv;
|
||||
struct devlink_health_reporter *reporter;
|
||||
|
||||
reporter = devl_port_health_reporter_create(dl_port,
|
||||
&mlx5_rep_vnic_reporter_ops,
|
||||
rpriv);
|
||||
if (IS_ERR(reporter)) {
|
||||
mlx5_core_err(priv->mdev,
|
||||
"Failed to create representor vnic reporter, err = %pe\n",
|
||||
reporter);
|
||||
return;
|
||||
}
|
||||
|
||||
rpriv->rep_vnic_reporter = reporter;
|
||||
}
|
||||
|
||||
static void mlx5e_rep_vnic_reporter_destroy(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5e_rep_priv *rpriv = priv->ppriv;
|
||||
|
||||
if (!IS_ERR_OR_NULL(rpriv->rep_vnic_reporter))
|
||||
devl_health_reporter_destroy(rpriv->rep_vnic_reporter);
|
||||
}
|
||||
|
||||
static const struct mlx5e_profile mlx5e_rep_profile = {
|
||||
.init = mlx5e_init_rep,
|
||||
.cleanup = mlx5e_cleanup_rep,
|
||||
|
|
@ -1607,10 +1561,8 @@ mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
|
|||
|
||||
dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch,
|
||||
rpriv->rep->vport);
|
||||
if (!IS_ERR(dl_port)) {
|
||||
if (!IS_ERR(dl_port))
|
||||
SET_NETDEV_DEVLINK_PORT(netdev, dl_port);
|
||||
mlx5e_rep_vnic_reporter_create(priv, dl_port);
|
||||
}
|
||||
|
||||
err = register_netdev(netdev);
|
||||
if (err) {
|
||||
|
|
@ -1623,7 +1575,6 @@ mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
|
|||
return 0;
|
||||
|
||||
err_detach_netdev:
|
||||
mlx5e_rep_vnic_reporter_destroy(priv);
|
||||
mlx5e_detach_netdev(netdev_priv(netdev));
|
||||
err_cleanup_profile:
|
||||
priv->profile->cleanup(priv);
|
||||
|
|
@ -1681,7 +1632,6 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
|
|||
}
|
||||
|
||||
unregister_netdev(netdev);
|
||||
mlx5e_rep_vnic_reporter_destroy(priv);
|
||||
mlx5e_detach_netdev(priv);
|
||||
priv->profile->cleanup(priv);
|
||||
mlx5e_destroy_netdev(netdev);
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ struct mlx5e_rep_priv {
|
|||
struct rtnl_link_stats64 prev_vf_vport_stats;
|
||||
struct mlx5_flow_handle *send_to_vport_meta_rule;
|
||||
struct rhashtable tc_ht;
|
||||
struct devlink_health_reporter *rep_vnic_reporter;
|
||||
};
|
||||
|
||||
static inline
|
||||
|
|
|
|||
|
|
@ -1199,50 +1199,39 @@ void mlx5e_stats_rmon_get(struct mlx5e_priv *priv,
|
|||
void mlx5e_stats_ts_get(struct mlx5e_priv *priv,
|
||||
struct ethtool_ts_stats *ts_stats)
|
||||
{
|
||||
int i, j;
|
||||
u16 nch = mlx5e_stats_nch_read(priv);
|
||||
int i, tc;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
ts_stats->pkts = 0;
|
||||
|
||||
for (i = 0; i < nch; i++) {
|
||||
struct mlx5e_channel_stats *channel_stats =
|
||||
priv->channel_stats[i];
|
||||
|
||||
for (tc = 0; tc < priv->max_opened_tc; tc++)
|
||||
ts_stats->pkts += channel_stats->sq[tc].timestamps;
|
||||
}
|
||||
|
||||
/* Accumulate DMA and port timestamp counters so values stay monotonic
|
||||
* across channel teardown and mode switches.
|
||||
*/
|
||||
if (priv->tx_ptp_opened) {
|
||||
struct mlx5e_ptp *ptp = priv->channels.ptp;
|
||||
|
||||
ts_stats->pkts = 0;
|
||||
/* Err and Lost stats are only relevant for port timestamping,
|
||||
* as the DMA layer will always successfully timestamp packets.
|
||||
*/
|
||||
ts_stats->err = 0;
|
||||
ts_stats->lost = 0;
|
||||
|
||||
if (!ptp)
|
||||
goto out;
|
||||
|
||||
/* Aggregate stats across all TCs */
|
||||
for (i = 0; i < ptp->num_tc; i++) {
|
||||
for (tc = 0; tc < priv->max_opened_tc; tc++) {
|
||||
struct mlx5e_ptp_cq_stats *stats =
|
||||
ptp->ptpsq[i].cq_stats;
|
||||
&priv->ptp_stats.cq[tc];
|
||||
|
||||
ts_stats->pkts += stats->cqe;
|
||||
ts_stats->err += stats->abort + stats->err_cqe +
|
||||
stats->late_cqe;
|
||||
stats->late_cqe;
|
||||
ts_stats->lost += stats->lost_cqe;
|
||||
}
|
||||
} else {
|
||||
/* DMA layer will always successfully timestamp packets. Other
|
||||
* counters do not make sense for this layer.
|
||||
*/
|
||||
ts_stats->pkts = 0;
|
||||
|
||||
/* Aggregate stats across all SQs */
|
||||
for (j = 0; j < priv->channels.num; j++) {
|
||||
struct mlx5e_channel *c = priv->channels.c[j];
|
||||
|
||||
for (i = 0; i < c->num_tc; i++) {
|
||||
struct mlx5e_sq_stats *stats = c->sq[i].stats;
|
||||
|
||||
ts_stats->pkts += stats->timestamps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->state_lock);
|
||||
}
|
||||
|
||||
#define PPORT_PHY_LAYER_OFF(c) \
|
||||
|
|
|
|||
|
|
@ -4,6 +4,26 @@
|
|||
#include <linux/mlx5/driver.h>
|
||||
#include "eswitch.h"
|
||||
#include "devlink.h"
|
||||
#include "diag/reporter_vnic.h"
|
||||
|
||||
static int
|
||||
mlx5_esw_rep_vnic_reporter_diagnose(struct devlink_health_reporter *reporter,
|
||||
struct devlink_fmsg *fmsg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_vport *vport = devlink_health_reporter_priv(reporter);
|
||||
|
||||
mlx5_reporter_vnic_diagnose_counters(vport->dev, fmsg, vport->vport,
|
||||
true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const
|
||||
struct devlink_health_reporter_ops mlx5_esw_rep_vnic_reporter_ops = {
|
||||
.name = "vnic",
|
||||
.diagnose = mlx5_esw_rep_vnic_reporter_diagnose,
|
||||
};
|
||||
|
||||
static void
|
||||
mlx5_esw_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_id *ppid)
|
||||
|
|
@ -220,6 +240,7 @@ static void mlx5_esw_devlink_port_res_unregister(struct devlink_port *dl_port)
|
|||
|
||||
int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
|
||||
{
|
||||
struct devlink_health_reporter *reporter;
|
||||
struct mlx5_core_dev *dev = esw->dev;
|
||||
const struct devlink_port_ops *ops;
|
||||
struct mlx5_devlink_port *dl_port;
|
||||
|
|
@ -255,6 +276,16 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, struct mlx
|
|||
mlx5_core_dbg(dev, "Failed to register port resources: %d\n",
|
||||
err);
|
||||
|
||||
reporter = devl_port_health_reporter_create(
|
||||
&dl_port->dl_port, &mlx5_esw_rep_vnic_reporter_ops,
|
||||
vport);
|
||||
if (IS_ERR(reporter))
|
||||
mlx5_core_err(dev,
|
||||
"Failed to create vnic health reporter for vport %d: %pe\n",
|
||||
vport_num, reporter);
|
||||
else
|
||||
dl_port->vnic_reporter = reporter;
|
||||
|
||||
return 0;
|
||||
|
||||
rate_err:
|
||||
|
|
@ -269,6 +300,12 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_vport *vport)
|
|||
if (!vport->dl_port)
|
||||
return;
|
||||
dl_port = vport->dl_port;
|
||||
|
||||
if (dl_port->vnic_reporter) {
|
||||
devl_health_reporter_destroy(dl_port->vnic_reporter);
|
||||
dl_port->vnic_reporter = NULL;
|
||||
}
|
||||
|
||||
mlx5_esw_devlink_port_res_unregister(&dl_port->dl_port);
|
||||
|
||||
devl_rate_leaf_destroy(&dl_port->dl_port);
|
||||
|
|
|
|||
|
|
@ -1040,13 +1040,19 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
|
|||
(vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled))
|
||||
esw->enabled_ipsec_vf_count--;
|
||||
|
||||
/* Clear rx-mode before esw_vport_change_handle_locked(): on
|
||||
* MLX5_VPORT_PROMISC_CHANGE it calls esw_update_vport_mc_promisc()
|
||||
* when vport->allmulti_rule is set, repopulating mc_list with FDB
|
||||
* rules that dangle once the FDB is destroyed. NULL allmulti_rule
|
||||
* here skips that path.
|
||||
*/
|
||||
esw_apply_vport_rx_mode(esw, vport, false, false);
|
||||
/* We don't assume VFs will cleanup after themselves.
|
||||
* Calling vport change handler while vport is disabled will cleanup
|
||||
* the vport resources.
|
||||
*/
|
||||
esw_vport_change_handle_locked(vport);
|
||||
vport->enabled_events = 0;
|
||||
esw_apply_vport_rx_mode(esw, vport, false, false);
|
||||
esw_vport_cleanup(esw, vport);
|
||||
esw->enabled_vports--;
|
||||
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ struct mlx5_vport;
|
|||
struct mlx5_devlink_port {
|
||||
struct devlink_port dl_port;
|
||||
struct mlx5_vport *vport;
|
||||
struct devlink_health_reporter *vnic_reporter;
|
||||
};
|
||||
|
||||
static inline void mlx5_devlink_port_init(struct mlx5_devlink_port *dl_port,
|
||||
|
|
|
|||
|
|
@ -163,12 +163,15 @@ void
|
|||
mlx5_eswitch_termtbl_put(struct mlx5_eswitch *esw,
|
||||
struct mlx5_termtbl_handle *tt)
|
||||
{
|
||||
bool last;
|
||||
|
||||
mutex_lock(&esw->offloads.termtbl_mutex);
|
||||
if (--tt->ref_count == 0)
|
||||
last = (--tt->ref_count == 0);
|
||||
if (last)
|
||||
hash_del(&tt->termtbl_hlist);
|
||||
mutex_unlock(&esw->offloads.termtbl_mutex);
|
||||
|
||||
if (!tt->ref_count) {
|
||||
if (last) {
|
||||
mlx5_del_flow_rules(tt->rule);
|
||||
mlx5_destroy_flow_table(tt->termtbl);
|
||||
kfree(tt);
|
||||
|
|
|
|||
|
|
@ -63,14 +63,15 @@ static int get_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags)
|
|||
return MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY;
|
||||
}
|
||||
|
||||
static u8 lag_active_port_bits(struct mlx5_lag *ldev)
|
||||
static u8 lag_active_port_bits(struct mlx5_lag *ldev,
|
||||
struct lag_tracker *tracker)
|
||||
{
|
||||
u8 enabled_ports[MLX5_MAX_PORTS] = {};
|
||||
u8 active_port = 0;
|
||||
int num_enabled;
|
||||
int idx;
|
||||
|
||||
mlx5_infer_tx_enabled(&ldev->tracker, ldev, enabled_ports,
|
||||
mlx5_infer_tx_enabled(tracker, ldev, enabled_ports,
|
||||
&num_enabled);
|
||||
for (idx = 0; idx < num_enabled; idx++)
|
||||
active_port |= BIT_MASK(enabled_ports[idx]);
|
||||
|
|
@ -79,7 +80,8 @@ static u8 lag_active_port_bits(struct mlx5_lag *ldev)
|
|||
}
|
||||
|
||||
static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, struct mlx5_lag *ldev,
|
||||
int mode, unsigned long flags)
|
||||
struct lag_tracker *tracker, int mode,
|
||||
unsigned long flags)
|
||||
{
|
||||
bool fdb_sel_mode = test_bit(MLX5_LAG_MODE_FLAG_FDB_SEL_MODE_NATIVE,
|
||||
&flags);
|
||||
|
|
@ -108,7 +110,7 @@ static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, struct mlx5_lag *ldev,
|
|||
break;
|
||||
|
||||
MLX5_SET(lagc, lag_ctx, active_port,
|
||||
lag_active_port_bits(mlx5_lag_dev(dev)));
|
||||
lag_active_port_bits(ldev, tracker));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -787,7 +789,8 @@ static int mlx5_cmd_modify_active_port(struct mlx5_core_dev *dev, u8 ports)
|
|||
return mlx5_cmd_exec_in(dev, modify_lag, in);
|
||||
}
|
||||
|
||||
static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
|
||||
static int _mlx5_modify_lag(struct mlx5_lag *ldev,
|
||||
struct lag_tracker *tracker, u8 *ports)
|
||||
{
|
||||
int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
|
||||
struct mlx5_core_dev *dev0;
|
||||
|
|
@ -804,7 +807,7 @@ static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
|
|||
!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table_bypass))
|
||||
return ret;
|
||||
|
||||
active_ports = lag_active_port_bits(ldev);
|
||||
active_ports = lag_active_port_bits(ldev, tracker);
|
||||
|
||||
return mlx5_cmd_modify_active_port(dev0, active_ports);
|
||||
}
|
||||
|
|
@ -868,7 +871,7 @@ void mlx5_modify_lag(struct mlx5_lag *ldev,
|
|||
idx = i * ldev->buckets + j;
|
||||
if (ports[idx] == ldev->v2p_map[idx])
|
||||
continue;
|
||||
err = _mlx5_modify_lag(ldev, ports);
|
||||
err = _mlx5_modify_lag(ldev, tracker, ports);
|
||||
if (err) {
|
||||
mlx5_core_err(dev0,
|
||||
"Failed to modify LAG (%d)\n",
|
||||
|
|
@ -976,7 +979,7 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
|
|||
mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n",
|
||||
shared_fdb, mlx5_get_str_port_sel_mode(mode, flags));
|
||||
|
||||
err = mlx5_cmd_create_lag(dev0, ldev, mode, flags);
|
||||
err = mlx5_cmd_create_lag(dev0, ldev, tracker, mode, flags);
|
||||
if (err) {
|
||||
mlx5_core_err(dev0,
|
||||
"Failed to create LAG (%d)\n",
|
||||
|
|
|
|||
|
|
@ -572,6 +572,38 @@ mlxsw_sp1_ptp_unmatched_remove(struct mlxsw_sp *mlxsw_sp,
|
|||
mlxsw_sp1_ptp_unmatched_ht_params);
|
||||
}
|
||||
|
||||
/* mlxsw_sp1_ptp_packet_finish() is reached both from the NAPI poll context
|
||||
* (mlxsw_sp1_ptp_got_packet(), mlxsw_sp1_ptp_got_piece() and
|
||||
* mlxsw_sp1_packet_timestamp()) and from process context, by way of the GC
|
||||
* workqueue (mlxsw_sp1_ptp_ht_gc_collect() ->
|
||||
* mlxsw_sp1_ptp_unmatched_finish()).
|
||||
*
|
||||
* mlxsw_sp_rx_listener_no_mark_func() ends in napi_gro_receive(), using the
|
||||
* NAPI pointer that was placed in the SKB control block when the trapped
|
||||
* packet was received in the NAPI context. That pointer may only be used
|
||||
* from its own poll context, which this call site cannot guarantee.
|
||||
*
|
||||
* netif_receive_skb(), unlike napi_gro_receive(), can be called from outside
|
||||
* of the NAPI instance's poll context. RX stats accounting and the skb->dev
|
||||
* assignment are still preserved; the only change is the delivery call.
|
||||
*/
|
||||
static void mlxsw_sp1_ptp_rx_finish(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
|
||||
|
||||
skb->dev = mlxsw_sp_port->dev;
|
||||
|
||||
pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
|
||||
u64_stats_update_begin(&pcpu_stats->syncp);
|
||||
pcpu_stats->rx_packets++;
|
||||
pcpu_stats->rx_bytes += skb->len;
|
||||
u64_stats_update_end(&pcpu_stats->syncp);
|
||||
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
netif_receive_skb(skb);
|
||||
}
|
||||
|
||||
/* This function is called in the following scenarios:
|
||||
*
|
||||
* 1) When a packet is matched with its timestamp.
|
||||
|
|
@ -600,7 +632,7 @@ static void mlxsw_sp1_ptp_packet_finish(struct mlxsw_sp *mlxsw_sp,
|
|||
if (ingress) {
|
||||
if (hwtstamps)
|
||||
*skb_hwtstamps(skb) = *hwtstamps;
|
||||
mlxsw_sp_rx_listener_no_mark_func(skb, local_port, mlxsw_sp);
|
||||
mlxsw_sp1_ptp_rx_finish(mlxsw_sp_port, skb);
|
||||
} else {
|
||||
/* skb_tstamp_tx() allows hwtstamps to be NULL. */
|
||||
skb_tstamp_tx(skb, hwtstamps);
|
||||
|
|
|
|||
|
|
@ -143,9 +143,6 @@ static int ks8851_write_mac_addr(struct net_device *dev)
|
|||
ks8851_wrreg16(ks, KS_MAR(i), val);
|
||||
}
|
||||
|
||||
if (!netif_running(dev))
|
||||
ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
|
||||
|
||||
ks8851_unlock(ks);
|
||||
|
||||
return 0;
|
||||
|
|
@ -478,8 +475,7 @@ static int ks8851_net_open(struct net_device *dev)
|
|||
* @dev: The device being closed.
|
||||
*
|
||||
* Called to close down a network device which has been active. Cancel any
|
||||
* work, shutdown the RX and TX process and then place the chip into a low
|
||||
* power state whilst it is not being used.
|
||||
* work and shutdown the RX and TX process.
|
||||
*/
|
||||
static int ks8851_net_stop(struct net_device *dev)
|
||||
{
|
||||
|
|
@ -506,8 +502,6 @@ static int ks8851_net_stop(struct net_device *dev)
|
|||
/* shutdown TX process */
|
||||
ks8851_wrreg16(ks, KS_TXCR, 0x0000);
|
||||
|
||||
/* set powermode to soft power down to save power */
|
||||
ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
|
||||
ks8851_unlock(ks);
|
||||
|
||||
/* ensure any queued tx buffers are dumped */
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog,
|
|||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"XDP: Insufficient memory for tx/rx re-config");
|
||||
apc->bpf_prog = old_prog;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2986,6 +2986,10 @@ static int mana_alloc_rx_wqe(struct mana_port_context *apc,
|
|||
*cq_size += COMP_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
/* Reserve an extra slot for Fence completion
|
||||
* event (CQE_RX_OBJECT_FENCE) in case RX CQ is full.
|
||||
*/
|
||||
*cq_size += COMP_ENTRY_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3080,7 +3084,7 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
|
|||
goto out;
|
||||
|
||||
rq_size = MANA_PAGE_ALIGN(rq_size);
|
||||
cq_size = MANA_PAGE_ALIGN(cq_size);
|
||||
cq_size = MANA_PAGE_ALIGN(roundup_pow_of_two(cq_size));
|
||||
|
||||
/* Create RQ */
|
||||
memset(&spec, 0, sizeof(spec));
|
||||
|
|
@ -3983,7 +3987,8 @@ static void mana_rdma_service_handle(struct work_struct *work)
|
|||
struct device *dev = gd->gdma_context->dev;
|
||||
int ret;
|
||||
|
||||
if (READ_ONCE(gd->rdma_teardown))
|
||||
/* Pairs with the smp_store_release() in mana_rdma_probe(). */
|
||||
if (smp_load_acquire(&gd->rdma_teardown))
|
||||
goto out;
|
||||
|
||||
switch (serv_work->event) {
|
||||
|
|
@ -4279,6 +4284,21 @@ int mana_rdma_probe(struct gdma_dev *gd)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* Clear the state left by a previous mana_rdma_remove() so servicing
|
||||
* events are handled again after a reset cycle.
|
||||
*/
|
||||
gd->is_suspended = false;
|
||||
|
||||
/* Publish is_suspended before re-opening the gate, so the handler
|
||||
* cannot observe an open gate with a stale is_suspended. Pairs
|
||||
* with the smp_load_acquire() in mana_rdma_service_handle(). This
|
||||
* matters on the reset path, where mana_rdma_remove() closed the
|
||||
* gate and drained the workqueue; on the initial probe path the
|
||||
* gate was never closed and both flags are already clear. It does
|
||||
* not order gd->adev, which add_adev() publishes below.
|
||||
*/
|
||||
smp_store_release(&gd->rdma_teardown, false);
|
||||
|
||||
err = add_adev(gd, "rdma");
|
||||
if (err)
|
||||
mana_gd_deregister_device(gd);
|
||||
|
|
|
|||
|
|
@ -1421,7 +1421,8 @@ static int nfp_net_get_fs_rule(struct nfp_net *nn, struct ethtool_rxnfc *cmd)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int nfp_net_get_fs_loc(struct nfp_net *nn, u32 *rule_locs)
|
||||
static int nfp_net_get_fs_loc(struct nfp_net *nn, struct ethtool_rxnfc *cmd,
|
||||
u32 *rule_locs)
|
||||
{
|
||||
struct nfp_fs_entry *entry;
|
||||
u32 count = 0;
|
||||
|
|
@ -1429,8 +1430,12 @@ static int nfp_net_get_fs_loc(struct nfp_net *nn, u32 *rule_locs)
|
|||
if (!(nn->cap_w1 & NFP_NET_CFG_CTRL_FLOW_STEER))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
list_for_each_entry(entry, &nn->fs.list, node)
|
||||
list_for_each_entry(entry, &nn->fs.list, node) {
|
||||
if (count == cmd->rule_cnt)
|
||||
return -EMSGSIZE;
|
||||
rule_locs[count++] = entry->loc;
|
||||
}
|
||||
cmd->rule_cnt = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1455,7 +1460,7 @@ static int nfp_net_get_rxnfc(struct net_device *netdev,
|
|||
return nfp_net_get_fs_rule(nn, cmd);
|
||||
case ETHTOOL_GRXCLSRLALL:
|
||||
cmd->data = NFP_FS_MAX_ENTRY;
|
||||
return nfp_net_get_fs_loc(nn, rule_locs);
|
||||
return nfp_net_get_fs_loc(nn, cmd, rule_locs);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
|
@ -1698,8 +1703,14 @@ static int nfp_net_fs_add(struct nfp_net *nn, struct ethtool_rxnfc *cmd)
|
|||
|
||||
nn->fs.count--;
|
||||
err = nfp_net_fs_add_hw(nn, new);
|
||||
if (err)
|
||||
if (err) {
|
||||
/* mbox broken, adding the old rule back will
|
||||
* likely also fail.
|
||||
*/
|
||||
list_del(&entry->node);
|
||||
kfree(entry);
|
||||
goto err;
|
||||
}
|
||||
|
||||
nn->fs.count++;
|
||||
list_replace(&entry->node, &new->node);
|
||||
|
|
|
|||
|
|
@ -1672,15 +1672,22 @@ static int ionic_tx(struct net_device *netdev, struct ionic_queue *q,
|
|||
stats->pkts++;
|
||||
stats->bytes += skb->len;
|
||||
|
||||
ionic_txq_post(q, false);
|
||||
|
||||
if (likely(!ionic_txq_hwstamp_enabled(q))) {
|
||||
struct netdev_queue *ndq = q_to_ndq(netdev, q);
|
||||
|
||||
if (unlikely(!ionic_q_has_space(q, MAX_SKB_FRAGS + 1)))
|
||||
netif_tx_stop_queue(ndq);
|
||||
netif_txq_maybe_stop(ndq, ionic_q_space_avail(q),
|
||||
MAX_SKB_FRAGS + 1, MAX_SKB_FRAGS + 1);
|
||||
ring_dbell = __netdev_tx_sent_queue(ndq, skb->len,
|
||||
netdev_xmit_more());
|
||||
}
|
||||
ionic_txq_post(q, ring_dbell);
|
||||
|
||||
if (ring_dbell) {
|
||||
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
|
||||
q->dbval | q->head_idx);
|
||||
q->dbell_jiffies = jiffies;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4454,6 +4454,26 @@ static bool stmmac_tso_valid_packet(struct sk_buff *skb)
|
|||
header_len + gso_size < 16383;
|
||||
}
|
||||
|
||||
static int stmmac_tso_get_num_desc(struct stmmac_tx_queue *tx_q,
|
||||
struct sk_buff *skb, u32 pay_len)
|
||||
{
|
||||
int i, ndesc = 1;
|
||||
|
||||
/* head payload */
|
||||
ndesc += DIV_ROUND_UP(pay_len, TSO_MAX_BUFF_SIZE);
|
||||
/* frag payload */
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
||||
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
||||
|
||||
ndesc += DIV_ROUND_UP(skb_frag_size(frag),
|
||||
TSO_MAX_BUFF_SIZE);
|
||||
}
|
||||
/* MSS update requires a new descriptor */
|
||||
ndesc += !!(skb_shinfo(skb)->gso_size != tx_q->mss);
|
||||
|
||||
return ndesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_tso_xmit - Tx entry point of the driver for oversized frames (TSO)
|
||||
* @skb : the socket buffer
|
||||
|
|
@ -4497,10 +4517,10 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
unsigned int first_entry, entry, tx_packets;
|
||||
struct stmmac_txq_stats *txq_stats;
|
||||
int i, first_tx, nfrags, ndesc;
|
||||
struct stmmac_tx_queue *tx_q;
|
||||
bool set_ic, is_last_segment;
|
||||
u32 pay_len, mss, queue;
|
||||
int i, first_tx, nfrags;
|
||||
u8 proto_hdr_len, hdr;
|
||||
dma_addr_t des;
|
||||
|
||||
|
|
@ -4513,14 +4533,15 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
|
||||
/* Compute header lengths */
|
||||
proto_hdr_len = stmmac_tso_header_size(skb);
|
||||
pay_len = skb_headlen(skb) - proto_hdr_len; /* no frags */
|
||||
|
||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
|
||||
hdr = sizeof(struct udphdr);
|
||||
else
|
||||
hdr = tcp_hdrlen(skb);
|
||||
|
||||
/* Desc availability based on threshold should be enough safe */
|
||||
if (unlikely(stmmac_tx_avail(priv, queue) <
|
||||
(((skb->len - proto_hdr_len) / TSO_MAX_BUFF_SIZE + 1)))) {
|
||||
ndesc = stmmac_tso_get_num_desc(tx_q, skb, pay_len);
|
||||
if (unlikely(stmmac_tx_avail(priv, queue) < ndesc)) {
|
||||
if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, queue))) {
|
||||
netif_tx_stop_queue(netdev_get_tx_queue(priv->dev,
|
||||
queue));
|
||||
|
|
@ -4532,8 +4553,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
pay_len = skb_headlen(skb) - proto_hdr_len; /* no frags */
|
||||
|
||||
mss = skb_shinfo(skb)->gso_size;
|
||||
|
||||
/* set new MSS value if needed */
|
||||
|
|
@ -8025,6 +8044,7 @@ static int __stmmac_dvr_probe(struct device *device,
|
|||
stmmac_napi_add(ndev);
|
||||
|
||||
mutex_init(&priv->lock);
|
||||
rwlock_init(&priv->ptp_lock);
|
||||
|
||||
stmmac_fpe_init(priv);
|
||||
|
||||
|
|
|
|||
|
|
@ -365,7 +365,6 @@ void stmmac_ptp_register(struct stmmac_priv *priv)
|
|||
if (priv->plat->crosststamp)
|
||||
priv->ptp_clock_ops.getcrosststamp = stmmac_getcrosststamp;
|
||||
|
||||
rwlock_init(&priv->ptp_lock);
|
||||
mutex_init(&priv->aux_ts_lock);
|
||||
|
||||
priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
|
||||
|
|
|
|||
|
|
@ -1156,11 +1156,10 @@ static void cc2520_remove(struct spi_device *spi)
|
|||
{
|
||||
struct cc2520_private *priv = spi_get_drvdata(spi);
|
||||
|
||||
mutex_destroy(&priv->buffer_mutex);
|
||||
flush_work(&priv->fifop_irqwork);
|
||||
|
||||
disable_work_sync(&priv->fifop_irqwork);
|
||||
ieee802154_unregister_hw(priv->hw);
|
||||
ieee802154_free_hw(priv->hw);
|
||||
mutex_destroy(&priv->buffer_mutex);
|
||||
}
|
||||
|
||||
static const struct spi_device_id cc2520_ids[] = {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ struct hwsim_phy {
|
|||
struct ieee802154_hw *hw;
|
||||
u32 idx;
|
||||
|
||||
/* Serializes phy->pib_updates. */
|
||||
spinlock_t pib_lock;
|
||||
struct hwsim_pib __rcu *pib;
|
||||
|
||||
bool suspended;
|
||||
|
|
@ -102,8 +104,6 @@ static int hwsim_update_pib(struct ieee802154_hw *hw, u8 page, u8 channel,
|
|||
if (!pib)
|
||||
return -ENOMEM;
|
||||
|
||||
pib_old = rtnl_dereference(phy->pib);
|
||||
|
||||
pib->page = page;
|
||||
pib->channel = channel;
|
||||
pib->filt.short_addr = filt->short_addr;
|
||||
|
|
@ -112,7 +112,10 @@ static int hwsim_update_pib(struct ieee802154_hw *hw, u8 page, u8 channel,
|
|||
pib->filt.pan_coord = filt->pan_coord;
|
||||
pib->filt_level = filt_level;
|
||||
|
||||
rcu_assign_pointer(phy->pib, pib);
|
||||
spin_lock_bh(&phy->pib_lock);
|
||||
pib_old = rcu_replace_pointer(phy->pib, pib,
|
||||
lockdep_is_held(&phy->pib_lock));
|
||||
spin_unlock_bh(&phy->pib_lock);
|
||||
kfree_rcu(pib_old, rcu);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -952,6 +955,7 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
|
|||
goto err_pib;
|
||||
}
|
||||
|
||||
spin_lock_init(&phy->pib_lock);
|
||||
pib->channel = 13;
|
||||
pib->filt.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
|
||||
pib->filt.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@ __must_hold(&busdevs_lock)
|
|||
static int mctp_i3c_probe(struct i3c_device *i3c)
|
||||
{
|
||||
struct mctp_i3c_bus *b = NULL, *mbus = NULL;
|
||||
int rc;
|
||||
|
||||
/* Look for a known bus */
|
||||
mutex_lock(&busdevs_lock);
|
||||
|
|
@ -296,14 +297,16 @@ static int mctp_i3c_probe(struct i3c_device *i3c)
|
|||
mbus = b;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&busdevs_lock);
|
||||
|
||||
if (!mbus) {
|
||||
/* probably no "mctp-controller" property on the i3c bus */
|
||||
return -ENODEV;
|
||||
rc = -ENODEV;
|
||||
} else {
|
||||
rc = mctp_i3c_add_device(mbus, i3c);
|
||||
}
|
||||
mutex_unlock(&busdevs_lock);
|
||||
|
||||
return mctp_i3c_add_device(mbus, i3c);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void mctp_i3c_remove_device(struct mctp_i3c_device *mi)
|
||||
|
|
|
|||
|
|
@ -675,7 +675,7 @@ static int net_failover_slave_name_change(struct net_device *slave_dev,
|
|||
/* We need to bring up the slave after the rename by udev in case
|
||||
* open failed with EBUSY when it was registered.
|
||||
*/
|
||||
dev_open(slave_dev, NULL);
|
||||
netif_open(slave_dev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1150,6 +1150,9 @@ static int dp83867_led_polarity_set(struct phy_device *phydev, int index,
|
|||
case PHY_LED_ACTIVE_LOW:
|
||||
polarity = 0;
|
||||
break;
|
||||
case PHY_LED_ACTIVE_HIGH:
|
||||
polarity = DP83867_LED_POLARITY(index);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -439,6 +439,9 @@ static int dp83td510_led_polarity_set(struct phy_device *phydev, int index,
|
|||
case PHY_LED_ACTIVE_LOW:
|
||||
polarity = 0;
|
||||
break;
|
||||
case PHY_LED_ACTIVE_HIGH:
|
||||
polarity = DP83TD510E_LED_POLARITY(index);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,10 +62,38 @@ static void mtk_gephy_config_init(struct phy_device *phydev)
|
|||
FIELD_PREP(MTK_MCC_NEARECHO_OFFSET_MASK, 0x3));
|
||||
}
|
||||
|
||||
static int mt7530_phy_probe(struct phy_device *phydev)
|
||||
{
|
||||
/* The MT7530 internal GE PHY has broken EEE: with EEE advertised,
|
||||
* some link partners fail to establish a stable link (on a 2-pair
|
||||
* cable, 1000BASE-T training fails and the port loops instead of
|
||||
* falling back). MediaTek recommends disabling EEE on this PHY.
|
||||
* Clear the advertisement as early as possible, before anything
|
||||
* can negotiate EEE with the link partner.
|
||||
*/
|
||||
return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
|
||||
}
|
||||
|
||||
static int mt7530_phy_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mtk_gephy_config_init(phydev);
|
||||
|
||||
/* The probe() clear alone is not durable: phy_init_hw() replays only
|
||||
* ->config_init after a PHY reset, with the register back at its
|
||||
* EEE-advertising hardware default, and phy_probe() zeroes
|
||||
* eee_disabled_modes (of_set_phy_eee_broken()) after ->probe already
|
||||
* ran. Clear the advertisement again and mark EEE disabled, so that
|
||||
* neither phylib nor userspace can re-enable it; dp83867 disables
|
||||
* broken EEE from config_init() the same way.
|
||||
*/
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
phy_disable_eee(phydev);
|
||||
|
||||
/* Increase post_update_timer */
|
||||
phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3,
|
||||
MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11, 0x4b);
|
||||
|
|
@ -100,6 +128,7 @@ static struct phy_driver mtk_gephy_driver[] = {
|
|||
{
|
||||
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
|
||||
.name = "MediaTek MT7530 PHY",
|
||||
.probe = mt7530_phy_probe,
|
||||
.config_init = mt7530_phy_config_init,
|
||||
/* Interrupts are handled by the switch, not the PHY
|
||||
* itself.
|
||||
|
|
|
|||
|
|
@ -1630,8 +1630,10 @@ static void phylink_resolve(struct work_struct *w)
|
|||
|
||||
if (pl->phylink_disable_state) {
|
||||
pl->link_failed = false;
|
||||
link_state = pl->link_config;
|
||||
link_state.link = false;
|
||||
} else if (pl->link_failed) {
|
||||
link_state = pl->link_config;
|
||||
link_state.link = false;
|
||||
retrigger = true;
|
||||
} else if (pl->act_link_an_mode == MLO_AN_FIXED) {
|
||||
|
|
|
|||
|
|
@ -742,11 +742,8 @@ process_input_packet(struct asyncppp *ap)
|
|||
err:
|
||||
/* frame had an error, remember that, reset SC_TOSS & SC_ESCAPE */
|
||||
ap->state = SC_PREV_ERROR;
|
||||
if (skb) {
|
||||
/* make skb appear as freshly allocated */
|
||||
skb_trim(skb, 0);
|
||||
skb_reserve(skb, - skb_headroom(skb));
|
||||
}
|
||||
kfree_skb(skb);
|
||||
ap->rpkt = NULL;
|
||||
}
|
||||
|
||||
/* Called when the tty driver has data for us. Runs parallel with the
|
||||
|
|
|
|||
|
|
@ -455,17 +455,9 @@ ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb)
|
|||
|
||||
/* prepend address/control fields if necessary */
|
||||
if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
|
||||
if (skb_headroom(skb) < 2) {
|
||||
struct sk_buff *npkt = dev_alloc_skb(skb->len + 2);
|
||||
if (npkt == NULL) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
skb_reserve(npkt,2);
|
||||
skb_copy_from_linear_data(skb,
|
||||
skb_put(npkt, skb->len), skb->len);
|
||||
consume_skb(skb);
|
||||
skb = npkt;
|
||||
if (skb_cow_head(skb, 2)) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
skb_push(skb,2);
|
||||
skb->data[0] = PPP_ALLSTATIONS;
|
||||
|
|
|
|||
|
|
@ -282,6 +282,7 @@ static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
|||
if (len == 0xffff) {
|
||||
netdev_info(dev->net, "router was rebooted, re-enabling ethernet mode");
|
||||
schedule_work(&priv->reenable_work);
|
||||
return 0;
|
||||
} else if (len > CX82310_MTU) {
|
||||
netdev_err(dev->net, "RX packet too long: %d B\n", len);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1547,10 +1547,10 @@ hso_wait_modem_status(struct hso_serial *serial, unsigned long arg)
|
|||
spin_unlock_irq(&serial->serial_lock);
|
||||
add_wait_queue(&tiocmget->waitq, &wait);
|
||||
for (;;) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
spin_lock_irq(&serial->serial_lock);
|
||||
memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
|
||||
spin_unlock_irq(&serial->serial_lock);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
|
||||
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
|
||||
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd))) {
|
||||
|
|
|
|||
|
|
@ -1084,6 +1084,7 @@ static const struct usb_device_id products[] = {
|
|||
},
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0122)}, /* Quectel RG650V */
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x013d)}, /* Quectel RG660QB */
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */
|
||||
|
|
|
|||
|
|
@ -996,6 +996,12 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (rcu_access_pointer(f->nh) &&
|
||||
!(state & (NUD_PERMANENT | NUD_NOARP))) {
|
||||
NL_SET_ERR_MSG(extack, "Cannot make a nexthop fdb dynamic");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Do not allow an externally learned entry to take over an entry added
|
||||
* by the user.
|
||||
*/
|
||||
|
|
@ -1257,6 +1263,11 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
if (nhid && !(ndm->ndm_state & (NUD_PERMANENT | NUD_NOARP))) {
|
||||
NL_SET_ERR_MSG(extack, "A nexthop fdb cannot be dynamic");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
|
|
@ -2362,7 +2373,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|||
struct ip_tunnel_key key;
|
||||
struct vxlan_dev *vxlan = netdev_priv(dev);
|
||||
const struct iphdr *old_iph;
|
||||
struct vxlan_metadata _md;
|
||||
struct vxlan_metadata _md = {};
|
||||
struct vxlan_metadata *md = &_md;
|
||||
unsigned int pkt_len = skb->len;
|
||||
__be16 src_port = 0, dst_port;
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ static void ism_free_dmb(struct ism_dev *ism, struct dibs_dmb *dmb)
|
|||
dma_unmap_page(&ism->pdev->dev, dmb->dma_addr, dmb->dmb_len,
|
||||
DMA_FROM_DEVICE);
|
||||
folio_put(virt_to_folio(dmb->cpu_addr));
|
||||
dmb->cpu_addr = NULL;
|
||||
}
|
||||
|
||||
static int ism_alloc_dmb(struct ism_dev *ism, struct dibs_dmb *dmb)
|
||||
|
|
@ -274,7 +275,8 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct dibs_dmb *dmb)
|
|||
return 0;
|
||||
|
||||
out_free:
|
||||
kfree(dmb->cpu_addr);
|
||||
folio_put(folio);
|
||||
dmb->cpu_addr = NULL;
|
||||
out_bit:
|
||||
clear_bit(dmb->idx, ism->sba_bitmap);
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ extern const struct attribute_group *qeth_l2_attr_groups[];
|
|||
|
||||
int qeth_bridgeport_query_ports(struct qeth_card *card,
|
||||
enum qeth_sbp_roles *role,
|
||||
enum qeth_sbp_states *state);
|
||||
enum qeth_sbp_states *state,
|
||||
bool *os_mismatch);
|
||||
int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role);
|
||||
int qeth_bridgeport_an_set(struct qeth_card *card, int enable);
|
||||
|
||||
|
|
|
|||
|
|
@ -1158,7 +1158,7 @@ static void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
|
|||
qeth_bridgeport_setrole(card, card->options.sbp.role);
|
||||
/* Let the callback function refresh the stored role value. */
|
||||
qeth_bridgeport_query_ports(card, &card->options.sbp.role,
|
||||
NULL);
|
||||
NULL, NULL);
|
||||
}
|
||||
if (card->options.sbp.hostnotification) {
|
||||
if (qeth_bridgeport_an_set(card, 1))
|
||||
|
|
@ -1545,6 +1545,7 @@ struct _qeth_sbp_cbctl {
|
|||
struct {
|
||||
enum qeth_sbp_roles *role;
|
||||
enum qeth_sbp_states *state;
|
||||
bool *os_mismatch;
|
||||
} qports;
|
||||
} data;
|
||||
};
|
||||
|
|
@ -1721,10 +1722,19 @@ static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
|
|||
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
||||
struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
|
||||
struct qeth_sbp_port_data *qports;
|
||||
u16 sbp_rc;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "brqprtcb");
|
||||
rc = qeth_bridgeport_makerc(card, cmd);
|
||||
sbp_rc = cmd->data.sbp.hdr.return_code;
|
||||
|
||||
/* on OS family mismatch, query still returns valid port data;
|
||||
* treat as success
|
||||
*/
|
||||
if (sbp_rc == IPA_RC_SBP_IQD_OS_MISMATCH && !cmd->hdr.return_code)
|
||||
rc = 0;
|
||||
else
|
||||
rc = qeth_bridgeport_makerc(card, cmd);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -1740,6 +1750,9 @@ static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
|
|||
if (cbctl->data.qports.state)
|
||||
*cbctl->data.qports.state = qports->entry[0].state;
|
||||
}
|
||||
if (cbctl->data.qports.os_mismatch)
|
||||
*cbctl->data.qports.os_mismatch =
|
||||
(sbp_rc == IPA_RC_SBP_IQD_OS_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1748,13 +1761,17 @@ static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
|
|||
* @card: qeth_card structure pointer.
|
||||
* @role: Role of the port: 0-none, 1-primary, 2-secondary.
|
||||
* @state: State of the port: 0-inactive, 1-standby, 2-active.
|
||||
* @os_mismatch: if non-NULL, set to true when firmware reports
|
||||
* OS family mismatch.
|
||||
*
|
||||
* Returns negative errno-compatible error indication or 0 on success.
|
||||
*
|
||||
* 'role' and 'state' are not updated in case of hardware operation failure.
|
||||
* 'role', 'state' and 'os_mismatch' are not updated in case of
|
||||
* hardware operation failure.
|
||||
*/
|
||||
int qeth_bridgeport_query_ports(struct qeth_card *card,
|
||||
enum qeth_sbp_roles *role, enum qeth_sbp_states *state)
|
||||
enum qeth_sbp_roles *role, enum qeth_sbp_states *state,
|
||||
bool *os_mismatch)
|
||||
{
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct _qeth_sbp_cbctl cbctl = {
|
||||
|
|
@ -1762,6 +1779,7 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
|
|||
.qports = {
|
||||
.role = role,
|
||||
.state = state,
|
||||
.os_mismatch = os_mismatch,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
|
|||
{
|
||||
struct qeth_card *card = dev_get_drvdata(dev);
|
||||
enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE;
|
||||
bool os_mismatch = false;
|
||||
int rc = 0;
|
||||
char *word;
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
|
|||
if (qeth_card_hw_is_reachable(card) &&
|
||||
card->options.sbp.supported_funcs)
|
||||
rc = qeth_bridgeport_query_ports(card,
|
||||
&card->options.sbp.role, &state);
|
||||
&card->options.sbp.role, &state, &os_mismatch);
|
||||
if (!rc) {
|
||||
if (show_state)
|
||||
switch (state) {
|
||||
|
|
@ -52,6 +53,10 @@ static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
|
|||
if (rc)
|
||||
QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x",
|
||||
card->options.sbp.role, state);
|
||||
else if (!show_state &&
|
||||
card->options.sbp.role == QETH_SBP_ROLE_NONE &&
|
||||
os_mismatch)
|
||||
rc = sysfs_emit(buf, "%s (OS family mismatch)\n", word);
|
||||
else
|
||||
rc = sysfs_emit(buf, "%s\n", word);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1057,6 +1057,12 @@ struct kernel_ethtool_ts_info {
|
|||
* @get_sset_count: Get number of strings that @get_strings will write.
|
||||
* @get_rxnfc: Get RX flow classification rules. Returns a negative
|
||||
* error code or zero.
|
||||
* Note that for %ETHTOOL_GRXCLSRLALL rule_cnt and size of the arrays
|
||||
* is user-provided, and not guaranteed to match what driver would
|
||||
* have reported via %ETHTOOL_GRXCLSRLCNT. Drivers must return -%EMSGSIZE
|
||||
* when rule_cnt is too small. rule_locs is %NULL when rule_cnt is zero.
|
||||
* On success drivers must set rule_cnt to the number of locations they
|
||||
* filled in, the core copies out exactly that many.
|
||||
* @set_rxnfc: Set RX flow classification rules. Returns a negative
|
||||
* error code or zero.
|
||||
* @flash_device: Write a firmware image to device's flash memory.
|
||||
|
|
|
|||
|
|
@ -56,23 +56,4 @@ void arpt_unregister_table(struct net *net, const char *name);
|
|||
extern unsigned int arpt_do_table(void *priv, struct sk_buff *skb,
|
||||
const struct nf_hook_state *state);
|
||||
|
||||
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
|
||||
#include <net/compat.h>
|
||||
|
||||
struct compat_arpt_entry {
|
||||
struct arpt_arp arp;
|
||||
__u16 target_offset;
|
||||
__u16 next_offset;
|
||||
compat_uint_t comefrom;
|
||||
struct compat_xt_counters counters;
|
||||
unsigned char elems[];
|
||||
};
|
||||
|
||||
static inline struct xt_entry_target *
|
||||
compat_arpt_get_target(struct compat_arpt_entry *e)
|
||||
{
|
||||
return (void *)e + e->target_offset;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* _ARPTABLES_H */
|
||||
|
|
|
|||
|
|
@ -376,6 +376,7 @@ struct cfg802154_mac_pkt {
|
|||
struct list_head node;
|
||||
struct sk_buff *skb;
|
||||
struct ieee802154_sub_if_data *sdata;
|
||||
netdevice_tracker dev_tracker;
|
||||
u8 page;
|
||||
u8 channel;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -384,6 +384,8 @@ static inline unsigned int ip6_dst_mtu_maybe_forward(const struct dst_entry *dst
|
|||
rcu_read_unlock();
|
||||
|
||||
out:
|
||||
mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
|
||||
|
||||
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -793,7 +793,7 @@ void qdisc_offload_query_caps(struct net_device *dev,
|
|||
struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
|
||||
const struct Qdisc_ops *ops,
|
||||
struct netlink_ext_ack *extack);
|
||||
void qdisc_free(struct Qdisc *qdisc);
|
||||
void qdisc_free_rcu(struct Qdisc *qdisc);
|
||||
struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
|
||||
const struct Qdisc_ops *ops, u32 parentid,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* @__nhc: variable name of the lowpan_nhc struct.
|
||||
* @_name: const char * of common header compression name.
|
||||
* @_nexthdr: ipv6 nexthdr field for the header compression.
|
||||
* @_nexthdrlen: ipv6 nexthdr len for the reserved space.
|
||||
* @_hdrlen: ipv6 nexthdr len for the reserved space.
|
||||
* @_id: one byte nhc id value.
|
||||
* @_idmask: one byte nhc id mask value.
|
||||
* @_uncompress: callback for uncompression call.
|
||||
|
|
@ -102,7 +102,6 @@ int lowpan_nhc_do_compression(struct sk_buff *skb, const struct ipv6hdr *hdr,
|
|||
/**
|
||||
* lowpan_nhc_do_uncompression - calling uncompress callback for nhc
|
||||
*
|
||||
* @nhc: 6LoWPAN nhc context, get by lowpan_nhc_by_ functions.
|
||||
* @skb: skb of 6LoWPAN header, skb->data should be pointed to nhc id value.
|
||||
* @dev: netdevice for print logging information.
|
||||
* @hdr: ipv6hdr for setting nexthdr value.
|
||||
|
|
|
|||
|
|
@ -4797,6 +4797,24 @@ static int hci_le_set_def_rate_sync(struct hci_dev *hdev)
|
|||
cp.cont_num = cpu_to_le16(0x0001);
|
||||
cp.supv_timeout = cpu_to_le16(0x000c); /* 120 ms */
|
||||
|
||||
/* The connection event length recommended in requests by a Peripheral
|
||||
* uses units of 125 us with a valid range of 0x0001 to 0x7CFF
|
||||
* (0.125 ms to 3.999875 s), so 0x0000 cannot be used. Also note that
|
||||
* the Controller is not required to use these values:
|
||||
*
|
||||
* BLUETOOTH CORE SPECIFICATION Version 6.2 | Vol 4, Part E
|
||||
* 7.8.158. LE Set Default Rate Parameters command
|
||||
*
|
||||
* The Min_CE_Length and Max_CE_Length parameters provide the
|
||||
* Controller with the expected minimum and maximum length of the
|
||||
* connection events. The Controller is not required to use these
|
||||
* values.
|
||||
*
|
||||
* So it is safe to just use the minimum.
|
||||
*/
|
||||
cp.min_ce_len = cpu_to_le16(0x0001);
|
||||
cp.max_ce_len = cpu_to_le16(0x0001);
|
||||
|
||||
return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_DEF_RATE,
|
||||
sizeof(cp), &cp, HCI_CMD_TIMEOUT);
|
||||
}
|
||||
|
|
@ -7466,8 +7484,24 @@ static int hci_le_conn_rate_request_sync(struct hci_dev *hdev, void *data)
|
|||
cp.max_latency = cpu_to_le16(params->max_latency);
|
||||
cp.cont_num = cpu_to_le16(params->cont_num);
|
||||
cp.supv_timeout = cpu_to_le16(params->rate_supv_timeout);
|
||||
cp.min_ce_len = cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = cpu_to_le16(0x0000);
|
||||
|
||||
/* The connection event length recommended in requests by a Peripheral
|
||||
* uses units of 125 us with a valid range of 0x0001 to 0x7CFF
|
||||
* (0.125 ms to 3.999875 s), so 0x0000 cannot be used. Also note that
|
||||
* the Controller is not required to use these values:
|
||||
*
|
||||
* BLUETOOTH CORE SPECIFICATION Version 6.2 | Vol 4, Part E
|
||||
* 7.8.157. LE Connection Rate Request command
|
||||
*
|
||||
* The Min_CE_Length and Max_CE_Length parameters provide the
|
||||
* Controller with the expected minimum and maximum length of the
|
||||
* connection events. The Controller is not required to use these
|
||||
* values.
|
||||
*
|
||||
* So it is safe to just use the minimum.
|
||||
*/
|
||||
cp.min_ce_len = cpu_to_le16(0x0001);
|
||||
cp.max_ce_len = cpu_to_le16(0x0001);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@ static const struct class bt_class = {
|
|||
static void bt_link_release(struct device *dev)
|
||||
{
|
||||
struct hci_conn *conn = to_hci_conn(dev);
|
||||
struct device *parent = dev->parent;
|
||||
|
||||
kfree(conn);
|
||||
put_device(parent);
|
||||
}
|
||||
|
||||
static const struct device_type bt_link = {
|
||||
|
|
@ -21,6 +24,16 @@ static const struct device_type bt_link = {
|
|||
.release = bt_link_release,
|
||||
};
|
||||
|
||||
/*
|
||||
* The rfcomm tty device will possibly retain even when conn
|
||||
* is down, and sysfs doesn't support move zombie device,
|
||||
* so we should move the device before conn device is destroyed.
|
||||
*/
|
||||
static int __match_tty(struct device *dev, const void *data)
|
||||
{
|
||||
return !strncmp(dev_name(dev), "rfcomm", 6);
|
||||
}
|
||||
|
||||
void hci_conn_init_sysfs(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
|
|
@ -29,7 +42,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn)
|
|||
|
||||
conn->dev.type = &bt_link;
|
||||
conn->dev.class = &bt_class;
|
||||
conn->dev.parent = &hdev->dev;
|
||||
conn->dev.parent = get_device(&hdev->dev);
|
||||
|
||||
device_initialize(&conn->dev);
|
||||
}
|
||||
|
|
@ -69,7 +82,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
|
|||
while (1) {
|
||||
struct device *dev;
|
||||
|
||||
dev = device_find_any_child(&conn->dev);
|
||||
dev = device_find_child(&conn->dev, NULL, __match_tty);
|
||||
if (!dev)
|
||||
break;
|
||||
device_move(dev, NULL, DPM_ORDER_DEV_LAST);
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ static u32 ccm_tlv_extract(struct sk_buff *skb, u32 index,
|
|||
}
|
||||
|
||||
/* note: already called with rcu_read_lock */
|
||||
static int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)
|
||||
int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)
|
||||
{
|
||||
u32 mdlevel, interval, size, index, max;
|
||||
const struct br_cfm_common_hdr *hdr;
|
||||
|
|
@ -489,11 +489,6 @@ static int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct br_frame_type cfm_frame_type __read_mostly = {
|
||||
.type = cpu_to_be16(ETH_P_CFM),
|
||||
.frame_handler = br_cfm_frame_rx,
|
||||
};
|
||||
|
||||
int br_cfm_mep_create(struct net_bridge *br,
|
||||
const u32 instance,
|
||||
struct br_cfm_mep_create *const create,
|
||||
|
|
@ -559,7 +554,7 @@ int br_cfm_mep_create(struct net_bridge *br,
|
|||
INIT_DELAYED_WORK(&mep->ccm_tx_dwork, ccm_tx_work_expired);
|
||||
|
||||
if (hlist_empty(&br->mep_list))
|
||||
br_add_frame(br, &cfm_frame_type);
|
||||
br_opt_toggle(br, BROPT_CFM_ENABLED, true);
|
||||
|
||||
hlist_add_tail_rcu(&mep->head, &br->mep_list);
|
||||
|
||||
|
|
@ -588,7 +583,7 @@ static void mep_delete_implementation(struct net_bridge *br,
|
|||
kfree_rcu(mep, rcu);
|
||||
|
||||
if (hlist_empty(&br->mep_list))
|
||||
br_del_frame(br, &cfm_frame_type);
|
||||
br_opt_toggle(br, BROPT_CFM_ENABLED, false);
|
||||
}
|
||||
|
||||
int br_cfm_mep_delete(struct net_bridge *br,
|
||||
|
|
|
|||
|
|
@ -503,7 +503,6 @@ void br_dev_setup(struct net_device *dev)
|
|||
spin_lock_init(&br->lock);
|
||||
INIT_LIST_HEAD(&br->port_list);
|
||||
INIT_HLIST_HEAD(&br->fdb_list);
|
||||
INIT_HLIST_HEAD(&br->frame_type_list);
|
||||
#if IS_ENABLED(CONFIG_BRIDGE_MRP)
|
||||
INIT_HLIST_HEAD(&br->mrp_list);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -317,17 +317,25 @@ static int nf_hook_bridge_pre(struct sk_buff *skb, struct sk_buff **pskb)
|
|||
return RX_HANDLER_CONSUMED;
|
||||
}
|
||||
|
||||
#define BR_CFM_MRP_OPTS \
|
||||
((IS_ENABLED(CONFIG_BRIDGE_CFM) ? BIT(BROPT_CFM_ENABLED) : 0UL) | \
|
||||
(IS_ENABLED(CONFIG_BRIDGE_MRP) ? BIT(BROPT_MRP_ENABLED) : 0UL))
|
||||
|
||||
/* Return 0 if the frame was not processed otherwise 1
|
||||
* note: already called with rcu_read_lock
|
||||
*/
|
||||
static int br_process_frame_type(struct net_bridge_port *p,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct br_frame_type *tmp;
|
||||
struct net_bridge *br = p->br;
|
||||
|
||||
hlist_for_each_entry_rcu(tmp, &p->br->frame_type_list, list)
|
||||
if (unlikely(tmp->type == skb->protocol))
|
||||
return tmp->frame_handler(p, skb);
|
||||
if (skb->protocol == htons(ETH_P_CFM) &&
|
||||
br_opt_get(br, BROPT_CFM_ENABLED))
|
||||
return br_cfm_frame_rx(p, skb);
|
||||
|
||||
if (skb->protocol == htons(ETH_P_MRP) &&
|
||||
br_opt_get(br, BROPT_MRP_ENABLED))
|
||||
return br_mrp_process(p, skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -425,7 +433,8 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
|
|||
}
|
||||
}
|
||||
|
||||
if (unlikely(br_process_frame_type(p, skb)))
|
||||
if (unlikely((READ_ONCE(p->br->options) & BR_CFM_MRP_OPTS) &&
|
||||
br_process_frame_type(p, skb)))
|
||||
return RX_HANDLER_PASS;
|
||||
|
||||
forward:
|
||||
|
|
@ -467,19 +476,3 @@ rx_handler_func_t *br_get_rx_handler(const struct net_device *dev)
|
|||
|
||||
return br_handle_frame;
|
||||
}
|
||||
|
||||
void br_add_frame(struct net_bridge *br, struct br_frame_type *ft)
|
||||
{
|
||||
hlist_add_head_rcu(&ft->list, &br->frame_type_list);
|
||||
}
|
||||
|
||||
void br_del_frame(struct net_bridge *br, struct br_frame_type *ft)
|
||||
{
|
||||
struct br_frame_type *tmp;
|
||||
|
||||
hlist_for_each_entry(tmp, &br->frame_type_list, list)
|
||||
if (ft == tmp) {
|
||||
hlist_del_rcu(&ft->list);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,6 @@
|
|||
static const u8 mrp_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x1 };
|
||||
static const u8 mrp_in_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x3 };
|
||||
|
||||
static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb);
|
||||
|
||||
static struct br_frame_type mrp_frame_type __read_mostly = {
|
||||
.type = cpu_to_be16(ETH_P_MRP),
|
||||
.frame_handler = br_mrp_process,
|
||||
};
|
||||
|
||||
static bool br_mrp_is_ring_port(struct net_bridge_port *p_port,
|
||||
struct net_bridge_port *s_port,
|
||||
struct net_bridge_port *port)
|
||||
|
|
@ -486,7 +479,7 @@ static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp)
|
|||
kfree_rcu(mrp, rcu);
|
||||
|
||||
if (hlist_empty(&br->mrp_list))
|
||||
br_del_frame(br, &mrp_frame_type);
|
||||
br_opt_toggle(br, BROPT_MRP_ENABLED, false);
|
||||
}
|
||||
|
||||
/* Adds a new MRP instance.
|
||||
|
|
@ -536,7 +529,7 @@ int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance)
|
|||
rcu_assign_pointer(mrp->s_port, p);
|
||||
|
||||
if (hlist_empty(&br->mrp_list))
|
||||
br_add_frame(br, &mrp_frame_type);
|
||||
br_opt_toggle(br, BROPT_MRP_ENABLED, true);
|
||||
|
||||
INIT_DELAYED_WORK(&mrp->test_work, br_mrp_test_work_expired);
|
||||
INIT_DELAYED_WORK(&mrp->in_test_work, br_mrp_in_test_work_expired);
|
||||
|
|
@ -1241,7 +1234,7 @@ static int br_mrp_rcv(struct net_bridge_port *p,
|
|||
* normal forwarding.
|
||||
* note: already called with rcu_read_lock
|
||||
*/
|
||||
static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
|
||||
int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
|
||||
{
|
||||
/* If there is no MRP instance do normal forwarding */
|
||||
if (likely(!test_bit(BR_MRP_AWARE_BIT, &p->flags)))
|
||||
|
|
|
|||
|
|
@ -1441,16 +1441,17 @@ struct net_bridge_port_group *br_multicast_new_port_group(
|
|||
goto free_out;
|
||||
}
|
||||
|
||||
rcu_assign_pointer(p->next, next);
|
||||
timer_setup(&p->timer, br_multicast_port_group_expired, 0);
|
||||
timer_setup(&p->rexmit_timer, br_multicast_port_group_rexmit, 0);
|
||||
hlist_add_head(&p->mglist, &port->mglist);
|
||||
|
||||
if (src)
|
||||
memcpy(p->eth_addr, src, ETH_ALEN);
|
||||
else
|
||||
eth_broadcast_addr(p->eth_addr);
|
||||
|
||||
RCU_INIT_POINTER(p->next, next);
|
||||
hlist_add_head_rcu(&p->mglist, &port->mglist);
|
||||
|
||||
return p;
|
||||
|
||||
free_out:
|
||||
|
|
@ -1465,11 +1466,11 @@ void br_multicast_del_port_group(struct net_bridge_port_group *p)
|
|||
struct net_bridge_port *port = p->key.port;
|
||||
__u16 vid = p->key.addr.vid;
|
||||
|
||||
hlist_del_init(&p->mglist);
|
||||
hlist_del_init_rcu(&p->mglist);
|
||||
if (!br_multicast_is_star_g(&p->key.addr))
|
||||
rhashtable_remove_fast(&port->br->sg_port_tbl, &p->rhnode,
|
||||
br_sg_port_rht_params);
|
||||
kfree(p);
|
||||
kfree_rcu(p, rcu);
|
||||
br_multicast_port_ngroups_dec(port, vid);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -495,12 +495,13 @@ enum net_bridge_opts {
|
|||
BROPT_MST_ENABLED,
|
||||
BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION,
|
||||
BROPT_FDB_LOCAL_VLAN_0,
|
||||
BROPT_CFM_ENABLED,
|
||||
BROPT_MRP_ENABLED,
|
||||
};
|
||||
|
||||
struct net_bridge {
|
||||
spinlock_t lock;
|
||||
spinlock_t hash_lock;
|
||||
struct hlist_head frame_type_list;
|
||||
struct net_device *dev;
|
||||
unsigned long options;
|
||||
/* These fields are accessed on each packet */
|
||||
|
|
@ -932,16 +933,6 @@ int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev);
|
|||
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
|
||||
rx_handler_func_t *br_get_rx_handler(const struct net_device *dev);
|
||||
|
||||
struct br_frame_type {
|
||||
__be16 type;
|
||||
int (*frame_handler)(struct net_bridge_port *port,
|
||||
struct sk_buff *skb);
|
||||
struct hlist_node list;
|
||||
};
|
||||
|
||||
void br_add_frame(struct net_bridge *br, struct br_frame_type *ft);
|
||||
void br_del_frame(struct net_bridge *br, struct br_frame_type *ft);
|
||||
|
||||
static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
|
||||
{
|
||||
return rcu_dereference(dev->rx_handler) == br_get_rx_handler(dev);
|
||||
|
|
@ -2080,6 +2071,7 @@ int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
|
|||
bool br_mrp_enabled(struct net_bridge *br);
|
||||
void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p);
|
||||
int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br);
|
||||
int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb);
|
||||
#else
|
||||
static inline int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
|
||||
struct nlattr *attr, int cmd,
|
||||
|
|
@ -2103,6 +2095,11 @@ static inline int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* br_cfm.c */
|
||||
|
|
@ -2111,6 +2108,7 @@ int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
|
|||
struct nlattr *attr, int cmd, struct netlink_ext_ack *extack);
|
||||
bool br_cfm_created(struct net_bridge *br);
|
||||
void br_cfm_port_del(struct net_bridge *br, struct net_bridge_port *p);
|
||||
int br_cfm_frame_rx(struct net_bridge_port *port, struct sk_buff *skb);
|
||||
int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br);
|
||||
int br_cfm_status_fill_info(struct sk_buff *skb,
|
||||
struct net_bridge *br,
|
||||
|
|
@ -2135,6 +2133,12 @@ static inline void br_cfm_port_del(struct net_bridge *br,
|
|||
{
|
||||
}
|
||||
|
||||
static inline int br_cfm_frame_rx(struct net_bridge_port *port,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
|
|
|
|||
|
|
@ -9982,7 +9982,7 @@ int netif_change_tx_queue_len(struct net_device *dev, unsigned long new_len)
|
|||
unsigned int orig_len = dev->tx_queue_len;
|
||||
int res;
|
||||
|
||||
if (new_len != (unsigned int)new_len)
|
||||
if (new_len > S16_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
if (new_len != orig_len) {
|
||||
|
|
|
|||
|
|
@ -2287,6 +2287,11 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static const struct netlink_range_validation txqlen_range = {
|
||||
.min = 0,
|
||||
.max = S16_MAX,
|
||||
};
|
||||
|
||||
static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
|
||||
[IFLA_UNSPEC] = { .strict_start_type = IFLA_DPLL_PIN },
|
||||
[IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
|
||||
|
|
@ -2297,7 +2302,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
|
|||
[IFLA_LINK] = { .type = NLA_U32 },
|
||||
[IFLA_MASTER] = { .type = NLA_U32 },
|
||||
[IFLA_CARRIER] = { .type = NLA_U8 },
|
||||
[IFLA_TXQLEN] = { .type = NLA_U32 },
|
||||
[IFLA_TXQLEN] = NLA_POLICY_FULL_RANGE(NLA_U32, &txqlen_range),
|
||||
[IFLA_WEIGHT] = { .type = NLA_U32 },
|
||||
[IFLA_OPERSTATE] = { .type = NLA_U8 },
|
||||
[IFLA_LINKMODE] = { .type = NLA_U8 },
|
||||
|
|
|
|||
|
|
@ -6690,6 +6690,13 @@ int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len,
|
|||
}
|
||||
skb->protocol = next_proto;
|
||||
|
||||
/* The last label is gone, so the inner header recorded by
|
||||
* skb_mpls_push() no longer describes this packet. Drop it, or a
|
||||
* later push keeps the stale offset.
|
||||
*/
|
||||
if (!eth_p_mpls(next_proto))
|
||||
skb->inner_protocol = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(skb_mpls_pop);
|
||||
|
|
|
|||
|
|
@ -373,6 +373,7 @@ static const struct dsa_device_ops brcm_legacy_fcs_netdev_ops = {
|
|||
.xmit = brcm_leg_fcs_tag_xmit,
|
||||
.rcv = brcm_leg_tag_rcv,
|
||||
.needed_headroom = BRCM_LEG_TAG_LEN,
|
||||
.needed_tailroom = ETH_FCS_LEN,
|
||||
};
|
||||
|
||||
DSA_TAG_DRIVER(brcm_legacy_fcs_netdev_ops);
|
||||
|
|
|
|||
|
|
@ -149,9 +149,12 @@ static int hsr_portdev_setup(struct hsr_priv *hsr, struct net_device *dev,
|
|||
int res;
|
||||
|
||||
/* Don't use promiscuous mode for offload since L2 frame forward
|
||||
* happens at the offloaded hardware.
|
||||
* happens at the offloaded hardware. The interlink port never
|
||||
* gets forwarding offload (RedBox forwarding to/from it is done
|
||||
* by this driver), so it still needs promiscuous mode to receive
|
||||
* frames addressed to hsr_dev's MAC rather than its own.
|
||||
*/
|
||||
if (!port->hsr->fwd_offloaded) {
|
||||
if (!port->hsr->fwd_offloaded || port->type == HSR_PT_INTERLINK) {
|
||||
res = dev_set_promiscuity(dev, 1);
|
||||
if (res)
|
||||
return res;
|
||||
|
|
@ -176,7 +179,7 @@ static int hsr_portdev_setup(struct hsr_priv *hsr, struct net_device *dev,
|
|||
fail_rx_handler:
|
||||
netdev_upper_dev_unlink(dev, hsr_dev);
|
||||
fail_upper_dev_link:
|
||||
if (!port->hsr->fwd_offloaded)
|
||||
if (!port->hsr->fwd_offloaded || port->type == HSR_PT_INTERLINK)
|
||||
dev_set_promiscuity(dev, -1);
|
||||
|
||||
return res;
|
||||
|
|
@ -240,7 +243,7 @@ void hsr_del_port(struct hsr_port *port)
|
|||
netdev_update_features(master->dev);
|
||||
dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
|
||||
netdev_rx_handler_unregister(port->dev);
|
||||
if (!port->hsr->fwd_offloaded)
|
||||
if (!port->hsr->fwd_offloaded || port->type == HSR_PT_INTERLINK)
|
||||
dev_set_promiscuity(port->dev, -1);
|
||||
if (port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B)
|
||||
vlan_vids_del_by_dev(port->dev, master->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