mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 06:43:09 +00:00
Including fixes from bpf, wifi and bluetooth.
Current release - regressions: - wifi: mt76: mt7915: add back 160MHz channel width support for MT7915 - libbpf: revert poisoning of strlcpy, it broke uClibc-ng Current release - new code bugs: - bpf: improve the coverage of the "allow reads from uninit stack" feature to fix verification complexity problems - eth: am65-cpts: reset PPS genf adj settings on enable Previous releases - regressions: - wifi: mac80211: serialize ieee80211_handle_wake_tx_queue() - wifi: mt76: do not run mt76_unregister_device() on unregistered hw, fix null-deref - Bluetooth: btqcomsmd: fix command timeout after setting BD address - eth: igb: revert rtnl_lock() that causes a deadlock - dsa: mscc: ocelot: fix device specific statistics Previous releases - always broken: - xsk: add missing overflow check in xdp_umem_reg() - wifi: mac80211: - fix QoS on mesh interfaces - fix mesh path discovery based on unicast packets - Bluetooth: - ISO: fix timestamped HCI ISO data packet parsing - remove "Power-on" check from Mesh feature - usbnet: more fixes to drivers trusting packet length - wifi: iwlwifi: mvm: fix mvmtxq->stopped handling - Bluetooth: btintel: iterate only bluetooth device ACPI entries - eth: iavf: fix inverted Rx hash condition leading to disabled hash - eth: igc: fix the validation logic for taprio's gate list - dsa: tag_brcm: legacy: fix daisy-chained switches Misc: - bpf: adjust insufficient default bpf_jit_limit to account for growth of BPF use over the last 5 years - xdp: bpf_xdp_metadata() use EOPNOTSUPP as unique errno indicating no driver support Signed-off-by: Jakub Kicinski <kuba@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmQc4vkACgkQMUZtbf5S IruG/w//XixBtdFMHE0/fcGv77jTovlJNiDYeaa+KtyjvIseieYwOKW5F31r3xvl Mf/YhNEjAc++V8Zna/1UM5i/WOj1PJdHgSC+wMUGUXjMF+MfzL57nM83CllOpUB5 Z9YtUqGfolf2Vtx03wnV14qawmVnJWYKHn3AU11cueE5dUu6KNyBTCefQ7uzgcJN zMtHAxw96MRQIDxSfKvZsePk4FnQ4qoSOLkslji5iikcMnKePaqZaxQla2oTcEIR zue9V+ILmi62Y8mPcdT4ePpZQsjB39bpemh+9EL6l03/cjsjqmuiCw/d1+6g9kuy ZD5LgZzUOb6xalhSseiwJL+vj8x2gQhshEfoHQvgp7fzr6agta6sisRX611wtmJl hv4k2PMRqFrMv2S+8m8XC177bXIaGbiWh4vBFOWjf4u0lG55cGlzclbXWWQ80njy C5cE4V7qPRk8Cl/+uT10CLNQx6JmaX8kcddtFrYpu0PZHKx1WfUYKIpgkiiMPRKT njLkDQbFRa8Y3p7UX0wU1TbeuMzzLz+aTBrFEN864IJmbnUnWimeluQzD60WbkSx 6dciqq11LtvYDsR1HZ1pb7IoHYuDsDrO2Rx4zuqsB/SyfrGdRKJoKOnYvsk+AdCL N/e4wivie8s6b+G3yL6p+IdlpEaVo2ZiLINp7JSW8jhW1hRcZUI= =XBLi -----END PGP SIGNATURE----- Merge tag 'net-6.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Jakub Kicinski: "Including fixes from bpf, wifi and bluetooth. Current release - regressions: - wifi: mt76: mt7915: add back 160MHz channel width support for MT7915 - libbpf: revert poisoning of strlcpy, it broke uClibc-ng Current release - new code bugs: - bpf: improve the coverage of the "allow reads from uninit stack" feature to fix verification complexity problems - eth: am65-cpts: reset PPS genf adj settings on enable Previous releases - regressions: - wifi: mac80211: serialize ieee80211_handle_wake_tx_queue() - wifi: mt76: do not run mt76_unregister_device() on unregistered hw, fix null-deref - Bluetooth: btqcomsmd: fix command timeout after setting BD address - eth: igb: revert rtnl_lock() that causes a deadlock - dsa: mscc: ocelot: fix device specific statistics Previous releases - always broken: - xsk: add missing overflow check in xdp_umem_reg() - wifi: mac80211: - fix QoS on mesh interfaces - fix mesh path discovery based on unicast packets - Bluetooth: - ISO: fix timestamped HCI ISO data packet parsing - remove "Power-on" check from Mesh feature - usbnet: more fixes to drivers trusting packet length - wifi: iwlwifi: mvm: fix mvmtxq->stopped handling - Bluetooth: btintel: iterate only bluetooth device ACPI entries - eth: iavf: fix inverted Rx hash condition leading to disabled hash - eth: igc: fix the validation logic for taprio's gate list - dsa: tag_brcm: legacy: fix daisy-chained switches Misc: - bpf: adjust insufficient default bpf_jit_limit to account for growth of BPF use over the last 5 years - xdp: bpf_xdp_metadata() use EOPNOTSUPP as unique errno indicating no driver support" * tag 'net-6.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (84 commits) Bluetooth: HCI: Fix global-out-of-bounds Bluetooth: mgmt: Fix MGMT add advmon with RSSI command Bluetooth: btsdio: fix use after free bug in btsdio_remove due to unfinished work Bluetooth: L2CAP: Fix responding with wrong PDU type Bluetooth: btqcomsmd: Fix command timeout after setting BD address Bluetooth: btinel: Check ACPI handle for NULL before accessing net: mdio: thunder: Add missing fwnode_handle_put() net: dsa: mt7530: move setting ssc_delta to PHY_INTERFACE_MODE_TRGMII case net: dsa: mt7530: move lowering TRGMII driving to mt7530_setup() net: dsa: mt7530: move enabling disabling core clock to mt7530_pll_setup() net: asix: fix modprobe "sysfs: cannot create duplicate filename" gve: Cache link_speed value from device tools: ynl: Fix genlmsg header encoding formats net: enetc: fix aggregate RMON counters not showing the ranges Bluetooth: Remove "Power-on" check from Mesh feature Bluetooth: Fix race condition in hci_cmd_sync_clear Bluetooth: btintel: Iterate only bluetooth device ACPI entries Bluetooth: ISO: fix timestamped HCI ISO data packet parsing Bluetooth: btusb: Remove detection of ISO packets over bulk Bluetooth: hci_core: Detect if an ACL packet is in fact an ISO packet ...
This commit is contained in:
commit
608f1b1366
@ -23,10 +23,13 @@ metadata is supported, this set will grow:
|
||||
An XDP program can use these kfuncs to read the metadata into stack
|
||||
variables for its own consumption. Or, to pass the metadata on to other
|
||||
consumers, an XDP program can store it into the metadata area carried
|
||||
ahead of the packet.
|
||||
ahead of the packet. Not all packets will necessary have the requested
|
||||
metadata available in which case the driver returns ``-ENODATA``.
|
||||
|
||||
Not all kfuncs have to be implemented by the device driver; when not
|
||||
implemented, the default ones that return ``-EOPNOTSUPP`` will be used.
|
||||
implemented, the default ones that return ``-EOPNOTSUPP`` will be used
|
||||
to indicate the device driver have not implemented this kfunc.
|
||||
|
||||
|
||||
Within an XDP frame, the metadata layout (accessed via ``xdp_buff``) is
|
||||
as follows::
|
||||
|
@ -2909,6 +2909,7 @@ close_card_oam(struct idt77252_dev *card)
|
||||
|
||||
recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
|
||||
}
|
||||
kfree(vc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2952,6 +2953,15 @@ open_card_ubr0(struct idt77252_dev *card)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
close_card_ubr0(struct idt77252_dev *card)
|
||||
{
|
||||
struct vc_map *vc = card->vcs[0];
|
||||
|
||||
free_scq(card, vc->scq);
|
||||
kfree(vc);
|
||||
}
|
||||
|
||||
static int
|
||||
idt77252_dev_open(struct idt77252_dev *card)
|
||||
{
|
||||
@ -3001,6 +3011,7 @@ static void idt77252_dev_close(struct atm_dev *dev)
|
||||
struct idt77252_dev *card = dev->dev_data;
|
||||
u32 conf;
|
||||
|
||||
close_card_ubr0(card);
|
||||
close_card_oam(card);
|
||||
|
||||
conf = SAR_CFG_RXPTH | /* enable receive path */
|
||||
|
@ -26,7 +26,14 @@
|
||||
#define ECDSA_HEADER_LEN 320
|
||||
|
||||
#define BTINTEL_PPAG_NAME "PPAG"
|
||||
#define BTINTEL_PPAG_PREFIX "\\_SB_.PCI0.XHCI.RHUB"
|
||||
|
||||
/* structure to store the PPAG data read from ACPI table */
|
||||
struct btintel_ppag {
|
||||
u32 domain;
|
||||
u32 mode;
|
||||
acpi_status status;
|
||||
struct hci_dev *hdev;
|
||||
};
|
||||
|
||||
#define CMD_WRITE_BOOT_PARAMS 0xfc0e
|
||||
struct cmd_write_boot_params {
|
||||
@ -1295,17 +1302,16 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
|
||||
|
||||
status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status));
|
||||
bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
if (strncmp(BTINTEL_PPAG_PREFIX, string.pointer,
|
||||
strlen(BTINTEL_PPAG_PREFIX))) {
|
||||
len = strlen(string.pointer);
|
||||
if (len < strlen(BTINTEL_PPAG_NAME)) {
|
||||
kfree(string.pointer);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
len = strlen(string.pointer);
|
||||
if (strncmp((char *)string.pointer + len - 4, BTINTEL_PPAG_NAME, 4)) {
|
||||
kfree(string.pointer);
|
||||
return AE_OK;
|
||||
@ -1314,7 +1320,8 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
|
||||
|
||||
status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status));
|
||||
ppag->status = status;
|
||||
bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1323,8 +1330,9 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
|
||||
|
||||
if (p->type != ACPI_TYPE_PACKAGE || p->package.count != 2) {
|
||||
kfree(buffer.pointer);
|
||||
bt_dev_warn(hdev, "Invalid object type: %d or package count: %d",
|
||||
bt_dev_warn(hdev, "PPAG-BT: Invalid object type: %d or package count: %d",
|
||||
p->type, p->package.count);
|
||||
ppag->status = AE_ERROR;
|
||||
return AE_ERROR;
|
||||
}
|
||||
|
||||
@ -1335,6 +1343,7 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
|
||||
|
||||
ppag->domain = (u32)p->package.elements[0].integer.value;
|
||||
ppag->mode = (u32)p->package.elements[1].integer.value;
|
||||
ppag->status = AE_OK;
|
||||
kfree(buffer.pointer);
|
||||
return AE_CTRL_TERMINATE;
|
||||
}
|
||||
@ -2314,12 +2323,12 @@ error:
|
||||
|
||||
static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver)
|
||||
{
|
||||
acpi_status status;
|
||||
struct btintel_ppag ppag;
|
||||
struct sk_buff *skb;
|
||||
struct btintel_loc_aware_reg ppag_cmd;
|
||||
acpi_handle handle;
|
||||
|
||||
/* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */
|
||||
/* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */
|
||||
switch (ver->cnvr_top & 0xFFF) {
|
||||
case 0x504: /* Hrp2 */
|
||||
case 0x202: /* Jfp2 */
|
||||
@ -2327,29 +2336,35 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver
|
||||
return;
|
||||
}
|
||||
|
||||
handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev));
|
||||
if (!handle) {
|
||||
bt_dev_info(hdev, "No support for BT device in ACPI firmware");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&ppag, 0, sizeof(ppag));
|
||||
|
||||
ppag.hdev = hdev;
|
||||
status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, NULL,
|
||||
btintel_ppag_callback, &ppag, NULL);
|
||||
ppag.status = AE_NOT_FOUND;
|
||||
acpi_walk_namespace(ACPI_TYPE_PACKAGE, handle, 1, NULL,
|
||||
btintel_ppag_callback, &ppag, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
/* Do not log warning message if ACPI entry is not found */
|
||||
if (status == AE_NOT_FOUND)
|
||||
if (ACPI_FAILURE(ppag.status)) {
|
||||
if (ppag.status == AE_NOT_FOUND) {
|
||||
bt_dev_dbg(hdev, "PPAG-BT: ACPI entry not found");
|
||||
return;
|
||||
bt_dev_warn(hdev, "PPAG: ACPI Failure: %s", acpi_format_exception(status));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ppag.domain != 0x12) {
|
||||
bt_dev_warn(hdev, "PPAG-BT Domain disabled");
|
||||
bt_dev_warn(hdev, "PPAG-BT: domain is not bluetooth");
|
||||
return;
|
||||
}
|
||||
|
||||
/* PPAG mode, BIT0 = 0 Disabled, BIT0 = 1 Enabled */
|
||||
if (!(ppag.mode & BIT(0))) {
|
||||
bt_dev_dbg(hdev, "PPAG disabled");
|
||||
bt_dev_dbg(hdev, "PPAG-BT: disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -137,13 +137,6 @@ struct intel_offload_use_cases {
|
||||
__u8 preset[8];
|
||||
} __packed;
|
||||
|
||||
/* structure to store the PPAG data read from ACPI table */
|
||||
struct btintel_ppag {
|
||||
u32 domain;
|
||||
u32 mode;
|
||||
struct hci_dev *hdev;
|
||||
};
|
||||
|
||||
struct btintel_loc_aware_reg {
|
||||
__le32 mcc;
|
||||
__le32 sel;
|
||||
|
@ -122,6 +122,21 @@ static int btqcomsmd_setup(struct hci_dev *hdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btqcomsmd_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qca_set_bdaddr_rome(hdev, bdaddr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* The firmware stops responding for a while after setting the bdaddr,
|
||||
* causing timeouts for subsequent commands. Sleep a bit to avoid this.
|
||||
*/
|
||||
usleep_range(1000, 10000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btqcomsmd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct btqcomsmd *btq;
|
||||
@ -162,7 +177,7 @@ static int btqcomsmd_probe(struct platform_device *pdev)
|
||||
hdev->close = btqcomsmd_close;
|
||||
hdev->send = btqcomsmd_send;
|
||||
hdev->setup = btqcomsmd_setup;
|
||||
hdev->set_bdaddr = qca_set_bdaddr_rome;
|
||||
hdev->set_bdaddr = btqcomsmd_set_bdaddr;
|
||||
|
||||
ret = hci_register_dev(hdev);
|
||||
if (ret < 0)
|
||||
|
@ -354,6 +354,7 @@ static void btsdio_remove(struct sdio_func *func)
|
||||
|
||||
BT_DBG("func %p", func);
|
||||
|
||||
cancel_work_sync(&data->work);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
|
@ -1050,21 +1050,11 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
|
||||
hci_skb_expect(skb) -= len;
|
||||
|
||||
if (skb->len == HCI_ACL_HDR_SIZE) {
|
||||
__u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
|
||||
__le16 dlen = hci_acl_hdr(skb)->dlen;
|
||||
__u8 type;
|
||||
|
||||
/* Complete ACL header */
|
||||
hci_skb_expect(skb) = __le16_to_cpu(dlen);
|
||||
|
||||
/* Detect if ISO packet has been sent over bulk */
|
||||
if (hci_conn_num(data->hdev, ISO_LINK)) {
|
||||
type = hci_conn_lookup_type(data->hdev,
|
||||
hci_handle(handle));
|
||||
if (type == ISO_LINK)
|
||||
hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
|
||||
}
|
||||
|
||||
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
|
@ -263,7 +263,7 @@ static int b53_mmap_probe_of(struct platform_device *pdev,
|
||||
if (of_property_read_u32(of_port, "reg", ®))
|
||||
continue;
|
||||
|
||||
if (reg < B53_CPU_PORT)
|
||||
if (reg < B53_N_PORTS)
|
||||
pdata->enabled_ports |= BIT(reg);
|
||||
}
|
||||
|
||||
|
@ -396,6 +396,9 @@ mt7530_fdb_write(struct mt7530_priv *priv, u16 vid,
|
||||
/* Set up switch core clock for MT7530 */
|
||||
static void mt7530_pll_setup(struct mt7530_priv *priv)
|
||||
{
|
||||
/* Disable core clock */
|
||||
core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
|
||||
|
||||
/* Disable PLL */
|
||||
core_write(priv, CORE_GSWPLL_GRP1, 0);
|
||||
|
||||
@ -409,14 +412,19 @@ static void mt7530_pll_setup(struct mt7530_priv *priv)
|
||||
RG_GSWPLL_EN_PRE |
|
||||
RG_GSWPLL_POSDIV_200M(2) |
|
||||
RG_GSWPLL_FBKDIV_200M(32));
|
||||
|
||||
udelay(20);
|
||||
|
||||
/* Enable core clock */
|
||||
core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
|
||||
}
|
||||
|
||||
/* Setup TX circuit including relevant PAD and driving */
|
||||
/* Setup port 6 interface mode and TRGMII TX circuit */
|
||||
static int
|
||||
mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
u32 ncpo1, ssc_delta, trgint, i, xtal;
|
||||
u32 ncpo1, ssc_delta, trgint, xtal;
|
||||
|
||||
xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK;
|
||||
|
||||
@ -433,6 +441,10 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_TRGMII:
|
||||
trgint = 1;
|
||||
if (xtal == HWTRAP_XTAL_25MHZ)
|
||||
ssc_delta = 0x57;
|
||||
else
|
||||
ssc_delta = 0x87;
|
||||
if (priv->id == ID_MT7621) {
|
||||
/* PLL frequency: 150MHz: 1.2GBit */
|
||||
if (xtal == HWTRAP_XTAL_40MHZ)
|
||||
@ -452,23 +464,12 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (xtal == HWTRAP_XTAL_25MHZ)
|
||||
ssc_delta = 0x57;
|
||||
else
|
||||
ssc_delta = 0x87;
|
||||
|
||||
mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK,
|
||||
P6_INTF_MODE(trgint));
|
||||
|
||||
if (trgint) {
|
||||
/* Lower Tx Driving for TRGMII path */
|
||||
for (i = 0 ; i < NUM_TRGMII_CTRL ; i++)
|
||||
mt7530_write(priv, MT7530_TRGMII_TD_ODT(i),
|
||||
TD_DM_DRVP(8) | TD_DM_DRVN(8));
|
||||
|
||||
/* Disable MT7530 core and TRGMII Tx clocks */
|
||||
core_clear(priv, CORE_TRGMII_GSW_CLK_CG,
|
||||
REG_GSWCK_EN | REG_TRGMIICK_EN);
|
||||
/* Disable the MT7530 TRGMII clocks */
|
||||
core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
|
||||
|
||||
/* Setup the MT7530 TRGMII Tx Clock */
|
||||
core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1));
|
||||
@ -485,13 +486,8 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
|
||||
RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) |
|
||||
RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
|
||||
|
||||
/* Enable MT7530 core and TRGMII Tx clocks */
|
||||
core_set(priv, CORE_TRGMII_GSW_CLK_CG,
|
||||
REG_GSWCK_EN | REG_TRGMIICK_EN);
|
||||
} else {
|
||||
for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
|
||||
mt7530_rmw(priv, MT7530_TRGMII_RD(i),
|
||||
RD_TAP_MASK, RD_TAP(16));
|
||||
/* Enable the MT7530 TRGMII clocks */
|
||||
core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2201,6 +2197,15 @@ mt7530_setup(struct dsa_switch *ds)
|
||||
|
||||
mt7530_pll_setup(priv);
|
||||
|
||||
/* Lower Tx driving for TRGMII path */
|
||||
for (i = 0; i < NUM_TRGMII_CTRL; i++)
|
||||
mt7530_write(priv, MT7530_TRGMII_TD_ODT(i),
|
||||
TD_DM_DRVP(8) | TD_DM_DRVN(8));
|
||||
|
||||
for (i = 0; i < NUM_TRGMII_CTRL; i++)
|
||||
mt7530_rmw(priv, MT7530_TRGMII_RD(i),
|
||||
RD_TAP_MASK, RD_TAP(16));
|
||||
|
||||
/* Enable port 6 */
|
||||
val = mt7530_read(priv, MT7530_MHWTRAP);
|
||||
val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS;
|
||||
|
@ -370,8 +370,7 @@ static const struct ethtool_rmon_hist_range enetc_rmon_ranges[] = {
|
||||
};
|
||||
|
||||
static void enetc_rmon_stats(struct enetc_hw *hw, int mac,
|
||||
struct ethtool_rmon_stats *s,
|
||||
const struct ethtool_rmon_hist_range **ranges)
|
||||
struct ethtool_rmon_stats *s)
|
||||
{
|
||||
s->undersize_pkts = enetc_port_rd(hw, ENETC_PM_RUND(mac));
|
||||
s->oversize_pkts = enetc_port_rd(hw, ENETC_PM_ROVR(mac));
|
||||
@ -393,8 +392,6 @@ static void enetc_rmon_stats(struct enetc_hw *hw, int mac,
|
||||
s->hist_tx[4] = enetc_port_rd(hw, ENETC_PM_T1023(mac));
|
||||
s->hist_tx[5] = enetc_port_rd(hw, ENETC_PM_T1522(mac));
|
||||
s->hist_tx[6] = enetc_port_rd(hw, ENETC_PM_T1523X(mac));
|
||||
|
||||
*ranges = enetc_rmon_ranges;
|
||||
}
|
||||
|
||||
static void enetc_get_eth_mac_stats(struct net_device *ndev,
|
||||
@ -447,13 +444,15 @@ static void enetc_get_rmon_stats(struct net_device *ndev,
|
||||
struct enetc_hw *hw = &priv->si->hw;
|
||||
struct enetc_si *si = priv->si;
|
||||
|
||||
*ranges = enetc_rmon_ranges;
|
||||
|
||||
switch (rmon_stats->src) {
|
||||
case ETHTOOL_MAC_STATS_SRC_EMAC:
|
||||
enetc_rmon_stats(hw, 0, rmon_stats, ranges);
|
||||
enetc_rmon_stats(hw, 0, rmon_stats);
|
||||
break;
|
||||
case ETHTOOL_MAC_STATS_SRC_PMAC:
|
||||
if (si->hw_features & ENETC_SI_F_QBU)
|
||||
enetc_rmon_stats(hw, 1, rmon_stats, ranges);
|
||||
enetc_rmon_stats(hw, 1, rmon_stats);
|
||||
break;
|
||||
case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
|
||||
ethtool_aggregate_rmon_stats(ndev, rmon_stats);
|
||||
|
@ -537,7 +537,10 @@ static int gve_get_link_ksettings(struct net_device *netdev,
|
||||
struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct gve_priv *priv = netdev_priv(netdev);
|
||||
int err = gve_adminq_report_link_speed(priv);
|
||||
int err = 0;
|
||||
|
||||
if (priv->link_speed == 0)
|
||||
err = gve_adminq_report_link_speed(priv);
|
||||
|
||||
cmd->base.speed = priv->link_speed;
|
||||
return err;
|
||||
|
@ -171,10 +171,10 @@ static char *i40e_create_dummy_packet(u8 *dummy_packet, bool ipv4, u8 l4proto,
|
||||
struct i40e_fdir_filter *data)
|
||||
{
|
||||
bool is_vlan = !!data->vlan_tag;
|
||||
struct vlan_hdr vlan;
|
||||
struct ipv6hdr ipv6;
|
||||
struct ethhdr eth;
|
||||
struct iphdr ip;
|
||||
struct vlan_hdr vlan = {};
|
||||
struct ipv6hdr ipv6 = {};
|
||||
struct ethhdr eth = {};
|
||||
struct iphdr ip = {};
|
||||
u8 *tmp;
|
||||
|
||||
if (ipv4) {
|
||||
|
@ -661,7 +661,7 @@ struct iavf_rx_ptype_decoded iavf_ptype_lookup[BIT(8)] = {
|
||||
/* Non Tunneled IPv6 */
|
||||
IAVF_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3),
|
||||
IAVF_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3),
|
||||
IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY3),
|
||||
IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY4),
|
||||
IAVF_PTT_UNUSED_ENTRY(91),
|
||||
IAVF_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4),
|
||||
IAVF_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4),
|
||||
|
@ -893,6 +893,10 @@ static int iavf_vlan_rx_add_vid(struct net_device *netdev,
|
||||
{
|
||||
struct iavf_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
/* Do not track VLAN 0 filter, always added by the PF on VF init */
|
||||
if (!vid)
|
||||
return 0;
|
||||
|
||||
if (!VLAN_FILTERING_ALLOWED(adapter))
|
||||
return -EIO;
|
||||
|
||||
@ -919,6 +923,10 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev,
|
||||
{
|
||||
struct iavf_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
/* We do not track VLAN 0 filter */
|
||||
if (!vid)
|
||||
return 0;
|
||||
|
||||
iavf_del_vlan(adapter, IAVF_VLAN(vid, be16_to_cpu(proto)));
|
||||
if (proto == cpu_to_be16(ETH_P_8021Q))
|
||||
clear_bit(vid, adapter->vsi.active_cvlans);
|
||||
@ -5066,6 +5074,11 @@ static void iavf_remove(struct pci_dev *pdev)
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
break;
|
||||
}
|
||||
/* Simply return if we already went through iavf_shutdown */
|
||||
if (adapter->state == __IAVF_REMOVE) {
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_unlock(&adapter->crit_lock);
|
||||
usleep_range(500, 1000);
|
||||
|
@ -1096,7 +1096,7 @@ static inline void iavf_rx_hash(struct iavf_ring *ring,
|
||||
cpu_to_le64((u64)IAVF_RX_DESC_FLTSTAT_RSS_HASH <<
|
||||
IAVF_RX_DESC_STATUS_FLTSTAT_SHIFT);
|
||||
|
||||
if (ring->netdev->features & NETIF_F_RXHASH)
|
||||
if (!(ring->netdev->features & NETIF_F_RXHASH))
|
||||
return;
|
||||
|
||||
if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
|
||||
|
@ -2446,8 +2446,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
|
||||
list_for_each_entry(f, &adapter->vlan_filter_list, list) {
|
||||
if (f->is_new_vlan) {
|
||||
f->is_new_vlan = false;
|
||||
if (!f->vlan.vid)
|
||||
continue;
|
||||
if (f->vlan.tpid == ETH_P_8021Q)
|
||||
set_bit(f->vlan.vid,
|
||||
adapter->vsi.active_cvlans);
|
||||
|
@ -291,6 +291,7 @@ static void ice_vsi_delete_from_hw(struct ice_vsi *vsi)
|
||||
struct ice_vsi_ctx *ctxt;
|
||||
int status;
|
||||
|
||||
ice_fltr_remove_all(vsi);
|
||||
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
|
||||
if (!ctxt)
|
||||
return;
|
||||
@ -2892,7 +2893,6 @@ void ice_vsi_decfg(struct ice_vsi *vsi)
|
||||
!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))
|
||||
ice_cfg_sw_lldp(vsi, false, false);
|
||||
|
||||
ice_fltr_remove_all(vsi);
|
||||
ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
|
||||
err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);
|
||||
if (err)
|
||||
|
@ -4641,6 +4641,12 @@ static int ice_start_eth(struct ice_vsi *vsi)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ice_stop_eth(struct ice_vsi *vsi)
|
||||
{
|
||||
ice_fltr_remove_all(vsi);
|
||||
ice_vsi_close(vsi);
|
||||
}
|
||||
|
||||
static int ice_init_eth(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_vsi *vsi = ice_get_main_vsi(pf);
|
||||
@ -5129,7 +5135,7 @@ void ice_unload(struct ice_pf *pf)
|
||||
{
|
||||
ice_deinit_features(pf);
|
||||
ice_deinit_rdma(pf);
|
||||
ice_vsi_close(ice_get_main_vsi(pf));
|
||||
ice_stop_eth(ice_get_main_vsi(pf));
|
||||
ice_vsi_decfg(ice_get_main_vsi(pf));
|
||||
ice_deinit_dev(pf);
|
||||
}
|
||||
|
@ -1341,15 +1341,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
|
||||
struct ice_vf *vf;
|
||||
int ret;
|
||||
|
||||
vf = ice_get_vf_by_id(pf, vf_id);
|
||||
if (!vf)
|
||||
return -EINVAL;
|
||||
|
||||
if (ice_is_eswitch_mode_switchdev(pf)) {
|
||||
dev_info(ice_pf_to_dev(pf), "Trusted VF is forbidden in switchdev mode\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
vf = ice_get_vf_by_id(pf, vf_id);
|
||||
if (!vf)
|
||||
return -EINVAL;
|
||||
|
||||
ret = ice_check_vf_ready_for_cfg(vf);
|
||||
if (ret)
|
||||
goto out_put_vf;
|
||||
|
@ -1210,6 +1210,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
||||
ice_vc_fdir_irq_handler(ctrl_vsi, rx_desc);
|
||||
if (++ntc == cnt)
|
||||
ntc = 0;
|
||||
rx_ring->first_desc = ntc;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -109,6 +109,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *);
|
||||
static void igb_setup_mrqc(struct igb_adapter *);
|
||||
static int igb_probe(struct pci_dev *, const struct pci_device_id *);
|
||||
static void igb_remove(struct pci_dev *pdev);
|
||||
static void igb_init_queue_configuration(struct igb_adapter *adapter);
|
||||
static int igb_sw_init(struct igb_adapter *);
|
||||
int igb_open(struct net_device *);
|
||||
int igb_close(struct net_device *);
|
||||
@ -175,9 +176,7 @@ static void igb_nfc_filter_restore(struct igb_adapter *adapter);
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static int igb_vf_configure(struct igb_adapter *adapter, int vf);
|
||||
static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs);
|
||||
static int igb_disable_sriov(struct pci_dev *dev);
|
||||
static int igb_pci_disable_sriov(struct pci_dev *dev);
|
||||
static int igb_disable_sriov(struct pci_dev *dev, bool reinit);
|
||||
#endif
|
||||
|
||||
static int igb_suspend(struct device *);
|
||||
@ -3665,7 +3664,7 @@ err_sw_init:
|
||||
kfree(adapter->shadow_vfta);
|
||||
igb_clear_interrupt_scheme(adapter);
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
igb_disable_sriov(pdev);
|
||||
igb_disable_sriov(pdev, false);
|
||||
#endif
|
||||
pci_iounmap(pdev, adapter->io_addr);
|
||||
err_ioremap:
|
||||
@ -3679,7 +3678,38 @@ err_dma:
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static int igb_disable_sriov(struct pci_dev *pdev)
|
||||
static int igb_sriov_reinit(struct pci_dev *dev)
|
||||
{
|
||||
struct net_device *netdev = pci_get_drvdata(dev);
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
if (netif_running(netdev))
|
||||
igb_close(netdev);
|
||||
else
|
||||
igb_reset(adapter);
|
||||
|
||||
igb_clear_interrupt_scheme(adapter);
|
||||
|
||||
igb_init_queue_configuration(adapter);
|
||||
|
||||
if (igb_init_interrupt_scheme(adapter, true)) {
|
||||
rtnl_unlock();
|
||||
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (netif_running(netdev))
|
||||
igb_open(netdev);
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igb_disable_sriov(struct pci_dev *pdev, bool reinit)
|
||||
{
|
||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
@ -3713,10 +3743,10 @@ static int igb_disable_sriov(struct pci_dev *pdev)
|
||||
adapter->flags |= IGB_FLAG_DMAC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return reinit ? igb_sriov_reinit(pdev) : 0;
|
||||
}
|
||||
|
||||
static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)
|
||||
static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs, bool reinit)
|
||||
{
|
||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
@ -3781,12 +3811,6 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)
|
||||
"Unable to allocate memory for VF MAC filter list\n");
|
||||
}
|
||||
|
||||
/* only call pci_enable_sriov() if no VFs are allocated already */
|
||||
if (!old_vfs) {
|
||||
err = pci_enable_sriov(pdev, adapter->vfs_allocated_count);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
dev_info(&pdev->dev, "%d VFs allocated\n",
|
||||
adapter->vfs_allocated_count);
|
||||
for (i = 0; i < adapter->vfs_allocated_count; i++)
|
||||
@ -3794,6 +3818,17 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)
|
||||
|
||||
/* DMA Coalescing is not supported in IOV mode. */
|
||||
adapter->flags &= ~IGB_FLAG_DMAC;
|
||||
|
||||
if (reinit) {
|
||||
err = igb_sriov_reinit(pdev);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* only call pci_enable_sriov() if no VFs are allocated already */
|
||||
if (!old_vfs)
|
||||
err = pci_enable_sriov(pdev, adapter->vfs_allocated_count);
|
||||
|
||||
goto out;
|
||||
|
||||
err_out:
|
||||
@ -3863,9 +3898,7 @@ static void igb_remove(struct pci_dev *pdev)
|
||||
igb_release_hw_control(adapter);
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
rtnl_lock();
|
||||
igb_disable_sriov(pdev);
|
||||
rtnl_unlock();
|
||||
igb_disable_sriov(pdev, false);
|
||||
#endif
|
||||
|
||||
unregister_netdev(netdev);
|
||||
@ -3911,7 +3944,7 @@ static void igb_probe_vfs(struct igb_adapter *adapter)
|
||||
igb_reset_interrupt_capability(adapter);
|
||||
|
||||
pci_sriov_set_totalvfs(pdev, 7);
|
||||
igb_enable_sriov(pdev, max_vfs);
|
||||
igb_enable_sriov(pdev, max_vfs, false);
|
||||
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
}
|
||||
@ -9520,71 +9553,17 @@ static void igb_shutdown(struct pci_dev *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static int igb_sriov_reinit(struct pci_dev *dev)
|
||||
{
|
||||
struct net_device *netdev = pci_get_drvdata(dev);
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
if (netif_running(netdev))
|
||||
igb_close(netdev);
|
||||
else
|
||||
igb_reset(adapter);
|
||||
|
||||
igb_clear_interrupt_scheme(adapter);
|
||||
|
||||
igb_init_queue_configuration(adapter);
|
||||
|
||||
if (igb_init_interrupt_scheme(adapter, true)) {
|
||||
rtnl_unlock();
|
||||
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (netif_running(netdev))
|
||||
igb_open(netdev);
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igb_pci_disable_sriov(struct pci_dev *dev)
|
||||
{
|
||||
int err = igb_disable_sriov(dev);
|
||||
|
||||
if (!err)
|
||||
err = igb_sriov_reinit(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs)
|
||||
{
|
||||
int err = igb_enable_sriov(dev, num_vfs);
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = igb_sriov_reinit(dev);
|
||||
if (!err)
|
||||
return num_vfs;
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
|
||||
{
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
if (num_vfs == 0)
|
||||
return igb_pci_disable_sriov(dev);
|
||||
else
|
||||
return igb_pci_enable_sriov(dev, num_vfs);
|
||||
int err;
|
||||
|
||||
if (num_vfs == 0) {
|
||||
return igb_disable_sriov(dev, true);
|
||||
} else {
|
||||
err = igb_enable_sriov(dev, num_vfs, true);
|
||||
return err ? err : num_vfs;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -1074,7 +1074,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
|
||||
igbvf_intr_msix_rx, 0, adapter->rx_ring->name,
|
||||
netdev);
|
||||
if (err)
|
||||
goto out;
|
||||
goto free_irq_tx;
|
||||
|
||||
adapter->rx_ring->itr_register = E1000_EITR(vector);
|
||||
adapter->rx_ring->itr_val = adapter->current_itr;
|
||||
@ -1083,10 +1083,14 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
|
||||
err = request_irq(adapter->msix_entries[vector].vector,
|
||||
igbvf_msix_other, 0, netdev->name, netdev);
|
||||
if (err)
|
||||
goto out;
|
||||
goto free_irq_rx;
|
||||
|
||||
igbvf_configure_msix(adapter);
|
||||
return 0;
|
||||
free_irq_rx:
|
||||
free_irq(adapter->msix_entries[--vector].vector, netdev);
|
||||
free_irq_tx:
|
||||
free_irq(adapter->msix_entries[--vector].vector, netdev);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 2009 - 2018 Intel Corporation. */
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "vf.h"
|
||||
|
||||
static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
|
||||
@ -131,11 +133,16 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
|
||||
/* set our "perm_addr" based on info provided by PF */
|
||||
ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
|
||||
if (!ret_val) {
|
||||
if (msgbuf[0] == (E1000_VF_RESET |
|
||||
E1000_VT_MSGTYPE_ACK))
|
||||
switch (msgbuf[0]) {
|
||||
case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK:
|
||||
memcpy(hw->mac.perm_addr, addr, ETH_ALEN);
|
||||
else
|
||||
break;
|
||||
case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK:
|
||||
eth_zero_addr(hw->mac.perm_addr);
|
||||
break;
|
||||
default:
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6010,18 +6010,18 @@ static bool validate_schedule(struct igc_adapter *adapter,
|
||||
if (e->command != TC_TAPRIO_CMD_SET_GATES)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < adapter->num_tx_queues; i++) {
|
||||
if (e->gate_mask & BIT(i))
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
if (e->gate_mask & BIT(i)) {
|
||||
queue_uses[i]++;
|
||||
|
||||
/* There are limitations: A single queue cannot be
|
||||
* opened and closed multiple times per cycle unless the
|
||||
* gate stays open. Check for it.
|
||||
*/
|
||||
if (queue_uses[i] > 1 &&
|
||||
!(prev->gate_mask & BIT(i)))
|
||||
return false;
|
||||
}
|
||||
/* There are limitations: A single queue cannot
|
||||
* be opened and closed multiple times per cycle
|
||||
* unless the gate stays open. Check for it.
|
||||
*/
|
||||
if (queue_uses[i] > 1 &&
|
||||
!(prev->gate_mask & BIT(i)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -709,6 +709,7 @@ err_unreg_netdev:
|
||||
err_ptp_destroy:
|
||||
otx2_ptp_destroy(vf);
|
||||
err_detach_rsrc:
|
||||
free_percpu(vf->hw.lmt_info);
|
||||
if (test_bit(CN10K_LMTST, &vf->hw.cap_flag))
|
||||
qmem_free(vf->dev, vf->dync_lmt);
|
||||
otx2_detach_resources(&vf->mbox);
|
||||
@ -762,6 +763,7 @@ static void otx2vf_remove(struct pci_dev *pdev)
|
||||
otx2_shutdown_tc(vf);
|
||||
otx2vf_disable_mbox_intr(vf);
|
||||
otx2_detach_resources(&vf->mbox);
|
||||
free_percpu(vf->hw.lmt_info);
|
||||
if (test_bit(CN10K_LMTST, &vf->hw.cap_flag))
|
||||
qmem_free(vf->dev, vf->dync_lmt);
|
||||
otx2vf_vfaf_mbox_destroy(vf);
|
||||
|
@ -674,7 +674,7 @@ int mlx4_en_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
|
||||
struct mlx4_en_xdp_buff *_ctx = (void *)ctx;
|
||||
|
||||
if (unlikely(_ctx->ring->hwtstamp_rx_filter != HWTSTAMP_FILTER_ALL))
|
||||
return -EOPNOTSUPP;
|
||||
return -ENODATA;
|
||||
|
||||
*timestamp = mlx4_en_get_hwtstamp(_ctx->mdev,
|
||||
mlx4_en_get_cqe_ts(_ctx->cqe));
|
||||
@ -686,7 +686,7 @@ int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
|
||||
struct mlx4_en_xdp_buff *_ctx = (void *)ctx;
|
||||
|
||||
if (unlikely(!(_ctx->dev->features & NETIF_F_RXHASH)))
|
||||
return -EOPNOTSUPP;
|
||||
return -ENODATA;
|
||||
|
||||
*hash = be32_to_cpu(_ctx->cqe->immed_rss_invalid);
|
||||
return 0;
|
||||
|
@ -162,7 +162,7 @@ static int mlx5e_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
|
||||
const struct mlx5e_xdp_buff *_ctx = (void *)ctx;
|
||||
|
||||
if (unlikely(!mlx5e_rx_hw_stamp(_ctx->rq->tstamp)))
|
||||
return -EOPNOTSUPP;
|
||||
return -ENODATA;
|
||||
|
||||
*timestamp = mlx5e_cqe_ts_to_ns(_ctx->rq->ptp_cyc2time,
|
||||
_ctx->rq->clock, get_cqe_ts(_ctx->cqe));
|
||||
@ -174,7 +174,7 @@ static int mlx5e_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
|
||||
const struct mlx5e_xdp_buff *_ctx = (void *)ctx;
|
||||
|
||||
if (unlikely(!(_ctx->xdp.rxq->dev->features & NETIF_F_RXHASH)))
|
||||
return -EOPNOTSUPP;
|
||||
return -ENODATA;
|
||||
|
||||
*hash = be32_to_cpu(_ctx->cqe->rss_hash_result);
|
||||
return 0;
|
||||
|
@ -1412,6 +1412,7 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *mac
|
||||
struct mlx5e_macsec_aso *aso;
|
||||
struct mlx5_aso_wqe *aso_wqe;
|
||||
struct mlx5_aso *maso;
|
||||
unsigned long expires;
|
||||
int err;
|
||||
|
||||
aso = &macsec->aso;
|
||||
@ -1425,7 +1426,13 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *mac
|
||||
macsec_aso_build_wqe_ctrl_seg(aso, &aso_wqe->aso_ctrl, NULL);
|
||||
|
||||
mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl);
|
||||
err = mlx5_aso_poll_cq(maso, false);
|
||||
expires = jiffies + msecs_to_jiffies(10);
|
||||
do {
|
||||
err = mlx5_aso_poll_cq(maso, false);
|
||||
if (err)
|
||||
usleep_range(2, 10);
|
||||
} while (err && time_is_after_jiffies(expires));
|
||||
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
|
@ -117,12 +117,14 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
|
||||
if (!MLX5_CAP_GEN(priv->mdev, ets))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
|
||||
for (i = 0; i < ets->ets_cap; i++) {
|
||||
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||
err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
|
||||
for (i = 0; i < ets->ets_cap; i++) {
|
||||
err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -4150,8 +4150,12 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
|
||||
}
|
||||
}
|
||||
|
||||
if (mlx5e_is_uplink_rep(priv))
|
||||
if (mlx5e_is_uplink_rep(priv)) {
|
||||
features = mlx5e_fix_uplink_rep_features(netdev, features);
|
||||
features |= NETIF_F_NETNS_LOCAL;
|
||||
} else {
|
||||
features &= ~NETIF_F_NETNS_LOCAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
|
@ -1103,8 +1103,8 @@ static void
|
||||
mlx5e_hairpin_params_init(struct mlx5e_hairpin_params *hairpin_params,
|
||||
struct mlx5_core_dev *mdev)
|
||||
{
|
||||
u32 link_speed = 0;
|
||||
u64 link_speed64;
|
||||
u32 link_speed;
|
||||
|
||||
hairpin_params->mdev = mdev;
|
||||
/* set hairpin pair per each 50Gbs share of the link */
|
||||
|
@ -364,8 +364,7 @@ int mlx5_esw_acl_ingress_vport_metadata_update(struct mlx5_eswitch *esw, u16 vpo
|
||||
|
||||
if (WARN_ON_ONCE(IS_ERR(vport))) {
|
||||
esw_warn(esw->dev, "vport(%d) invalid!\n", vport_num);
|
||||
err = PTR_ERR(vport);
|
||||
goto out;
|
||||
return PTR_ERR(vport);
|
||||
}
|
||||
|
||||
esw_acl_ingress_ofld_rules_destroy(esw, vport);
|
||||
|
@ -959,6 +959,7 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num)
|
||||
*/
|
||||
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--;
|
||||
|
||||
|
@ -3405,6 +3405,18 @@ static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool esw_offloads_devlink_ns_eq_netdev_ns(struct devlink *devlink)
|
||||
{
|
||||
struct net *devl_net, *netdev_net;
|
||||
struct mlx5_eswitch *esw;
|
||||
|
||||
esw = mlx5_devlink_eswitch_get(devlink);
|
||||
netdev_net = dev_net(esw->dev->mlx5e_res.uplink_netdev);
|
||||
devl_net = devlink_net(devlink);
|
||||
|
||||
return net_eq(devl_net, netdev_net);
|
||||
}
|
||||
|
||||
int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
@ -3419,6 +3431,13 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
|
||||
if (esw_mode_from_devlink(mode, &mlx5_mode))
|
||||
return -EINVAL;
|
||||
|
||||
if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV &&
|
||||
!esw_offloads_devlink_ns_eq_netdev_ns(devlink)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Can't change E-Switch mode to switchdev when netdev net namespace has diverged from the devlink's.");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
mlx5_lag_disable_change(esw->dev);
|
||||
err = mlx5_esw_try_lock(esw);
|
||||
if (err < 0) {
|
||||
|
@ -105,7 +105,6 @@ struct mlxsw_thermal {
|
||||
struct thermal_zone_device *tzdev;
|
||||
int polling_delay;
|
||||
struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
|
||||
u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
|
||||
struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
|
||||
struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
|
||||
struct mlxsw_thermal_area line_cards[];
|
||||
@ -468,7 +467,7 @@ static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
|
||||
return idx;
|
||||
|
||||
/* Normalize the state to the valid speed range. */
|
||||
state = thermal->cooling_levels[state];
|
||||
state = max_t(unsigned long, MLXSW_THERMAL_MIN_STATE, state);
|
||||
mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
|
||||
err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
|
||||
if (err) {
|
||||
@ -859,10 +858,6 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize cooling levels per PWM state. */
|
||||
for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
|
||||
thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i);
|
||||
|
||||
thermal->polling_delay = bus_info->low_frequency ?
|
||||
MLXSW_THERMAL_SLOW_POLL_INT :
|
||||
MLXSW_THERMAL_POLL_INT;
|
||||
|
@ -1354,7 +1354,7 @@ static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
|
||||
u16 vid)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||
u8 local_port = mlxsw_sp_port->local_port;
|
||||
u16 local_port = mlxsw_sp_port->local_port;
|
||||
int err;
|
||||
|
||||
/* In case there are no {Port, VID} => FID mappings on the port,
|
||||
@ -1391,7 +1391,7 @@ mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
|
||||
struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||
u8 local_port = mlxsw_sp_port->local_port;
|
||||
u16 local_port = mlxsw_sp_port->local_port;
|
||||
|
||||
mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
|
||||
mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
|
||||
|
@ -258,6 +258,7 @@ struct ocelot_stat_layout {
|
||||
struct ocelot_stats_region {
|
||||
struct list_head node;
|
||||
u32 base;
|
||||
enum ocelot_stat first_stat;
|
||||
int count;
|
||||
u32 *buf;
|
||||
};
|
||||
@ -273,6 +274,7 @@ static const struct ocelot_stat_layout ocelot_mm_stats_layout[OCELOT_NUM_STATS]
|
||||
OCELOT_STAT(RX_ASSEMBLY_OK),
|
||||
OCELOT_STAT(RX_MERGE_FRAGMENTS),
|
||||
OCELOT_STAT(TX_MERGE_FRAGMENTS),
|
||||
OCELOT_STAT(TX_MM_HOLD),
|
||||
OCELOT_STAT(RX_PMAC_OCTETS),
|
||||
OCELOT_STAT(RX_PMAC_UNICAST),
|
||||
OCELOT_STAT(RX_PMAC_MULTICAST),
|
||||
@ -341,11 +343,12 @@ static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
|
||||
*/
|
||||
static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port)
|
||||
{
|
||||
unsigned int idx = port * OCELOT_NUM_STATS;
|
||||
struct ocelot_stats_region *region;
|
||||
int j;
|
||||
|
||||
list_for_each_entry(region, &ocelot->stats_regions, node) {
|
||||
unsigned int idx = port * OCELOT_NUM_STATS + region->first_stat;
|
||||
|
||||
for (j = 0; j < region->count; j++) {
|
||||
u64 *stat = &ocelot->stats[idx + j];
|
||||
u64 val = region->buf[j];
|
||||
@ -355,8 +358,6 @@ static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port)
|
||||
|
||||
*stat = (*stat & ~(u64)U32_MAX) + val;
|
||||
}
|
||||
|
||||
idx += region->count;
|
||||
}
|
||||
}
|
||||
|
||||
@ -899,7 +900,8 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
|
||||
if (!layout[i].reg)
|
||||
continue;
|
||||
|
||||
if (region && layout[i].reg == last + 4) {
|
||||
if (region && ocelot->map[SYS][layout[i].reg & REG_MASK] ==
|
||||
ocelot->map[SYS][last & REG_MASK] + 4) {
|
||||
region->count++;
|
||||
} else {
|
||||
region = devm_kzalloc(ocelot->dev, sizeof(*region),
|
||||
@ -914,6 +916,7 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
|
||||
WARN_ON(last >= layout[i].reg);
|
||||
|
||||
region->base = layout[i].reg;
|
||||
region->first_stat = i;
|
||||
region->count = 1;
|
||||
list_add_tail(®ion->node, &ocelot->stats_regions);
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
|
||||
*/
|
||||
|
||||
laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
|
||||
if (!laddr) {
|
||||
if (dma_mapping_error(lp->device, laddr)) {
|
||||
pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name);
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
@ -509,7 +509,7 @@ static bool sonic_alloc_rb(struct net_device *dev, struct sonic_local *lp,
|
||||
|
||||
*new_addr = dma_map_single(lp->device, skb_put(*new_skb, SONIC_RBSIZE),
|
||||
SONIC_RBSIZE, DMA_FROM_DEVICE);
|
||||
if (!*new_addr) {
|
||||
if (dma_mapping_error(lp->device, *new_addr)) {
|
||||
dev_kfree_skb(*new_skb);
|
||||
*new_skb = NULL;
|
||||
return false;
|
||||
|
@ -4404,6 +4404,9 @@ qed_iov_configure_min_tx_rate(struct qed_dev *cdev, int vfid, u32 rate)
|
||||
}
|
||||
|
||||
vf = qed_iov_get_vf_info(QED_LEADING_HWFN(cdev), (u16)vfid, true);
|
||||
if (!vf)
|
||||
return -EINVAL;
|
||||
|
||||
vport_id = vf->vport_id;
|
||||
|
||||
return qed_configure_vport_wfq(cdev, vport_id, rate);
|
||||
@ -5152,7 +5155,7 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
|
||||
|
||||
/* Validate that the VF has a configured vport */
|
||||
vf = qed_iov_get_vf_info(hwfn, i, true);
|
||||
if (!vf->vport_instance)
|
||||
if (!vf || !vf->vport_instance)
|
||||
continue;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
@ -724,9 +724,15 @@ static int emac_remove(struct platform_device *pdev)
|
||||
struct net_device *netdev = dev_get_drvdata(&pdev->dev);
|
||||
struct emac_adapter *adpt = netdev_priv(netdev);
|
||||
|
||||
netif_carrier_off(netdev);
|
||||
netif_tx_disable(netdev);
|
||||
|
||||
unregister_netdev(netdev);
|
||||
netif_napi_del(&adpt->rx_q.napi);
|
||||
|
||||
free_irq(adpt->irq.irq, &adpt->irq);
|
||||
cancel_work_sync(&adpt->work_thread);
|
||||
|
||||
emac_clks_teardown(adpt);
|
||||
|
||||
put_device(&adpt->phydev->mdio.dev);
|
||||
|
@ -418,6 +418,7 @@ struct dma_features {
|
||||
unsigned int frpbs;
|
||||
unsigned int frpes;
|
||||
unsigned int addr64;
|
||||
unsigned int host_dma_width;
|
||||
unsigned int rssen;
|
||||
unsigned int vlhash;
|
||||
unsigned int sphen;
|
||||
|
@ -288,7 +288,7 @@ static int imx_dwmac_probe(struct platform_device *pdev)
|
||||
goto err_parse_dt;
|
||||
}
|
||||
|
||||
plat_dat->addr64 = dwmac->ops->addr_width;
|
||||
plat_dat->host_dma_width = dwmac->ops->addr_width;
|
||||
plat_dat->init = imx_dwmac_init;
|
||||
plat_dat->exit = imx_dwmac_exit;
|
||||
plat_dat->clks_config = imx_dwmac_clks_config;
|
||||
|
@ -684,7 +684,7 @@ static int ehl_pse0_common_data(struct pci_dev *pdev,
|
||||
|
||||
intel_priv->is_pse = true;
|
||||
plat->bus_id = 2;
|
||||
plat->addr64 = 32;
|
||||
plat->host_dma_width = 32;
|
||||
|
||||
plat->clk_ptp_rate = 200000000;
|
||||
|
||||
@ -725,7 +725,7 @@ static int ehl_pse1_common_data(struct pci_dev *pdev,
|
||||
|
||||
intel_priv->is_pse = true;
|
||||
plat->bus_id = 3;
|
||||
plat->addr64 = 32;
|
||||
plat->host_dma_width = 32;
|
||||
|
||||
plat->clk_ptp_rate = 200000000;
|
||||
|
||||
|
@ -591,7 +591,7 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev,
|
||||
plat->use_phy_wol = priv_plat->mac_wol ? 0 : 1;
|
||||
plat->riwt_off = 1;
|
||||
plat->maxmtu = ETH_DATA_LEN;
|
||||
plat->addr64 = priv_plat->variant->dma_bit_mask;
|
||||
plat->host_dma_width = priv_plat->variant->dma_bit_mask;
|
||||
plat->bsp_priv = priv_plat;
|
||||
plat->init = mediatek_dwmac_init;
|
||||
plat->clks_config = mediatek_dwmac_clks_config;
|
||||
|
@ -1431,7 +1431,7 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv,
|
||||
struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
|
||||
gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
|
||||
|
||||
if (priv->dma_cap.addr64 <= 32)
|
||||
if (priv->dma_cap.host_dma_width <= 32)
|
||||
gfp |= GFP_DMA32;
|
||||
|
||||
if (!buf->page) {
|
||||
@ -4587,7 +4587,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
|
||||
unsigned int entry = rx_q->dirty_rx;
|
||||
gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
|
||||
|
||||
if (priv->dma_cap.addr64 <= 32)
|
||||
if (priv->dma_cap.host_dma_width <= 32)
|
||||
gfp |= GFP_DMA32;
|
||||
|
||||
while (dirty-- > 0) {
|
||||
@ -6205,7 +6205,7 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
|
||||
seq_printf(seq, "\tFlexible RX Parser: %s\n",
|
||||
priv->dma_cap.frpsel ? "Y" : "N");
|
||||
seq_printf(seq, "\tEnhanced Addressing: %d\n",
|
||||
priv->dma_cap.addr64);
|
||||
priv->dma_cap.host_dma_width);
|
||||
seq_printf(seq, "\tReceive Side Scaling: %s\n",
|
||||
priv->dma_cap.rssen ? "Y" : "N");
|
||||
seq_printf(seq, "\tVLAN Hash Filtering: %s\n",
|
||||
@ -7178,20 +7178,22 @@ int stmmac_dvr_probe(struct device *device,
|
||||
dev_info(priv->device, "SPH feature enabled\n");
|
||||
}
|
||||
|
||||
/* The current IP register MAC_HW_Feature1[ADDR64] only define
|
||||
* 32/40/64 bit width, but some SOC support others like i.MX8MP
|
||||
* support 34 bits but it map to 40 bits width in MAC_HW_Feature1[ADDR64].
|
||||
* So overwrite dma_cap.addr64 according to HW real design.
|
||||
/* Ideally our host DMA address width is the same as for the
|
||||
* device. However, it may differ and then we have to use our
|
||||
* host DMA width for allocation and the device DMA width for
|
||||
* register handling.
|
||||
*/
|
||||
if (priv->plat->addr64)
|
||||
priv->dma_cap.addr64 = priv->plat->addr64;
|
||||
if (priv->plat->host_dma_width)
|
||||
priv->dma_cap.host_dma_width = priv->plat->host_dma_width;
|
||||
else
|
||||
priv->dma_cap.host_dma_width = priv->dma_cap.addr64;
|
||||
|
||||
if (priv->dma_cap.addr64) {
|
||||
if (priv->dma_cap.host_dma_width) {
|
||||
ret = dma_set_mask_and_coherent(device,
|
||||
DMA_BIT_MASK(priv->dma_cap.addr64));
|
||||
DMA_BIT_MASK(priv->dma_cap.host_dma_width));
|
||||
if (!ret) {
|
||||
dev_info(priv->device, "Using %d bits DMA width\n",
|
||||
priv->dma_cap.addr64);
|
||||
dev_info(priv->device, "Using %d/%d bits DMA host/device width\n",
|
||||
priv->dma_cap.host_dma_width, priv->dma_cap.addr64);
|
||||
|
||||
/*
|
||||
* If more than 32 bits can be addressed, make sure to
|
||||
@ -7206,7 +7208,7 @@ int stmmac_dvr_probe(struct device *device,
|
||||
goto error_hw_init;
|
||||
}
|
||||
|
||||
priv->dma_cap.addr64 = 32;
|
||||
priv->dma_cap.host_dma_width = 32;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -636,6 +636,10 @@ static void am65_cpts_perout_enable_hw(struct am65_cpts *cpts,
|
||||
val = lower_32_bits(cycles);
|
||||
am65_cpts_write32(cpts, val, genf[req->index].length);
|
||||
|
||||
am65_cpts_write32(cpts, 0, genf[req->index].control);
|
||||
am65_cpts_write32(cpts, 0, genf[req->index].ppm_hi);
|
||||
am65_cpts_write32(cpts, 0, genf[req->index].ppm_low);
|
||||
|
||||
cpts->genf_enable |= BIT(req->index);
|
||||
} else {
|
||||
am65_cpts_write32(cpts, 0, genf[req->index].length);
|
||||
|
@ -317,15 +317,17 @@ static int gelic_card_init_chain(struct gelic_card *card,
|
||||
|
||||
/* set up the hardware pointers in each descriptor */
|
||||
for (i = 0; i < no; i++, descr++) {
|
||||
gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE);
|
||||
descr->bus_addr =
|
||||
dma_map_single(ctodev(card), descr,
|
||||
GELIC_DESCR_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_addr_t cpu_addr;
|
||||
|
||||
if (!descr->bus_addr)
|
||||
gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE);
|
||||
|
||||
cpu_addr = dma_map_single(ctodev(card), descr,
|
||||
GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL);
|
||||
|
||||
if (dma_mapping_error(ctodev(card), cpu_addr))
|
||||
goto iommu_error;
|
||||
|
||||
descr->bus_addr = cpu_to_be32(cpu_addr);
|
||||
descr->next = descr + 1;
|
||||
descr->prev = descr - 1;
|
||||
}
|
||||
@ -365,26 +367,28 @@ iommu_error:
|
||||
*
|
||||
* allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
|
||||
* Activate the descriptor state-wise
|
||||
*
|
||||
* Gelic RX sk_buffs must be aligned to GELIC_NET_RXBUF_ALIGN and the length
|
||||
* must be a multiple of GELIC_NET_RXBUF_ALIGN.
|
||||
*/
|
||||
static int gelic_descr_prepare_rx(struct gelic_card *card,
|
||||
struct gelic_descr *descr)
|
||||
{
|
||||
static const unsigned int rx_skb_size =
|
||||
ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN) +
|
||||
GELIC_NET_RXBUF_ALIGN - 1;
|
||||
dma_addr_t cpu_addr;
|
||||
int offset;
|
||||
unsigned int bufsize;
|
||||
|
||||
if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE)
|
||||
dev_info(ctodev(card), "%s: ERROR status\n", __func__);
|
||||
/* we need to round up the buffer size to a multiple of 128 */
|
||||
bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN);
|
||||
|
||||
/* and we need to have it 128 byte aligned, therefore we allocate a
|
||||
* bit more */
|
||||
descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1);
|
||||
descr->skb = netdev_alloc_skb(*card->netdev, rx_skb_size);
|
||||
if (!descr->skb) {
|
||||
descr->buf_addr = 0; /* tell DMAC don't touch memory */
|
||||
return -ENOMEM;
|
||||
}
|
||||
descr->buf_size = cpu_to_be32(bufsize);
|
||||
descr->buf_size = cpu_to_be32(rx_skb_size);
|
||||
descr->dmac_cmd_status = 0;
|
||||
descr->result_size = 0;
|
||||
descr->valid_size = 0;
|
||||
@ -395,11 +399,10 @@ static int gelic_descr_prepare_rx(struct gelic_card *card,
|
||||
if (offset)
|
||||
skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset);
|
||||
/* io-mmu-map the skb */
|
||||
descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card),
|
||||
descr->skb->data,
|
||||
GELIC_NET_MAX_MTU,
|
||||
DMA_FROM_DEVICE));
|
||||
if (!descr->buf_addr) {
|
||||
cpu_addr = dma_map_single(ctodev(card), descr->skb->data,
|
||||
GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE);
|
||||
descr->buf_addr = cpu_to_be32(cpu_addr);
|
||||
if (dma_mapping_error(ctodev(card), cpu_addr)) {
|
||||
dev_kfree_skb_any(descr->skb);
|
||||
descr->skb = NULL;
|
||||
dev_info(ctodev(card),
|
||||
@ -779,7 +782,7 @@ static int gelic_descr_prepare_tx(struct gelic_card *card,
|
||||
|
||||
buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE);
|
||||
|
||||
if (!buf) {
|
||||
if (dma_mapping_error(ctodev(card), buf)) {
|
||||
dev_err(ctodev(card),
|
||||
"dma map 2 failed (%p, %i). Dropping packet\n",
|
||||
skb->data, skb->len);
|
||||
@ -915,7 +918,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr,
|
||||
data_error = be32_to_cpu(descr->data_error);
|
||||
/* unmap skb buffer */
|
||||
dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr),
|
||||
GELIC_NET_MAX_MTU,
|
||||
GELIC_NET_MAX_FRAME,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
skb_put(skb, be32_to_cpu(descr->valid_size)?
|
||||
|
@ -19,8 +19,9 @@
|
||||
#define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */
|
||||
#define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */
|
||||
|
||||
#define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN
|
||||
#define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN
|
||||
#define GELIC_NET_MAX_FRAME 2312
|
||||
#define GELIC_NET_MAX_MTU 2294
|
||||
#define GELIC_NET_MIN_MTU 64
|
||||
#define GELIC_NET_RXBUF_ALIGN 128
|
||||
#define GELIC_CARD_RX_CSUM_DEFAULT 1 /* hw chksum */
|
||||
#define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ
|
||||
|
@ -503,6 +503,11 @@ static void
|
||||
xirc2ps_detach(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
struct local_info *local = netdev_priv(dev);
|
||||
|
||||
netif_carrier_off(dev);
|
||||
netif_tx_disable(dev);
|
||||
cancel_work_sync(&local->tx_timeout_task);
|
||||
|
||||
dev_dbg(&link->dev, "detach\n");
|
||||
|
||||
|
@ -18,16 +18,18 @@ MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/**
|
||||
* acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL.
|
||||
* __acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL.
|
||||
* @mdio: pointer to mii_bus structure
|
||||
* @fwnode: pointer to fwnode of MDIO bus. This fwnode is expected to represent
|
||||
* @owner: module owning this @mdio object.
|
||||
* an ACPI device object corresponding to the MDIO bus and its children are
|
||||
* expected to correspond to the PHY devices on that bus.
|
||||
*
|
||||
* This function registers the mii_bus structure and registers a phy_device
|
||||
* for each child node of @fwnode.
|
||||
*/
|
||||
int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
|
||||
int __acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode,
|
||||
struct module *owner)
|
||||
{
|
||||
struct fwnode_handle *child;
|
||||
u32 addr;
|
||||
@ -35,7 +37,7 @@ int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
|
||||
|
||||
/* Mask out all PHYs from auto probing. */
|
||||
mdio->phy_mask = GENMASK(31, 0);
|
||||
ret = mdiobus_register(mdio);
|
||||
ret = __mdiobus_register(mdio, owner);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -55,4 +57,4 @@ int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_mdiobus_register);
|
||||
EXPORT_SYMBOL(__acpi_mdiobus_register);
|
||||
|
@ -106,6 +106,7 @@ static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
|
||||
if (i >= ARRAY_SIZE(nexus->buses))
|
||||
break;
|
||||
}
|
||||
fwnode_handle_put(fwn);
|
||||
return 0;
|
||||
|
||||
err_release_regions:
|
||||
|
@ -139,21 +139,23 @@ bool of_mdiobus_child_is_phy(struct device_node *child)
|
||||
EXPORT_SYMBOL(of_mdiobus_child_is_phy);
|
||||
|
||||
/**
|
||||
* of_mdiobus_register - Register mii_bus and create PHYs from the device tree
|
||||
* __of_mdiobus_register - Register mii_bus and create PHYs from the device tree
|
||||
* @mdio: pointer to mii_bus structure
|
||||
* @np: pointer to device_node of MDIO bus.
|
||||
* @owner: module owning the @mdio object.
|
||||
*
|
||||
* This function registers the mii_bus structure and registers a phy_device
|
||||
* for each child node of @np.
|
||||
*/
|
||||
int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
|
||||
int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,
|
||||
struct module *owner)
|
||||
{
|
||||
struct device_node *child;
|
||||
bool scanphys = false;
|
||||
int addr, rc;
|
||||
|
||||
if (!np)
|
||||
return mdiobus_register(mdio);
|
||||
return __mdiobus_register(mdio, owner);
|
||||
|
||||
/* Do not continue if the node is disabled */
|
||||
if (!of_device_is_available(np))
|
||||
@ -172,7 +174,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
|
||||
of_property_read_u32(np, "reset-post-delay-us", &mdio->reset_post_delay_us);
|
||||
|
||||
/* Register the MDIO bus */
|
||||
rc = mdiobus_register(mdio);
|
||||
rc = __mdiobus_register(mdio, owner);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -236,7 +238,7 @@ unregister:
|
||||
mdiobus_unregister(mdio);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(of_mdiobus_register);
|
||||
EXPORT_SYMBOL(__of_mdiobus_register);
|
||||
|
||||
/**
|
||||
* of_mdio_find_device - Given a device tree node, find the mdio_device
|
||||
|
@ -98,13 +98,14 @@ EXPORT_SYMBOL(__devm_mdiobus_register);
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF_MDIO)
|
||||
/**
|
||||
* devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register()
|
||||
* __devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register()
|
||||
* @dev: Device to register mii_bus for
|
||||
* @mdio: MII bus structure to register
|
||||
* @np: Device node to parse
|
||||
* @owner: Owning module
|
||||
*/
|
||||
int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
|
||||
struct device_node *np)
|
||||
int __devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
|
||||
struct device_node *np, struct module *owner)
|
||||
{
|
||||
struct mdiobus_devres *dr;
|
||||
int ret;
|
||||
@ -117,7 +118,7 @@ int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
|
||||
if (!dr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_mdiobus_register(mdio, np);
|
||||
ret = __of_mdiobus_register(mdio, np, owner);
|
||||
if (ret) {
|
||||
devres_free(dr);
|
||||
return ret;
|
||||
@ -127,7 +128,7 @@ int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
|
||||
devres_add(dev, dr);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_of_mdiobus_register);
|
||||
EXPORT_SYMBOL(__devm_of_mdiobus_register);
|
||||
#endif /* CONFIG_OF_MDIO */
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -57,6 +57,18 @@ static const char *phy_state_to_str(enum phy_state st)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void phy_process_state_change(struct phy_device *phydev,
|
||||
enum phy_state old_state)
|
||||
{
|
||||
if (old_state != phydev->state) {
|
||||
phydev_dbg(phydev, "PHY state change %s -> %s\n",
|
||||
phy_state_to_str(old_state),
|
||||
phy_state_to_str(phydev->state));
|
||||
if (phydev->drv && phydev->drv->link_change_notify)
|
||||
phydev->drv->link_change_notify(phydev);
|
||||
}
|
||||
}
|
||||
|
||||
static void phy_link_up(struct phy_device *phydev)
|
||||
{
|
||||
phydev->phy_link_change(phydev, true);
|
||||
@ -1301,6 +1313,7 @@ EXPORT_SYMBOL(phy_free_interrupt);
|
||||
void phy_stop(struct phy_device *phydev)
|
||||
{
|
||||
struct net_device *dev = phydev->attached_dev;
|
||||
enum phy_state old_state;
|
||||
|
||||
if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
|
||||
WARN(1, "called from state %s\n",
|
||||
@ -1309,6 +1322,7 @@ void phy_stop(struct phy_device *phydev)
|
||||
}
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
old_state = phydev->state;
|
||||
|
||||
if (phydev->state == PHY_CABLETEST) {
|
||||
phy_abort_cable_test(phydev);
|
||||
@ -1319,6 +1333,7 @@ void phy_stop(struct phy_device *phydev)
|
||||
sfp_upstream_stop(phydev->sfp_bus);
|
||||
|
||||
phydev->state = PHY_HALTED;
|
||||
phy_process_state_change(phydev, old_state);
|
||||
|
||||
mutex_unlock(&phydev->lock);
|
||||
|
||||
@ -1436,13 +1451,7 @@ void phy_state_machine(struct work_struct *work)
|
||||
if (err < 0)
|
||||
phy_error(phydev);
|
||||
|
||||
if (old_state != phydev->state) {
|
||||
phydev_dbg(phydev, "PHY state change %s -> %s\n",
|
||||
phy_state_to_str(old_state),
|
||||
phy_state_to_str(phydev->state));
|
||||
if (phydev->drv && phydev->drv->link_change_notify)
|
||||
phydev->drv->link_change_notify(phydev);
|
||||
}
|
||||
phy_process_state_change(phydev, old_state);
|
||||
|
||||
/* Only re-schedule a PHY state machine change if we are polling the
|
||||
* PHY, if PHY_MAC_INTERRUPT is set, then we will be moving
|
||||
|
@ -2190,6 +2190,11 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Force a poll to re-read the hardware signal state after
|
||||
* sfp_sm_mod_probe() changed state_hw_mask.
|
||||
*/
|
||||
mod_delayed_work(system_wq, &sfp->poll, 1);
|
||||
|
||||
err = sfp_hwmon_insert(sfp);
|
||||
if (err)
|
||||
dev_warn(sfp->dev, "hwmon probe failed: %pe\n",
|
||||
|
@ -666,8 +666,9 @@ static int asix_resume(struct usb_interface *intf)
|
||||
static int ax88772_init_mdio(struct usbnet *dev)
|
||||
{
|
||||
struct asix_common_private *priv = dev->driver_priv;
|
||||
int ret;
|
||||
|
||||
priv->mdio = devm_mdiobus_alloc(&dev->udev->dev);
|
||||
priv->mdio = mdiobus_alloc();
|
||||
if (!priv->mdio)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -679,7 +680,20 @@ static int ax88772_init_mdio(struct usbnet *dev)
|
||||
snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
|
||||
dev->udev->bus->busnum, dev->udev->devnum);
|
||||
|
||||
return devm_mdiobus_register(&dev->udev->dev, priv->mdio);
|
||||
ret = mdiobus_register(priv->mdio);
|
||||
if (ret) {
|
||||
netdev_err(dev->net, "Could not register MDIO bus (err %d)\n", ret);
|
||||
mdiobus_free(priv->mdio);
|
||||
priv->mdio = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ax88772_mdio_unregister(struct asix_common_private *priv)
|
||||
{
|
||||
mdiobus_unregister(priv->mdio);
|
||||
mdiobus_free(priv->mdio);
|
||||
}
|
||||
|
||||
static int ax88772_init_phy(struct usbnet *dev)
|
||||
@ -896,16 +910,23 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
|
||||
ret = ax88772_init_mdio(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto mdio_err;
|
||||
|
||||
ret = ax88772_phylink_setup(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto phylink_err;
|
||||
|
||||
ret = ax88772_init_phy(dev);
|
||||
if (ret)
|
||||
phylink_destroy(priv->phylink);
|
||||
goto initphy_err;
|
||||
|
||||
return 0;
|
||||
|
||||
initphy_err:
|
||||
phylink_destroy(priv->phylink);
|
||||
phylink_err:
|
||||
ax88772_mdio_unregister(priv);
|
||||
mdio_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -926,6 +947,7 @@ static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
|
||||
phylink_disconnect_phy(priv->phylink);
|
||||
rtnl_unlock();
|
||||
phylink_destroy(priv->phylink);
|
||||
ax88772_mdio_unregister(priv);
|
||||
asix_rx_fixup_common_free(dev->driver_priv);
|
||||
}
|
||||
|
||||
|
@ -3579,13 +3579,29 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb,
|
||||
size = (rx_cmd_a & RX_CMD_A_LEN_MASK_);
|
||||
align_count = (4 - ((size + RXW_PADDING) % 4)) % 4;
|
||||
|
||||
if (unlikely(size > skb->len)) {
|
||||
netif_dbg(dev, rx_err, dev->net,
|
||||
"size err rx_cmd_a=0x%08x\n",
|
||||
rx_cmd_a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unlikely(rx_cmd_a & RX_CMD_A_RED_)) {
|
||||
netif_dbg(dev, rx_err, dev->net,
|
||||
"Error rx_cmd_a=0x%08x", rx_cmd_a);
|
||||
} else {
|
||||
u32 frame_len = size - ETH_FCS_LEN;
|
||||
u32 frame_len;
|
||||
struct sk_buff *skb2;
|
||||
|
||||
if (unlikely(size < ETH_FCS_LEN)) {
|
||||
netif_dbg(dev, rx_err, dev->net,
|
||||
"size err rx_cmd_a=0x%08x\n",
|
||||
rx_cmd_a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
frame_len = size - ETH_FCS_LEN;
|
||||
|
||||
skb2 = napi_alloc_skb(&dev->napi, frame_len);
|
||||
if (!skb2)
|
||||
return 0;
|
||||
|
@ -61,12 +61,6 @@ pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
|
||||
val, index, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
pl_clear_QuickLink_features(struct usbnet *dev, int val)
|
||||
{
|
||||
return pl_vendor_req(dev, 1, (u8) val, 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
pl_set_QuickLink_features(struct usbnet *dev, int val)
|
||||
{
|
||||
|
@ -1833,6 +1833,12 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
||||
size = (u16)((header & RX_STS_FL_) >> 16);
|
||||
align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
|
||||
|
||||
if (unlikely(size > skb->len)) {
|
||||
netif_dbg(dev, rx_err, dev->net,
|
||||
"size err header=0x%08x\n", header);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unlikely(header & RX_STS_ES_)) {
|
||||
netif_dbg(dev, rx_err, dev->net,
|
||||
"Error header=0x%08x\n", header);
|
||||
|
@ -1642,7 +1642,7 @@ static int veth_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
|
||||
struct veth_xdp_buff *_ctx = (void *)ctx;
|
||||
|
||||
if (!_ctx->skb)
|
||||
return -EOPNOTSUPP;
|
||||
return -ENODATA;
|
||||
|
||||
*timestamp = skb_hwtstamps(_ctx->skb)->hwtstamp;
|
||||
return 0;
|
||||
@ -1653,7 +1653,7 @@ static int veth_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
|
||||
struct veth_xdp_buff *_ctx = (void *)ctx;
|
||||
|
||||
if (!_ctx->skb)
|
||||
return -EOPNOTSUPP;
|
||||
return -ENODATA;
|
||||
|
||||
*hash = skb_get_hash(_ctx->skb);
|
||||
return 0;
|
||||
|
@ -732,7 +732,10 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
|
||||
|
||||
rcu_read_lock();
|
||||
do {
|
||||
while (likely(!mvmtxq->stopped &&
|
||||
while (likely(!test_bit(IWL_MVM_TXQ_STATE_STOP_FULL,
|
||||
&mvmtxq->state) &&
|
||||
!test_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT,
|
||||
&mvmtxq->state) &&
|
||||
!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))) {
|
||||
skb = ieee80211_tx_dequeue(hw, txq);
|
||||
|
||||
@ -757,42 +760,25 @@ static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
|
||||
|
||||
/*
|
||||
* Please note that racing is handled very carefully here:
|
||||
* mvmtxq->txq_id is updated during allocation, and mvmtxq->list is
|
||||
* deleted afterwards.
|
||||
* This means that if:
|
||||
* mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list):
|
||||
* queue is allocated and we can TX.
|
||||
* mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list):
|
||||
* a race, should defer the frame.
|
||||
* mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list):
|
||||
* need to allocate the queue and defer the frame.
|
||||
* mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list):
|
||||
* queue is already scheduled for allocation, no need to allocate,
|
||||
* should defer the frame.
|
||||
*/
|
||||
|
||||
/* If the queue is allocated TX and return. */
|
||||
if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) {
|
||||
/*
|
||||
* Check that list is empty to avoid a race where txq_id is
|
||||
* already updated, but the queue allocation work wasn't
|
||||
* finished
|
||||
*/
|
||||
if (unlikely(txq->sta && !list_empty(&mvmtxq->list)))
|
||||
return;
|
||||
|
||||
if (likely(test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) ||
|
||||
!txq->sta) {
|
||||
iwl_mvm_mac_itxq_xmit(hw, txq);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The list is being deleted only after the queue is fully allocated. */
|
||||
if (!list_empty(&mvmtxq->list))
|
||||
return;
|
||||
/* iwl_mvm_mac_itxq_xmit() will later be called by the worker
|
||||
* to handle any packets we leave on the txq now
|
||||
*/
|
||||
|
||||
list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
|
||||
schedule_work(&mvm->add_stream_wk);
|
||||
spin_lock_bh(&mvm->add_stream_lock);
|
||||
/* The list is being deleted only after the queue is fully allocated. */
|
||||
if (list_empty(&mvmtxq->list) &&
|
||||
/* recheck under lock */
|
||||
!test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) {
|
||||
list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
|
||||
schedule_work(&mvm->add_stream_wk);
|
||||
}
|
||||
spin_unlock_bh(&mvm->add_stream_lock);
|
||||
}
|
||||
|
||||
#define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...) \
|
||||
|
@ -729,7 +729,10 @@ struct iwl_mvm_txq {
|
||||
struct list_head list;
|
||||
u16 txq_id;
|
||||
atomic_t tx_request;
|
||||
bool stopped;
|
||||
#define IWL_MVM_TXQ_STATE_STOP_FULL 0
|
||||
#define IWL_MVM_TXQ_STATE_STOP_REDIRECT 1
|
||||
#define IWL_MVM_TXQ_STATE_READY 2
|
||||
unsigned long state;
|
||||
};
|
||||
|
||||
static inline struct iwl_mvm_txq *
|
||||
@ -827,6 +830,7 @@ struct iwl_mvm {
|
||||
struct iwl_mvm_tvqm_txq_info tvqm_info[IWL_MAX_TVQM_QUEUES];
|
||||
};
|
||||
struct work_struct add_stream_wk; /* To add streams to queues */
|
||||
spinlock_t add_stream_lock;
|
||||
|
||||
const char *nvm_file_name;
|
||||
struct iwl_nvm_data *nvm_data;
|
||||
|
@ -1195,6 +1195,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
|
||||
INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
|
||||
INIT_LIST_HEAD(&mvm->add_stream_txqs);
|
||||
spin_lock_init(&mvm->add_stream_lock);
|
||||
|
||||
init_waitqueue_head(&mvm->rx_sync_waitq);
|
||||
|
||||
@ -1691,7 +1692,10 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
|
||||
|
||||
txq = sta->txq[tid];
|
||||
mvmtxq = iwl_mvm_txq_from_mac80211(txq);
|
||||
mvmtxq->stopped = !start;
|
||||
if (start)
|
||||
clear_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
|
||||
else
|
||||
set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
|
||||
|
||||
if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
|
||||
iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
|
||||
|
@ -384,8 +384,11 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
struct iwl_mvm_txq *mvmtxq =
|
||||
iwl_mvm_txq_from_tid(sta, tid);
|
||||
|
||||
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
|
||||
spin_lock_bh(&mvm->add_stream_lock);
|
||||
list_del_init(&mvmtxq->list);
|
||||
clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
|
||||
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
|
||||
spin_unlock_bh(&mvm->add_stream_lock);
|
||||
}
|
||||
|
||||
/* Regardless if this is a reserved TXQ for a STA - mark it as false */
|
||||
@ -479,8 +482,11 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
|
||||
disable_agg_tids |= BIT(tid);
|
||||
mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE;
|
||||
|
||||
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
|
||||
spin_lock_bh(&mvm->add_stream_lock);
|
||||
list_del_init(&mvmtxq->list);
|
||||
clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
|
||||
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
|
||||
spin_unlock_bh(&mvm->add_stream_lock);
|
||||
}
|
||||
|
||||
mvmsta->tfd_queue_msk &= ~BIT(queue); /* Don't use this queue anymore */
|
||||
@ -693,7 +699,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
|
||||
queue, iwl_mvm_ac_to_tx_fifo[ac]);
|
||||
|
||||
/* Stop the queue and wait for it to empty */
|
||||
txq->stopped = true;
|
||||
set_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
|
||||
|
||||
ret = iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(queue));
|
||||
if (ret) {
|
||||
@ -736,7 +742,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
|
||||
|
||||
out:
|
||||
/* Continue using the queue */
|
||||
txq->stopped = false;
|
||||
clear_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1444,12 +1450,22 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
|
||||
* a queue in the function itself.
|
||||
*/
|
||||
if (iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid)) {
|
||||
spin_lock_bh(&mvm->add_stream_lock);
|
||||
list_del_init(&mvmtxq->list);
|
||||
spin_unlock_bh(&mvm->add_stream_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
list_del_init(&mvmtxq->list);
|
||||
/* now we're ready, any remaining races/concurrency will be
|
||||
* handled in iwl_mvm_mac_itxq_xmit()
|
||||
*/
|
||||
set_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
|
||||
|
||||
local_bh_disable();
|
||||
spin_lock(&mvm->add_stream_lock);
|
||||
list_del_init(&mvmtxq->list);
|
||||
spin_unlock(&mvm->add_stream_lock);
|
||||
|
||||
iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
|
||||
local_bh_enable();
|
||||
}
|
||||
@ -1864,8 +1880,11 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_txq *mvmtxq =
|
||||
iwl_mvm_txq_from_mac80211(sta->txq[i]);
|
||||
|
||||
spin_lock_bh(&mvm->add_stream_lock);
|
||||
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
|
||||
list_del_init(&mvmtxq->list);
|
||||
clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
|
||||
spin_unlock_bh(&mvm->add_stream_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8997 = {
|
||||
.can_ext_scan = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id mwifiex_pcie_of_match_table[] = {
|
||||
static const struct of_device_id mwifiex_pcie_of_match_table[] __maybe_unused = {
|
||||
{ .compatible = "pci11ab,2b42" },
|
||||
{ .compatible = "pci1b4b,2b42" },
|
||||
{ }
|
||||
|
@ -495,7 +495,7 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = {
|
||||
{"EXTLAST", NULL, 0, 0xFE},
|
||||
};
|
||||
|
||||
static const struct of_device_id mwifiex_sdio_of_match_table[] = {
|
||||
static const struct of_device_id mwifiex_sdio_of_match_table[] __maybe_unused = {
|
||||
{ .compatible = "marvell,sd8787" },
|
||||
{ .compatible = "marvell,sd8897" },
|
||||
{ .compatible = "marvell,sd8978" },
|
||||
|
@ -539,6 +539,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_bit(MT76_STATE_REGISTERED, &phy->state);
|
||||
phy->dev->phys[phy->band_idx] = phy;
|
||||
|
||||
return 0;
|
||||
@ -549,6 +550,9 @@ void mt76_unregister_phy(struct mt76_phy *phy)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
|
||||
if (!test_bit(MT76_STATE_REGISTERED, &phy->state))
|
||||
return;
|
||||
|
||||
if (IS_ENABLED(CONFIG_MT76_LEDS))
|
||||
mt76_led_cleanup(phy);
|
||||
mt76_tx_status_check(dev, true);
|
||||
@ -719,6 +723,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
return ret;
|
||||
|
||||
WARN_ON(mt76_worker_setup(hw, &dev->tx_worker, NULL, "tx"));
|
||||
set_bit(MT76_STATE_REGISTERED, &phy->state);
|
||||
sched_set_fifo_low(dev->tx_worker.task);
|
||||
|
||||
return 0;
|
||||
@ -729,6 +734,9 @@ void mt76_unregister_device(struct mt76_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = dev->hw;
|
||||
|
||||
if (!test_bit(MT76_STATE_REGISTERED, &dev->phy.state))
|
||||
return;
|
||||
|
||||
if (IS_ENABLED(CONFIG_MT76_LEDS))
|
||||
mt76_led_cleanup(&dev->phy);
|
||||
mt76_tx_status_check(dev, true);
|
||||
|
@ -402,6 +402,7 @@ struct mt76_tx_cb {
|
||||
|
||||
enum {
|
||||
MT76_STATE_INITIALIZED,
|
||||
MT76_STATE_REGISTERED,
|
||||
MT76_STATE_RUNNING,
|
||||
MT76_STATE_MCU_RUNNING,
|
||||
MT76_SCANNING,
|
||||
|
@ -1221,6 +1221,9 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba_tlv);
|
||||
|
||||
int mt76_connac_mcu_sta_wed_update(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
if (!mt76_is_mmio(dev))
|
||||
return 0;
|
||||
|
||||
if (!mtk_wed_device_active(&dev->mmio.wed))
|
||||
return 0;
|
||||
|
||||
|
@ -383,7 +383,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
||||
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
|
||||
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
||||
|
||||
hw->max_tx_fragments = 4;
|
||||
|
||||
@ -396,6 +395,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
||||
}
|
||||
|
||||
if (phy->mt76->cap.has_5ghz) {
|
||||
struct ieee80211_sta_vht_cap *vht_cap;
|
||||
|
||||
vht_cap = &phy->mt76->sband_5g.sband.vht_cap;
|
||||
phy->mt76->sband_5g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
@ -403,19 +405,28 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
||||
IEEE80211_HT_MPDU_DENSITY_4;
|
||||
|
||||
if (is_mt7915(&dev->mt76)) {
|
||||
phy->mt76->sband_5g.sband.vht_cap.cap |=
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
|
||||
if (!dev->dbdc_support)
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
|
||||
FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);
|
||||
} else {
|
||||
phy->mt76->sband_5g.sband.vht_cap.cap |=
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
|
||||
/* mt7916 dbdc with 2g 2x2 bw40 and 5g 2x2 bw160c */
|
||||
phy->mt76->sband_5g.sband.vht_cap.cap |=
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
|
||||
}
|
||||
|
||||
if (!is_mt7915(&dev->mt76) || !dev->dbdc_support)
|
||||
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
||||
}
|
||||
|
||||
mt76_set_stream_caps(phy->mt76, true);
|
||||
@ -841,9 +852,13 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
|
||||
int sts = hweight8(phy->mt76->chainmask);
|
||||
u8 c, sts_160 = sts;
|
||||
|
||||
/* mt7915 doesn't support bw160 */
|
||||
if (is_mt7915(&dev->mt76))
|
||||
sts_160 = 0;
|
||||
/* Can do 1/2 of STS in 160Mhz mode for mt7915 */
|
||||
if (is_mt7915(&dev->mt76)) {
|
||||
if (!dev->dbdc_support)
|
||||
sts_160 /= 2;
|
||||
else
|
||||
sts_160 = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
if (vif == NL80211_IFTYPE_MESH_POINT)
|
||||
@ -944,10 +959,15 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask);
|
||||
u16 mcs_map = 0;
|
||||
u16 mcs_map_160 = 0;
|
||||
u8 nss_160 = nss;
|
||||
u8 nss_160;
|
||||
|
||||
/* Can't do 160MHz with mt7915 */
|
||||
if (is_mt7915(&dev->mt76))
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
nss_160 = nss;
|
||||
else if (!dev->dbdc_support)
|
||||
/* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
|
||||
nss_160 = nss / 2;
|
||||
else
|
||||
/* Can't do 160MHz with mt7915 dbdc */
|
||||
nss_160 = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
|
@ -9,7 +9,14 @@
|
||||
#include <linux/phy.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACPI_MDIO)
|
||||
int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode);
|
||||
int __acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode,
|
||||
struct module *owner);
|
||||
|
||||
static inline int
|
||||
acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *handle)
|
||||
{
|
||||
return __acpi_mdiobus_register(mdio, handle, THIS_MODULE);
|
||||
}
|
||||
#else /* CONFIG_ACPI_MDIO */
|
||||
static inline int
|
||||
acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
|
||||
|
@ -14,9 +14,25 @@
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF_MDIO)
|
||||
bool of_mdiobus_child_is_phy(struct device_node *child);
|
||||
int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np);
|
||||
int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
|
||||
struct device_node *np);
|
||||
int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,
|
||||
struct module *owner);
|
||||
|
||||
static inline int of_mdiobus_register(struct mii_bus *mdio,
|
||||
struct device_node *np)
|
||||
{
|
||||
return __of_mdiobus_register(mdio, np, THIS_MODULE);
|
||||
}
|
||||
|
||||
int __devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
|
||||
struct device_node *np, struct module *owner);
|
||||
|
||||
static inline int devm_of_mdiobus_register(struct device *dev,
|
||||
struct mii_bus *mdio,
|
||||
struct device_node *np)
|
||||
{
|
||||
return __devm_of_mdiobus_register(dev, mdio, np, THIS_MODULE);
|
||||
}
|
||||
|
||||
struct mdio_device *of_mdio_find_device(struct device_node *np);
|
||||
struct phy_device *of_phy_find_device(struct device_node *phy_np);
|
||||
struct phy_device *
|
||||
|
@ -215,7 +215,7 @@ struct plat_stmmacenet_data {
|
||||
int unicast_filter_entries;
|
||||
int tx_fifo_size;
|
||||
int rx_fifo_size;
|
||||
u32 addr64;
|
||||
u32 host_dma_width;
|
||||
u32 rx_queues_to_use;
|
||||
u32 tx_queues_to_use;
|
||||
u8 rx_sched_algorithm;
|
||||
|
@ -1613,6 +1613,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn);
|
||||
void hci_conn_del_sysfs(struct hci_conn *conn);
|
||||
|
||||
#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
|
||||
#define GET_HCIDEV_DEV(hdev) ((hdev)->dev.parent)
|
||||
|
||||
/* ----- LMP capabilities ----- */
|
||||
#define lmp_encrypt_capable(dev) ((dev)->features[0][0] & LMP_ENCRYPT)
|
||||
|
@ -972,7 +972,7 @@ static int __init bpf_jit_charge_init(void)
|
||||
{
|
||||
/* Only used as heuristic here to derive limit. */
|
||||
bpf_jit_limit_max = bpf_jit_alloc_exec_limit();
|
||||
bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 2,
|
||||
bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 1,
|
||||
PAGE_SIZE), LONG_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
@ -3826,6 +3826,8 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
||||
continue;
|
||||
if (type == STACK_MISC)
|
||||
continue;
|
||||
if (type == STACK_INVALID && env->allow_uninit_stack)
|
||||
continue;
|
||||
verbose(env, "invalid read from stack off %d+%d size %d\n",
|
||||
off, i, size);
|
||||
return -EACCES;
|
||||
@ -3863,6 +3865,8 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
||||
continue;
|
||||
if (type == STACK_ZERO)
|
||||
continue;
|
||||
if (type == STACK_INVALID && env->allow_uninit_stack)
|
||||
continue;
|
||||
verbose(env, "invalid read from stack off %d+%d size %d\n",
|
||||
off, i, size);
|
||||
return -EACCES;
|
||||
@ -5754,7 +5758,8 @@ static int check_stack_range_initialized(
|
||||
stype = &state->stack[spi].slot_type[slot % BPF_REG_SIZE];
|
||||
if (*stype == STACK_MISC)
|
||||
goto mark;
|
||||
if (*stype == STACK_ZERO) {
|
||||
if ((*stype == STACK_ZERO) ||
|
||||
(*stype == STACK_INVALID && env->allow_uninit_stack)) {
|
||||
if (clobber) {
|
||||
/* helper can write anything into the stack */
|
||||
*stype = STACK_MISC;
|
||||
@ -13936,6 +13941,10 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old,
|
||||
if (old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_INVALID)
|
||||
continue;
|
||||
|
||||
if (env->allow_uninit_stack &&
|
||||
old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_MISC)
|
||||
continue;
|
||||
|
||||
/* explored stack has more populated slots than current stack
|
||||
* and these slots were used
|
||||
*/
|
||||
|
@ -2871,10 +2871,25 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
|
||||
hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
|
||||
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
|
||||
hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) {
|
||||
switch (hci_skb_pkt_type(skb)) {
|
||||
case HCI_EVENT_PKT:
|
||||
break;
|
||||
case HCI_ACLDATA_PKT:
|
||||
/* Detect if ISO packet has been sent as ACL */
|
||||
if (hci_conn_num(hdev, ISO_LINK)) {
|
||||
__u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
|
||||
__u8 type;
|
||||
|
||||
type = hci_conn_lookup_type(hdev, hci_handle(handle));
|
||||
if (type == ISO_LINK)
|
||||
hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
|
||||
}
|
||||
break;
|
||||
case HCI_SCODATA_PKT:
|
||||
break;
|
||||
case HCI_ISODATA_PKT:
|
||||
break;
|
||||
default:
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -643,6 +643,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
|
||||
cancel_work_sync(&hdev->cmd_sync_work);
|
||||
cancel_work_sync(&hdev->reenable_adv_work);
|
||||
|
||||
mutex_lock(&hdev->cmd_sync_work_lock);
|
||||
list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
|
||||
if (entry->destroy)
|
||||
entry->destroy(hdev, entry->data, -ECANCELED);
|
||||
@ -650,6 +651,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
|
||||
list_del(&entry->list);
|
||||
kfree(entry);
|
||||
}
|
||||
mutex_unlock(&hdev->cmd_sync_work_lock);
|
||||
}
|
||||
|
||||
void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
|
||||
@ -2367,6 +2369,45 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hci_pause_addr_resolution(struct hci_dev *hdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!use_ll_privacy(hdev))
|
||||
return 0;
|
||||
|
||||
if (!hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION))
|
||||
return 0;
|
||||
|
||||
/* Cannot disable addr resolution if scanning is enabled or
|
||||
* when initiating an LE connection.
|
||||
*/
|
||||
if (hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
|
||||
hci_lookup_le_connect(hdev)) {
|
||||
bt_dev_err(hdev, "Command not allowed when scan/LE connect");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* Cannot disable addr resolution if advertising is enabled. */
|
||||
err = hci_pause_advertising_sync(hdev);
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "Pause advertising failed: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00);
|
||||
if (err)
|
||||
bt_dev_err(hdev, "Unable to disable Address Resolution: %d",
|
||||
err);
|
||||
|
||||
/* Return if address resolution is disabled and RPA is not used. */
|
||||
if (!err && scan_use_rpa(hdev))
|
||||
return err;
|
||||
|
||||
hci_resume_advertising_sync(hdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,
|
||||
bool extended, struct sock *sk)
|
||||
{
|
||||
@ -2402,7 +2443,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
|
||||
u8 filter_policy;
|
||||
int err;
|
||||
|
||||
/* Pause advertising if resolving list can be used as controllers are
|
||||
/* Pause advertising if resolving list can be used as controllers
|
||||
* cannot accept resolving list modifications while advertising.
|
||||
*/
|
||||
if (use_ll_privacy(hdev)) {
|
||||
@ -3319,6 +3360,7 @@ static const struct hci_init_stage amp_init1[] = {
|
||||
HCI_INIT(hci_read_flow_control_mode_sync),
|
||||
/* HCI_OP_READ_LOCATION_DATA */
|
||||
HCI_INIT(hci_read_location_data_sync),
|
||||
{}
|
||||
};
|
||||
|
||||
static int hci_init1_sync(struct hci_dev *hdev)
|
||||
@ -3353,6 +3395,7 @@ static int hci_init1_sync(struct hci_dev *hdev)
|
||||
static const struct hci_init_stage amp_init2[] = {
|
||||
/* HCI_OP_READ_LOCAL_FEATURES */
|
||||
HCI_INIT(hci_read_local_features_sync),
|
||||
{}
|
||||
};
|
||||
|
||||
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
|
||||
@ -5394,27 +5437,12 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
|
||||
|
||||
cancel_interleave_scan(hdev);
|
||||
|
||||
/* Pause advertising since active scanning disables address resolution
|
||||
* which advertising depend on in order to generate its RPAs.
|
||||
/* Pause address resolution for active scan and stop advertising if
|
||||
* privacy is enabled.
|
||||
*/
|
||||
if (use_ll_privacy(hdev) && hci_dev_test_flag(hdev, HCI_PRIVACY)) {
|
||||
err = hci_pause_advertising_sync(hdev);
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "pause advertising failed: %d", err);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable address resolution while doing active scanning since the
|
||||
* accept list shall not be used and all reports shall reach the host
|
||||
* anyway.
|
||||
*/
|
||||
err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00);
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "Unable to disable Address Resolution: %d",
|
||||
err);
|
||||
err = hci_pause_addr_resolution(hdev);
|
||||
if (err)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* All active scans will be done with either a resolvable private
|
||||
* address (when privacy feature has been enabled) or non-resolvable
|
||||
|
@ -1620,7 +1620,6 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
|
||||
void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
|
||||
{
|
||||
struct iso_conn *conn = hcon->iso_data;
|
||||
struct hci_iso_data_hdr *hdr;
|
||||
__u16 pb, ts, len;
|
||||
|
||||
if (!conn)
|
||||
@ -1642,6 +1641,8 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
|
||||
}
|
||||
|
||||
if (ts) {
|
||||
struct hci_iso_ts_data_hdr *hdr;
|
||||
|
||||
/* TODO: add timestamp to the packet? */
|
||||
hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
|
||||
if (!hdr) {
|
||||
@ -1649,15 +1650,19 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
|
||||
goto drop;
|
||||
}
|
||||
|
||||
len = __le16_to_cpu(hdr->slen);
|
||||
} else {
|
||||
struct hci_iso_data_hdr *hdr;
|
||||
|
||||
hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
|
||||
if (!hdr) {
|
||||
BT_ERR("Frame is too short (len %d)", skb->len);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
len = __le16_to_cpu(hdr->slen);
|
||||
}
|
||||
|
||||
len = __le16_to_cpu(hdr->slen);
|
||||
flags = hci_iso_data_flags(len);
|
||||
len = hci_iso_data_len(len);
|
||||
|
||||
|
@ -708,6 +708,17 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l2cap_chan_del);
|
||||
|
||||
static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id,
|
||||
l2cap_chan_func_t func, void *data)
|
||||
{
|
||||
struct l2cap_chan *chan, *l;
|
||||
|
||||
list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
|
||||
if (chan->ident == id)
|
||||
func(chan, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
|
||||
void *data)
|
||||
{
|
||||
@ -775,23 +786,9 @@ static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
|
||||
|
||||
static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
|
||||
{
|
||||
struct l2cap_conn *conn = chan->conn;
|
||||
struct l2cap_ecred_conn_rsp rsp;
|
||||
u16 result;
|
||||
|
||||
if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
|
||||
result = L2CAP_CR_LE_AUTHORIZATION;
|
||||
else
|
||||
result = L2CAP_CR_LE_BAD_PSM;
|
||||
|
||||
l2cap_state_change(chan, BT_DISCONN);
|
||||
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
|
||||
rsp.result = cpu_to_le16(result);
|
||||
|
||||
l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
|
||||
&rsp);
|
||||
__l2cap_ecred_conn_rsp_defer(chan);
|
||||
}
|
||||
|
||||
static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
|
||||
@ -846,7 +843,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
|
||||
break;
|
||||
case L2CAP_MODE_EXT_FLOWCTL:
|
||||
l2cap_chan_ecred_connect_reject(chan);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3938,43 +3935,86 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
|
||||
&rsp);
|
||||
}
|
||||
|
||||
void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
|
||||
static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data)
|
||||
{
|
||||
struct {
|
||||
struct l2cap_ecred_conn_rsp rsp;
|
||||
__le16 dcid[5];
|
||||
} __packed pdu;
|
||||
struct l2cap_conn *conn = chan->conn;
|
||||
u16 ident = chan->ident;
|
||||
int i = 0;
|
||||
int *result = data;
|
||||
|
||||
if (!ident)
|
||||
if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
|
||||
return;
|
||||
|
||||
BT_DBG("chan %p ident %d", chan, ident);
|
||||
|
||||
pdu.rsp.mtu = cpu_to_le16(chan->imtu);
|
||||
pdu.rsp.mps = cpu_to_le16(chan->mps);
|
||||
pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
|
||||
pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
|
||||
|
||||
mutex_lock(&conn->chan_lock);
|
||||
|
||||
list_for_each_entry(chan, &conn->chan_l, list) {
|
||||
if (chan->ident != ident)
|
||||
continue;
|
||||
|
||||
/* Reset ident so only one response is sent */
|
||||
chan->ident = 0;
|
||||
|
||||
/* Include all channels pending with the same ident */
|
||||
pdu.dcid[i++] = cpu_to_le16(chan->scid);
|
||||
switch (chan->state) {
|
||||
case BT_CONNECT2:
|
||||
/* If channel still pending accept add to result */
|
||||
(*result)++;
|
||||
return;
|
||||
case BT_CONNECTED:
|
||||
return;
|
||||
default:
|
||||
/* If not connected or pending accept it has been refused */
|
||||
*result = -ECONNREFUSED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&conn->chan_lock);
|
||||
struct l2cap_ecred_rsp_data {
|
||||
struct {
|
||||
struct l2cap_ecred_conn_rsp rsp;
|
||||
__le16 scid[L2CAP_ECRED_MAX_CID];
|
||||
} __packed pdu;
|
||||
int count;
|
||||
};
|
||||
|
||||
l2cap_send_cmd(conn, ident, L2CAP_ECRED_CONN_RSP,
|
||||
sizeof(pdu.rsp) + i * sizeof(__le16), &pdu);
|
||||
static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
|
||||
{
|
||||
struct l2cap_ecred_rsp_data *rsp = data;
|
||||
|
||||
if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
|
||||
return;
|
||||
|
||||
/* Reset ident so only one response is sent */
|
||||
chan->ident = 0;
|
||||
|
||||
/* Include all channels pending with the same ident */
|
||||
if (!rsp->pdu.rsp.result)
|
||||
rsp->pdu.rsp.dcid[rsp->count++] = cpu_to_le16(chan->scid);
|
||||
else
|
||||
l2cap_chan_del(chan, ECONNRESET);
|
||||
}
|
||||
|
||||
void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
|
||||
{
|
||||
struct l2cap_conn *conn = chan->conn;
|
||||
struct l2cap_ecred_rsp_data data;
|
||||
u16 id = chan->ident;
|
||||
int result = 0;
|
||||
|
||||
if (!id)
|
||||
return;
|
||||
|
||||
BT_DBG("chan %p id %d", chan, id);
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
data.pdu.rsp.mtu = cpu_to_le16(chan->imtu);
|
||||
data.pdu.rsp.mps = cpu_to_le16(chan->mps);
|
||||
data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
|
||||
data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
|
||||
|
||||
/* Verify that all channels are ready */
|
||||
__l2cap_chan_list_id(conn, id, l2cap_ecred_list_defer, &result);
|
||||
|
||||
if (result > 0)
|
||||
return;
|
||||
|
||||
if (result < 0)
|
||||
data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_AUTHORIZATION);
|
||||
|
||||
/* Build response */
|
||||
__l2cap_chan_list_id(conn, id, l2cap_ecred_rsp_defer, &data);
|
||||
|
||||
l2cap_send_cmd(conn, id, L2CAP_ECRED_CONN_RSP,
|
||||
sizeof(data.pdu.rsp) + (data.count * sizeof(__le16)),
|
||||
&data.pdu);
|
||||
}
|
||||
|
||||
void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
|
||||
@ -6078,6 +6118,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
|
||||
__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
|
||||
|
||||
chan->ident = cmd->ident;
|
||||
chan->mode = L2CAP_MODE_EXT_FLOWCTL;
|
||||
|
||||
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
|
||||
l2cap_state_change(chan, BT_CONNECT2);
|
||||
|
@ -4639,12 +4639,6 @@ static int set_mgmt_mesh_func(struct sock *sk, struct hci_dev *hdev,
|
||||
MGMT_OP_SET_EXP_FEATURE,
|
||||
MGMT_STATUS_INVALID_INDEX);
|
||||
|
||||
/* Changes can only be made when controller is powered down */
|
||||
if (hdev_is_powered(hdev))
|
||||
return mgmt_cmd_status(sk, hdev->id,
|
||||
MGMT_OP_SET_EXP_FEATURE,
|
||||
MGMT_STATUS_REJECTED);
|
||||
|
||||
/* Parameters are limited to a single octet */
|
||||
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
|
||||
return mgmt_cmd_status(sk, hdev->id,
|
||||
@ -9363,7 +9357,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
|
||||
{ add_ext_adv_data, MGMT_ADD_EXT_ADV_DATA_SIZE,
|
||||
HCI_MGMT_VAR_LEN },
|
||||
{ add_adv_patterns_monitor_rssi,
|
||||
MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE },
|
||||
MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE,
|
||||
HCI_MGMT_VAR_LEN },
|
||||
{ set_mesh, MGMT_SET_MESH_RECEIVER_SIZE,
|
||||
HCI_MGMT_VAR_LEN },
|
||||
{ mesh_features, MGMT_MESH_READ_FEATURES_SIZE },
|
||||
|
@ -720,7 +720,10 @@ __diag_ignore_all("-Wmissing-prototypes",
|
||||
* @ctx: XDP context pointer.
|
||||
* @timestamp: Return value pointer.
|
||||
*
|
||||
* Returns 0 on success or ``-errno`` on error.
|
||||
* Return:
|
||||
* * Returns 0 on success or ``-errno`` on error.
|
||||
* * ``-EOPNOTSUPP`` : means device driver does not implement kfunc
|
||||
* * ``-ENODATA`` : means no RX-timestamp available for this frame
|
||||
*/
|
||||
__bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
|
||||
{
|
||||
@ -732,7 +735,10 @@ __bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *tim
|
||||
* @ctx: XDP context pointer.
|
||||
* @hash: Return value pointer.
|
||||
*
|
||||
* Returns 0 on success or ``-errno`` on error.
|
||||
* Return:
|
||||
* * Returns 0 on success or ``-errno`` on error.
|
||||
* * ``-EOPNOTSUPP`` : means device driver doesn't implement kfunc
|
||||
* * ``-ENODATA`` : means no RX-hash available for this frame
|
||||
*/
|
||||
__bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash)
|
||||
{
|
||||
|
@ -114,7 +114,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
skb = nskb;
|
||||
}
|
||||
|
||||
dev_sw_netstats_rx_add(skb->dev, skb->len);
|
||||
dev_sw_netstats_rx_add(skb->dev, skb->len + ETH_HLEN);
|
||||
|
||||
if (dsa_skb_defer_rx_timestamp(p, skb))
|
||||
return 0;
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/dsa/brcm.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@ -252,6 +253,7 @@ static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
|
||||
static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
int len = BRCM_LEG_TAG_LEN;
|
||||
int source_port;
|
||||
u8 *brcm_tag;
|
||||
|
||||
@ -266,12 +268,16 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
|
||||
if (!skb->dev)
|
||||
return NULL;
|
||||
|
||||
/* VLAN tag is added by BCM63xx internal switch */
|
||||
if (netdev_uses_dsa(skb->dev))
|
||||
len += VLAN_HLEN;
|
||||
|
||||
/* Remove Broadcom tag and update checksum */
|
||||
skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
|
||||
skb_pull_rcsum(skb, len);
|
||||
|
||||
dsa_default_offload_fwd_mark(skb);
|
||||
|
||||
dsa_strip_etype_header(skb, BRCM_LEG_TAG_LEN);
|
||||
dsa_strip_etype_header(skb, len);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
@ -552,7 +552,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
truncate = true;
|
||||
}
|
||||
|
||||
nhoff = skb_network_header(skb) - skb_mac_header(skb);
|
||||
nhoff = skb_network_offset(skb);
|
||||
if (skb->protocol == htons(ETH_P_IP) &&
|
||||
(ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
|
||||
truncate = true;
|
||||
@ -561,7 +561,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
int thoff;
|
||||
|
||||
if (skb_transport_header_was_set(skb))
|
||||
thoff = skb_transport_header(skb) - skb_mac_header(skb);
|
||||
thoff = skb_transport_offset(skb);
|
||||
else
|
||||
thoff = nhoff + sizeof(struct ipv6hdr);
|
||||
if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
|
||||
|
@ -959,7 +959,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
|
||||
truncate = true;
|
||||
}
|
||||
|
||||
nhoff = skb_network_header(skb) - skb_mac_header(skb);
|
||||
nhoff = skb_network_offset(skb);
|
||||
if (skb->protocol == htons(ETH_P_IP) &&
|
||||
(ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
|
||||
truncate = true;
|
||||
@ -968,7 +968,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
|
||||
int thoff;
|
||||
|
||||
if (skb_transport_header_was_set(skb))
|
||||
thoff = skb_transport_header(skb) - skb_mac_header(skb);
|
||||
thoff = skb_transport_offset(skb);
|
||||
else
|
||||
thoff = nhoff + sizeof(struct ipv6hdr);
|
||||
if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
|
||||
|
@ -1284,6 +1284,9 @@ struct ieee80211_local {
|
||||
struct list_head active_txqs[IEEE80211_NUM_ACS];
|
||||
u16 schedule_round[IEEE80211_NUM_ACS];
|
||||
|
||||
/* serializes ieee80211_handle_wake_tx_queue */
|
||||
spinlock_t handle_wake_tx_queue_lock;
|
||||
|
||||
u16 airtime_flags;
|
||||
u32 aql_txq_limit_low[IEEE80211_NUM_ACS];
|
||||
u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
|
||||
|
@ -802,6 +802,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
||||
local->aql_threshold = IEEE80211_AQL_THRESHOLD;
|
||||
atomic_set(&local->aql_total_pending_airtime, 0);
|
||||
|
||||
spin_lock_init(&local->handle_wake_tx_queue_lock);
|
||||
|
||||
INIT_LIST_HEAD(&local->chanctx_list);
|
||||
mutex_init(&local->chanctx_mtx);
|
||||
|
||||
|
@ -2765,17 +2765,6 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta
|
||||
mesh_rmc_check(sdata, eth->h_source, mesh_hdr))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
/* Frame has reached destination. Don't forward */
|
||||
if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
|
||||
goto rx_accept;
|
||||
|
||||
if (!ifmsh->mshcfg.dot11MeshForwarding) {
|
||||
if (is_multicast_ether_addr(eth->h_dest))
|
||||
goto rx_accept;
|
||||
|
||||
return RX_DROP_MONITOR;
|
||||
}
|
||||
|
||||
/* forward packet */
|
||||
if (sdata->crypto_tx_tailroom_needed_cnt)
|
||||
tailroom = IEEE80211_ENCRYPT_TAILROOM;
|
||||
@ -2814,6 +2803,17 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/* Frame has reached destination. Don't forward */
|
||||
if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
|
||||
goto rx_accept;
|
||||
|
||||
if (!ifmsh->mshcfg.dot11MeshForwarding) {
|
||||
if (is_multicast_ether_addr(eth->h_dest))
|
||||
goto rx_accept;
|
||||
|
||||
return RX_DROP_MONITOR;
|
||||
}
|
||||
|
||||
skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
|
||||
|
||||
ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control,
|
||||
|
@ -314,6 +314,8 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
|
||||
struct ieee80211_txq *queue;
|
||||
|
||||
spin_lock(&local->handle_wake_tx_queue_lock);
|
||||
|
||||
/* Use ieee80211_next_txq() for airtime fairness accounting */
|
||||
ieee80211_txq_schedule_start(hw, txq->ac);
|
||||
while ((queue = ieee80211_next_txq(hw, txq->ac))) {
|
||||
@ -321,6 +323,7 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
ieee80211_return_txq(hw, queue, false);
|
||||
}
|
||||
ieee80211_txq_schedule_end(hw, txq->ac);
|
||||
spin_unlock(&local->handle_wake_tx_queue_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
|
||||
|
||||
|
@ -147,6 +147,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
|
||||
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta, struct sk_buff *skb)
|
||||
{
|
||||
const struct ethhdr *eth = (void *)skb->data;
|
||||
struct mac80211_qos_map *qos_map;
|
||||
bool qos;
|
||||
|
||||
@ -154,8 +155,9 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
|
||||
skb_get_hash(skb);
|
||||
|
||||
/* all mesh/ocb stations are required to support WME */
|
||||
if (sta && (sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
|
||||
sdata->vif.type == NL80211_IFTYPE_OCB))
|
||||
if ((sdata->vif.type == NL80211_IFTYPE_MESH_POINT &&
|
||||
!is_multicast_ether_addr(eth->h_dest)) ||
|
||||
(sdata->vif.type == NL80211_IFTYPE_OCB && sta))
|
||||
qos = true;
|
||||
else if (sta)
|
||||
qos = sta->sta.wme;
|
||||
|
@ -150,10 +150,11 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)
|
||||
|
||||
static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
|
||||
{
|
||||
u32 npgs_rem, chunk_size = mr->chunk_size, headroom = mr->headroom;
|
||||
bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG;
|
||||
u64 npgs, addr = mr->addr, size = mr->len;
|
||||
unsigned int chunks, chunks_rem;
|
||||
u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
|
||||
u64 addr = mr->addr, size = mr->len;
|
||||
u32 chunks_rem, npgs_rem;
|
||||
u64 chunks, npgs;
|
||||
int err;
|
||||
|
||||
if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
|
||||
@ -188,8 +189,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
|
||||
if (npgs > U32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
chunks = (unsigned int)div_u64_rem(size, chunk_size, &chunks_rem);
|
||||
if (chunks == 0)
|
||||
chunks = div_u64_rem(size, chunk_size, &chunks_rem);
|
||||
if (!chunks || chunks > U32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (!unaligned_chunks && chunks_rem)
|
||||
@ -202,7 +203,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
|
||||
umem->headroom = headroom;
|
||||
umem->chunk_size = chunk_size;
|
||||
umem->chunks = chunks;
|
||||
umem->npgs = (u32)npgs;
|
||||
umem->npgs = npgs;
|
||||
umem->pgs = NULL;
|
||||
umem->user = NULL;
|
||||
umem->flags = mr->flags;
|
||||
|
@ -20,8 +20,8 @@
|
||||
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
||||
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
||||
|
||||
/* prevent accidental re-addition of reallocarray()/strlcpy() */
|
||||
#pragma GCC poison reallocarray strlcpy
|
||||
/* prevent accidental re-addition of reallocarray() */
|
||||
#pragma GCC poison reallocarray
|
||||
|
||||
#include "libbpf.h"
|
||||
#include "btf.h"
|
||||
|
@ -200,7 +200,7 @@ def _genl_msg(nl_type, nl_flags, genl_cmd, genl_version, seq=None):
|
||||
if seq is None:
|
||||
seq = random.randint(1, 1024)
|
||||
nlmsg = struct.pack("HHII", nl_type, nl_flags, seq, 0)
|
||||
genlmsg = struct.pack("bbH", genl_cmd, genl_version, 0)
|
||||
genlmsg = struct.pack("BBH", genl_cmd, genl_version, 0)
|
||||
return nlmsg + genlmsg
|
||||
|
||||
|
||||
@ -264,7 +264,7 @@ class GenlMsg:
|
||||
self.hdr = nl_msg.raw[0:4]
|
||||
self.raw = nl_msg.raw[4:]
|
||||
|
||||
self.genl_cmd, self.genl_version, _ = struct.unpack("bbH", self.hdr)
|
||||
self.genl_cmd, self.genl_version, _ = struct.unpack("BBH", self.hdr)
|
||||
|
||||
self.raw_attrs = NlAttrs(self.raw)
|
||||
|
||||
@ -358,7 +358,7 @@ class YnlFamily(SpecFamily):
|
||||
raw >>= 1
|
||||
i += 1
|
||||
else:
|
||||
value = enum['entries'][raw - i]
|
||||
value = enum.entries_by_val[raw - i].name
|
||||
rsp[attr_spec['name']] = value
|
||||
|
||||
def _decode(self, attrs, space):
|
||||
|
9
tools/testing/selftests/bpf/prog_tests/uninit_stack.c
Normal file
9
tools/testing/selftests/bpf/prog_tests/uninit_stack.c
Normal file
@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <test_progs.h>
|
||||
#include "uninit_stack.skel.h"
|
||||
|
||||
void test_uninit_stack(void)
|
||||
{
|
||||
RUN_TESTS(uninit_stack);
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
/* Copyright (c) 2021 Facebook */
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#define vm_flags vm_start
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
|
@ -5,12 +5,10 @@
|
||||
#include <errno.h>
|
||||
#include <linux/capability.h>
|
||||
|
||||
struct kernel_cap_struct {
|
||||
__u64 val;
|
||||
} __attribute__((preserve_access_index));
|
||||
typedef struct { unsigned long long val; } kernel_cap_t;
|
||||
|
||||
struct cred {
|
||||
struct kernel_cap_struct cap_effective;
|
||||
kernel_cap_t cap_effective;
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
@ -18,8 +16,8 @@ char _license[] SEC("license") = "GPL";
|
||||
SEC("lsm.s/userns_create")
|
||||
int BPF_PROG(test_userns_create, const struct cred *cred, int ret)
|
||||
{
|
||||
struct kernel_cap_struct caps = cred->cap_effective;
|
||||
__u64 cap_mask = BIT_LL(CAP_SYS_ADMIN);
|
||||
kernel_cap_t caps = cred->cap_effective;
|
||||
__u64 cap_mask = 1ULL << CAP_SYS_ADMIN;
|
||||
|
||||
if (ret)
|
||||
return 0;
|
||||
|
@ -5,12 +5,12 @@
|
||||
#include "bpf_misc.h"
|
||||
|
||||
struct Small {
|
||||
int x;
|
||||
long x;
|
||||
};
|
||||
|
||||
struct Big {
|
||||
int x;
|
||||
int y;
|
||||
long x;
|
||||
long y;
|
||||
};
|
||||
|
||||
__noinline int foo(const struct Big *big)
|
||||
@ -22,7 +22,7 @@ __noinline int foo(const struct Big *big)
|
||||
}
|
||||
|
||||
SEC("cgroup_skb/ingress")
|
||||
__failure __msg("invalid indirect read from stack")
|
||||
__failure __msg("invalid indirect access to stack")
|
||||
int global_func10(struct __sk_buff *skb)
|
||||
{
|
||||
const struct Small small = {.x = skb->len };
|
||||
|
87
tools/testing/selftests/bpf/progs/uninit_stack.c
Normal file
87
tools/testing/selftests/bpf/progs/uninit_stack.c
Normal file
@ -0,0 +1,87 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include "bpf_misc.h"
|
||||
|
||||
/* Read an uninitialized value from stack at a fixed offset */
|
||||
SEC("socket")
|
||||
__naked int read_uninit_stack_fixed_off(void *ctx)
|
||||
{
|
||||
asm volatile (" \
|
||||
r0 = 0; \
|
||||
/* force stack depth to be 128 */ \
|
||||
*(u64*)(r10 - 128) = r1; \
|
||||
r1 = *(u8 *)(r10 - 8 ); \
|
||||
r0 += r1; \
|
||||
r1 = *(u8 *)(r10 - 11); \
|
||||
r1 = *(u8 *)(r10 - 13); \
|
||||
r1 = *(u8 *)(r10 - 15); \
|
||||
r1 = *(u16*)(r10 - 16); \
|
||||
r1 = *(u32*)(r10 - 32); \
|
||||
r1 = *(u64*)(r10 - 64); \
|
||||
/* read from a spill of a wrong size, it is a separate \
|
||||
* branch in check_stack_read_fixed_off() \
|
||||
*/ \
|
||||
*(u32*)(r10 - 72) = r1; \
|
||||
r1 = *(u64*)(r10 - 72); \
|
||||
r0 = 0; \
|
||||
exit; \
|
||||
"
|
||||
::: __clobber_all);
|
||||
}
|
||||
|
||||
/* Read an uninitialized value from stack at a variable offset */
|
||||
SEC("socket")
|
||||
__naked int read_uninit_stack_var_off(void *ctx)
|
||||
{
|
||||
asm volatile (" \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
/* force stack depth to be 64 */ \
|
||||
*(u64*)(r10 - 64) = r0; \
|
||||
r0 = -r0; \
|
||||
/* give r0 a range [-31, -1] */ \
|
||||
if r0 s<= -32 goto exit_%=; \
|
||||
if r0 s>= 0 goto exit_%=; \
|
||||
/* access stack using r0 */ \
|
||||
r1 = r10; \
|
||||
r1 += r0; \
|
||||
r2 = *(u8*)(r1 + 0); \
|
||||
exit_%=: r0 = 0; \
|
||||
exit; \
|
||||
"
|
||||
:
|
||||
: __imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
static __noinline void dummy(void) {}
|
||||
|
||||
/* Pass a pointer to uninitialized stack memory to a helper.
|
||||
* Passed memory block should be marked as STACK_MISC after helper call.
|
||||
*/
|
||||
SEC("socket")
|
||||
__log_level(7) __msg("fp-104=mmmmmmmm")
|
||||
__naked int helper_uninit_to_misc(void *ctx)
|
||||
{
|
||||
asm volatile (" \
|
||||
/* force stack depth to be 128 */ \
|
||||
*(u64*)(r10 - 128) = r1; \
|
||||
r1 = r10; \
|
||||
r1 += -128; \
|
||||
r2 = 32; \
|
||||
call %[bpf_trace_printk]; \
|
||||
/* Call to dummy() forces print_verifier_state(..., true), \
|
||||
* thus showing the stack state, matched by __msg(). \
|
||||
*/ \
|
||||
call %[dummy]; \
|
||||
r0 = 0; \
|
||||
exit; \
|
||||
"
|
||||
:
|
||||
: __imm(bpf_trace_printk),
|
||||
__imm(dummy)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
@ -2221,19 +2221,22 @@
|
||||
* that fp-8 stack slot was unused in the fall-through
|
||||
* branch and will accept the program incorrectly
|
||||
*/
|
||||
BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 2, 2),
|
||||
BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
|
||||
BPF_JMP_IMM(BPF_JGT, BPF_REG_0, 2, 2),
|
||||
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
||||
BPF_JMP_IMM(BPF_JA, 0, 0, 0),
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
||||
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_map_hash_48b = { 6 },
|
||||
.errstr = "invalid indirect read from stack R2 off -8+0 size 8",
|
||||
.result = REJECT,
|
||||
.prog_type = BPF_PROG_TYPE_XDP,
|
||||
.fixup_map_hash_48b = { 7 },
|
||||
.errstr_unpriv = "invalid indirect read from stack R2 off -8+0 size 8",
|
||||
.result_unpriv = REJECT,
|
||||
/* in privileged mode reads from uninitialized stack locations are permitted */
|
||||
.result = ACCEPT,
|
||||
},
|
||||
{
|
||||
"calls: ctx read at start of subprog",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user