mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 11:33:28 +02:00
Including fixes from netfilter, wireless and Bluetooth.
We're reverting the removal of a Sundance driver, a user has appeared.
This makes the PR rather large in terms of LoC.
There's a conspicuous absence of real, user-reported 6.17 issues.
Slightly worried that the summer distracted people from testing.
Previous releases - regressions:
- ax25: properly unshare skbs in ax25_kiss_rcv()
Previous releases - always broken:
- phylink: disable autoneg for interfaces that have no inband,
fix regression on pcs-lynx (NXP LS1088)
- vxlan: fix null-deref when using nexthop objects
- batman-adv: fix OOB read/write in network-coding decode
- icmp: icmp_ndo_send: fix reversing address translation for replies
- tcp: fix socket ref leak in TCP-AO failure handling for IPv6
- mctp:
- mctp_fraq_queue should take ownership of passed skb
- usb: initialise mac header in RX path, avoid WARN
- wifi: mac80211: do not permit 40 MHz EHT operation on 5/6 GHz,
respect device limitations
- wifi: wilc1000: avoid buffer overflow in WID string configuration
- wifi: mt76:
- fix regressions from mt7996 MLO support rework
- fix offchannel handling issues on mt7996
- fix multiple wcid linked list corruption issues
- mt7921: don't disconnect when AP requests switch to a channel which
requires radar detection
- mt7925u: use connac3 tx aggr check in tx complete
- wifi: intel:
- improve validation of ACPI DSM data
- cfg: restore some 1000 series configs
- wifi: ath:
- ath11k: a fix for GTK rekeying
- ath12k: a missed WiFi7 capability (multi-link EMLSR)
- eth: intel:
- ice: fix races in "low latency" firmware interface for Tx timestamps
- idpf: set mac type when adding and removing MAC filters
- i40e: remove racy read access to some debugfs files
Misc:
- Revert "eth: remove the DLink/Sundance (ST201) driver"
- netfilter: conntrack: helper: Replace -EEXIST by -EBUSY, avoid confusing
modprobe
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmi5tR8ACgkQMUZtbf5S
Irt/dA//YtVjqx/qVRADORDq2CF2SZk7P4Kcanci5gI36tP+7yVYOoJyGm1SFfSp
MSv5Oxqn2U37we34FBgaIbkPOc6Bg1ZDDlzgs/RzGYzNbz9mZkYMHry0kJ8bjbeA
c6tlOKJu49wG82K/3eMXRFQFUJZS0TeMEfZMGoqcKU8ziHC6+XpUzXj1IqBbTU/+
C6JLGzpWnWHI0o97rscnRF4w1h2tl5FF1eBV6MiIJzP1nuBuK7bDkwbGvA5DdBOr
nqWdi6iSfGwb/4XYMKeRMNucYSsZOwAt9DYAxlPb2AXhpKSO31OjZ1qp3e5Uhg4u
n6Oj3q9tPNBitSqizZOAftay7xZJtXISpuFVm2pijgAz0G2SITvx7Z0kPKDw7rXa
S6ZSmBhlamj/6uaOmmmIyG7zqMXarLKVCh6C+tU/+vCYVb1YhC5fcIU1QML68FxX
9YfJFOf6Fn/j68MtRdknB5pnEfh0acMcKgie5b0725KBbRPM0/QlpLL5vj4UXZD5
3yxpgQbgciU3HiYBDJM1vWwF0Z3Y89YDtZqjUavnrnrxRv+BkzTmGlmNuqICKm3f
rUCjdNm8TDPUwKgSLeUbXF2u8Aapgizd7ptXcmKT2mbjSKdhqdvafUnrdPZaBZBA
uKH0XLNezj2zxcQaTEVdV5mtDujZMoXPS/RnCrICaMfXkz5Whxg=
=e0Jg
-----END PGP SIGNATURE-----
Merge tag 'net-6.17-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Including fixes from netfilter, wireless and Bluetooth.
We're reverting the removal of a Sundance driver, a user has appeared.
This makes the PR rather large in terms of LoC.
There's a conspicuous absence of real, user-reported 6.17 issues.
Slightly worried that the summer distracted people from testing.
Previous releases - regressions:
- ax25: properly unshare skbs in ax25_kiss_rcv()
Previous releases - always broken:
- phylink: disable autoneg for interfaces that have no inband, fix
regression on pcs-lynx (NXP LS1088)
- vxlan: fix null-deref when using nexthop objects
- batman-adv: fix OOB read/write in network-coding decode
- icmp: icmp_ndo_send: fix reversing address translation for replies
- tcp: fix socket ref leak in TCP-AO failure handling for IPv6
- mctp:
- mctp_fraq_queue should take ownership of passed skb
- usb: initialise mac header in RX path, avoid WARN
- wifi: mac80211: do not permit 40 MHz EHT operation on 5/6 GHz,
respect device limitations
- wifi: wilc1000: avoid buffer overflow in WID string configuration
- wifi: mt76:
- fix regressions from mt7996 MLO support rework
- fix offchannel handling issues on mt7996
- fix multiple wcid linked list corruption issues
- mt7921: don't disconnect when AP requests switch to a channel
which requires radar detection
- mt7925u: use connac3 tx aggr check in tx complete
- wifi: intel:
- improve validation of ACPI DSM data
- cfg: restore some 1000 series configs
- wifi: ath:
- ath11k: a fix for GTK rekeying
- ath12k: a missed WiFi7 capability (multi-link EMLSR)
- eth: intel:
- ice: fix races in "low latency" firmware interface for Tx timestamps
- idpf: set mac type when adding and removing MAC filters
- i40e: remove racy read access to some debugfs files
Misc:
- Revert "eth: remove the DLink/Sundance (ST201) driver"
- netfilter: conntrack: helper: Replace -EEXIST by -EBUSY, avoid
confusing modprobe"
* tag 'net-6.17-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (99 commits)
phy: mscc: Stop taking ts_lock for tx_queue and use its own lock
selftest: net: Fix weird setsockopt() in bind_bhash.c.
MAINTAINERS: add Sabrina to TLS maintainers
gve: update MAINTAINERS
ppp: fix memory leak in pad_compress_skb
net: xilinx: axienet: Add error handling for RX metadata pointer retrieval
net: atm: fix memory leak in atm_register_sysfs when device_register fail
netfilter: nf_tables: Introduce NFTA_DEVICE_PREFIX
selftests: netfilter: fix udpclash tool hang
ax25: properly unshare skbs in ax25_kiss_rcv()
mctp: return -ENOPROTOOPT for unknown getsockopt options
net/smc: Remove validation of reserved bits in CLC Decline message
ipv4: Fix NULL vs error pointer check in inet_blackhole_dev_init()
net: thunder_bgx: decrement cleanup index before use
net: thunder_bgx: add a missing of_node_put
net: phylink: move PHY interrupt request to non-fail path
net: lockless sock_i_ino()
tools: ynl-gen: fix nested array counting
wifi: wilc1000: avoid buffer overflow in WID string configuration
wifi: cfg80211: sme: cap SSID length in __cfg80211_connect_result()
...
This commit is contained in:
commit
d69eb204c2
|
|
@ -433,9 +433,8 @@ Threaded NAPI
|
|||
|
||||
Threaded NAPI is an operating mode that uses dedicated kernel
|
||||
threads rather than software IRQ context for NAPI processing.
|
||||
The configuration is per netdevice and will affect all
|
||||
NAPI instances of that device. Each NAPI instance will spawn a separate
|
||||
thread (called ``napi/${ifc-name}-${napi-id}``).
|
||||
Each threaded NAPI instance will spawn a separate thread
|
||||
(called ``napi/${ifc-name}-${napi-id}``).
|
||||
|
||||
It is recommended to pin each kernel thread to a single CPU, the same
|
||||
CPU as the CPU which services the interrupt. Note that the mapping
|
||||
|
|
|
|||
|
|
@ -10389,7 +10389,7 @@ S: Maintained
|
|||
F: drivers/input/touchscreen/goodix*
|
||||
|
||||
GOOGLE ETHERNET DRIVERS
|
||||
M: Jeroen de Borst <jeroendb@google.com>
|
||||
M: Joshua Washington <joshwash@google.com>
|
||||
M: Harshitha Ramamurthy <hramamurthy@google.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
@ -17851,6 +17851,7 @@ F: net/ipv6/tcp*.c
|
|||
NETWORKING [TLS]
|
||||
M: John Fastabend <john.fastabend@gmail.com>
|
||||
M: Jakub Kicinski <kuba@kernel.org>
|
||||
M: Sabrina Dubroca <sd@queasysnail.net>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: include/net/tls.h
|
||||
|
|
@ -24253,6 +24254,12 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
|
||||
F: drivers/input/keyboard/sun4i-lradc-keys.c
|
||||
|
||||
SUNDANCE NETWORK DRIVER
|
||||
M: Denis Kirjanov <dkirjanov@suse.de>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/dlink/sundance.c
|
||||
|
||||
SUNPLUS ETHERNET DRIVER
|
||||
M: Wells Lu <wellslutw@gmail.com>
|
||||
L: netdev@vger.kernel.org
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ CONFIG_DM9102=m
|
|||
CONFIG_ULI526X=m
|
||||
CONFIG_PCMCIA_XIRCOM=m
|
||||
CONFIG_DL2K=m
|
||||
CONFIG_SUNDANCE=m
|
||||
CONFIG_PCMCIA_FMVJ18X=m
|
||||
CONFIG_E100=m
|
||||
CONFIG_E1000=m
|
||||
|
|
|
|||
|
|
@ -433,6 +433,7 @@ CONFIG_DM9102=m
|
|||
CONFIG_ULI526X=m
|
||||
CONFIG_PCMCIA_XIRCOM=m
|
||||
CONFIG_DL2K=m
|
||||
CONFIG_SUNDANCE=m
|
||||
CONFIG_S2IO=m
|
||||
CONFIG_FEC_MPC52xx=m
|
||||
CONFIG_GIANFAR=m
|
||||
|
|
|
|||
|
|
@ -380,6 +380,28 @@ static const struct file_operations force_devcoredump_fops = {
|
|||
.write = force_devcd_write,
|
||||
};
|
||||
|
||||
static void vhci_debugfs_init(struct vhci_data *data)
|
||||
{
|
||||
struct hci_dev *hdev = data->hdev;
|
||||
|
||||
debugfs_create_file("force_suspend", 0644, hdev->debugfs, data,
|
||||
&force_suspend_fops);
|
||||
|
||||
debugfs_create_file("force_wakeup", 0644, hdev->debugfs, data,
|
||||
&force_wakeup_fops);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MSFTEXT))
|
||||
debugfs_create_file("msft_opcode", 0644, hdev->debugfs, data,
|
||||
&msft_opcode_fops);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_AOSPEXT))
|
||||
debugfs_create_file("aosp_capable", 0644, hdev->debugfs, data,
|
||||
&aosp_capable_fops);
|
||||
|
||||
debugfs_create_file("force_devcoredump", 0644, hdev->debugfs, data,
|
||||
&force_devcoredump_fops);
|
||||
}
|
||||
|
||||
static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
|
|
@ -434,22 +456,8 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
debugfs_create_file("force_suspend", 0644, hdev->debugfs, data,
|
||||
&force_suspend_fops);
|
||||
|
||||
debugfs_create_file("force_wakeup", 0644, hdev->debugfs, data,
|
||||
&force_wakeup_fops);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MSFTEXT))
|
||||
debugfs_create_file("msft_opcode", 0644, hdev->debugfs, data,
|
||||
&msft_opcode_fops);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_AOSPEXT))
|
||||
debugfs_create_file("aosp_capable", 0644, hdev->debugfs, data,
|
||||
&aosp_capable_fops);
|
||||
|
||||
debugfs_create_file("force_devcoredump", 0644, hdev->debugfs, data,
|
||||
&force_devcoredump_fops);
|
||||
if (!IS_ERR_OR_NULL(hdev->debugfs))
|
||||
vhci_debugfs_init(data);
|
||||
|
||||
hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
|
||||
|
||||
|
|
@ -651,6 +659,21 @@ static int vhci_open(struct inode *inode, struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void vhci_debugfs_remove(struct hci_dev *hdev)
|
||||
{
|
||||
debugfs_lookup_and_remove("force_suspend", hdev->debugfs);
|
||||
|
||||
debugfs_lookup_and_remove("force_wakeup", hdev->debugfs);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MSFTEXT))
|
||||
debugfs_lookup_and_remove("msft_opcode", hdev->debugfs);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_AOSPEXT))
|
||||
debugfs_lookup_and_remove("aosp_capable", hdev->debugfs);
|
||||
|
||||
debugfs_lookup_and_remove("force_devcoredump", hdev->debugfs);
|
||||
}
|
||||
|
||||
static int vhci_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct vhci_data *data = file->private_data;
|
||||
|
|
@ -662,6 +685,8 @@ static int vhci_release(struct inode *inode, struct file *file)
|
|||
hdev = data->hdev;
|
||||
|
||||
if (hdev) {
|
||||
if (!IS_ERR_OR_NULL(hdev->debugfs))
|
||||
vhci_debugfs_remove(hdev);
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,14 +51,14 @@ void dsp_hwec_enable(struct dsp *dsp, const char *arg)
|
|||
goto _do;
|
||||
|
||||
{
|
||||
char *dup, *tok, *name, *val;
|
||||
char *dup, *next, *tok, *name, *val;
|
||||
int tmp;
|
||||
|
||||
dup = kstrdup(arg, GFP_ATOMIC);
|
||||
dup = next = kstrdup(arg, GFP_ATOMIC);
|
||||
if (!dup)
|
||||
return;
|
||||
|
||||
while ((tok = strsep(&dup, ","))) {
|
||||
while ((tok = strsep(&next, ","))) {
|
||||
if (!strlen(tok))
|
||||
continue;
|
||||
name = strsep(&tok, "=");
|
||||
|
|
|
|||
|
|
@ -779,7 +779,8 @@ int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip *chip, int port)
|
|||
continue;
|
||||
if (led_num > 1) {
|
||||
dev_err(dev, "invalid LED specified port %d\n", port);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_put_led;
|
||||
}
|
||||
|
||||
if (led_num == 0)
|
||||
|
|
@ -823,17 +824,25 @@ int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip *chip, int port)
|
|||
init_data.devname_mandatory = true;
|
||||
init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d:0%d", chip->info->name,
|
||||
port, led_num);
|
||||
if (!init_data.devicename)
|
||||
return -ENOMEM;
|
||||
if (!init_data.devicename) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put_led;
|
||||
}
|
||||
|
||||
ret = devm_led_classdev_register_ext(dev, l, &init_data);
|
||||
kfree(init_data.devicename);
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to init LED %d for port %d", led_num, port);
|
||||
return ret;
|
||||
goto err_put_led;
|
||||
}
|
||||
}
|
||||
|
||||
fwnode_handle_put(leds);
|
||||
return 0;
|
||||
|
||||
err_put_led:
|
||||
fwnode_handle_put(led);
|
||||
fwnode_handle_put(leds);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4397,7 +4397,7 @@ static void bnxt_alloc_one_rx_ring_netmem(struct bnxt *bp,
|
|||
for (i = 0; i < bp->rx_agg_ring_size; i++) {
|
||||
if (bnxt_alloc_rx_netmem(bp, rxr, prod, GFP_KERNEL)) {
|
||||
netdev_warn(bp->dev, "init'ed rx ring %d with %d/%d pages only\n",
|
||||
ring_nr, i, bp->rx_ring_size);
|
||||
ring_nr, i, bp->rx_agg_ring_size);
|
||||
break;
|
||||
}
|
||||
prod = NEXT_RX_AGG(prod);
|
||||
|
|
|
|||
|
|
@ -1223,12 +1223,13 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)
|
|||
{
|
||||
struct macb *bp = queue->bp;
|
||||
u16 queue_index = queue - bp->queues;
|
||||
unsigned long flags;
|
||||
unsigned int tail;
|
||||
unsigned int head;
|
||||
int packets = 0;
|
||||
u32 bytes = 0;
|
||||
|
||||
spin_lock(&queue->tx_ptr_lock);
|
||||
spin_lock_irqsave(&queue->tx_ptr_lock, flags);
|
||||
head = queue->tx_head;
|
||||
for (tail = queue->tx_tail; tail != head && packets < budget; tail++) {
|
||||
struct macb_tx_skb *tx_skb;
|
||||
|
|
@ -1291,7 +1292,7 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)
|
|||
CIRC_CNT(queue->tx_head, queue->tx_tail,
|
||||
bp->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp))
|
||||
netif_wake_subqueue(bp->dev, queue_index);
|
||||
spin_unlock(&queue->tx_ptr_lock);
|
||||
spin_unlock_irqrestore(&queue->tx_ptr_lock, flags);
|
||||
|
||||
return packets;
|
||||
}
|
||||
|
|
@ -1707,8 +1708,9 @@ static void macb_tx_restart(struct macb_queue *queue)
|
|||
{
|
||||
struct macb *bp = queue->bp;
|
||||
unsigned int head_idx, tbqp;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&queue->tx_ptr_lock);
|
||||
spin_lock_irqsave(&queue->tx_ptr_lock, flags);
|
||||
|
||||
if (queue->tx_head == queue->tx_tail)
|
||||
goto out_tx_ptr_unlock;
|
||||
|
|
@ -1720,19 +1722,20 @@ static void macb_tx_restart(struct macb_queue *queue)
|
|||
if (tbqp == head_idx)
|
||||
goto out_tx_ptr_unlock;
|
||||
|
||||
spin_lock_irq(&bp->lock);
|
||||
spin_lock(&bp->lock);
|
||||
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
|
||||
spin_unlock_irq(&bp->lock);
|
||||
spin_unlock(&bp->lock);
|
||||
|
||||
out_tx_ptr_unlock:
|
||||
spin_unlock(&queue->tx_ptr_lock);
|
||||
spin_unlock_irqrestore(&queue->tx_ptr_lock, flags);
|
||||
}
|
||||
|
||||
static bool macb_tx_complete_pending(struct macb_queue *queue)
|
||||
{
|
||||
bool retval = false;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&queue->tx_ptr_lock);
|
||||
spin_lock_irqsave(&queue->tx_ptr_lock, flags);
|
||||
if (queue->tx_head != queue->tx_tail) {
|
||||
/* Make hw descriptor updates visible to CPU */
|
||||
rmb();
|
||||
|
|
@ -1740,7 +1743,7 @@ static bool macb_tx_complete_pending(struct macb_queue *queue)
|
|||
if (macb_tx_desc(queue, queue->tx_tail)->ctrl & MACB_BIT(TX_USED))
|
||||
retval = true;
|
||||
}
|
||||
spin_unlock(&queue->tx_ptr_lock);
|
||||
spin_unlock_irqrestore(&queue->tx_ptr_lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -2308,6 +2311,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
struct macb_queue *queue = &bp->queues[queue_index];
|
||||
unsigned int desc_cnt, nr_frags, frag_size, f;
|
||||
unsigned int hdrlen;
|
||||
unsigned long flags;
|
||||
bool is_lso;
|
||||
netdev_tx_t ret = NETDEV_TX_OK;
|
||||
|
||||
|
|
@ -2368,7 +2372,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
desc_cnt += DIV_ROUND_UP(frag_size, bp->max_tx_length);
|
||||
}
|
||||
|
||||
spin_lock_bh(&queue->tx_ptr_lock);
|
||||
spin_lock_irqsave(&queue->tx_ptr_lock, flags);
|
||||
|
||||
/* This is a hard error, log it. */
|
||||
if (CIRC_SPACE(queue->tx_head, queue->tx_tail,
|
||||
|
|
@ -2392,15 +2396,15 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
netdev_tx_sent_queue(netdev_get_tx_queue(bp->dev, queue_index),
|
||||
skb->len);
|
||||
|
||||
spin_lock_irq(&bp->lock);
|
||||
spin_lock(&bp->lock);
|
||||
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
|
||||
spin_unlock_irq(&bp->lock);
|
||||
spin_unlock(&bp->lock);
|
||||
|
||||
if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1)
|
||||
netif_stop_subqueue(dev, queue_index);
|
||||
|
||||
unlock:
|
||||
spin_unlock_bh(&queue->tx_ptr_lock);
|
||||
spin_unlock_irqrestore(&queue->tx_ptr_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1493,13 +1493,17 @@ static int bgx_init_of_phy(struct bgx *bgx)
|
|||
* this cortina phy, for which there is no driver
|
||||
* support, ignore it.
|
||||
*/
|
||||
if (phy_np &&
|
||||
!of_device_is_compatible(phy_np, "cortina,cs4223-slice")) {
|
||||
/* Wait until the phy drivers are available */
|
||||
pd = of_phy_find_device(phy_np);
|
||||
if (!pd)
|
||||
goto defer;
|
||||
bgx->lmac[lmac].phydev = pd;
|
||||
if (phy_np) {
|
||||
if (!of_device_is_compatible(phy_np, "cortina,cs4223-slice")) {
|
||||
/* Wait until the phy drivers are available */
|
||||
pd = of_phy_find_device(phy_np);
|
||||
if (!pd) {
|
||||
of_node_put(phy_np);
|
||||
goto defer;
|
||||
}
|
||||
bgx->lmac[lmac].phydev = pd;
|
||||
}
|
||||
of_node_put(phy_np);
|
||||
}
|
||||
|
||||
lmac++;
|
||||
|
|
@ -1515,11 +1519,11 @@ static int bgx_init_of_phy(struct bgx *bgx)
|
|||
* for phy devices we may have already found.
|
||||
*/
|
||||
while (lmac) {
|
||||
lmac--;
|
||||
if (bgx->lmac[lmac].phydev) {
|
||||
put_device(&bgx->lmac[lmac].phydev->mdio.dev);
|
||||
bgx->lmac[lmac].phydev = NULL;
|
||||
}
|
||||
lmac--;
|
||||
}
|
||||
of_node_put(node);
|
||||
return -EPROBE_DEFER;
|
||||
|
|
|
|||
|
|
@ -32,4 +32,24 @@ config DL2K
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called dl2k.
|
||||
|
||||
config SUNDANCE
|
||||
tristate "Sundance Alta support"
|
||||
depends on PCI
|
||||
select CRC32
|
||||
select MII
|
||||
help
|
||||
This driver is for the Sundance "Alta" chip.
|
||||
More specific information and updates are available from
|
||||
<http://www.scyld.com/network/sundance.html>.
|
||||
|
||||
config SUNDANCE_MMIO
|
||||
bool "Use MMIO instead of PIO"
|
||||
depends on SUNDANCE
|
||||
help
|
||||
Enable memory-mapped I/O for interaction with Sundance NIC registers.
|
||||
Do NOT enable this by default, PIO (enabled when MMIO is disabled)
|
||||
is known to solve bugs on certain chips.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
endif # NET_VENDOR_DLINK
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_DL2K) += dl2k.o
|
||||
obj-$(CONFIG_SUNDANCE) += sundance.o
|
||||
|
|
|
|||
1990
drivers/net/ethernet/dlink/sundance.c
Normal file
1990
drivers/net/ethernet/dlink/sundance.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -549,12 +549,12 @@ static int e1000_set_eeprom(struct net_device *netdev,
|
|||
{
|
||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
size_t total_len, max_len;
|
||||
u16 *eeprom_buff;
|
||||
void *ptr;
|
||||
int max_len;
|
||||
int ret_val = 0;
|
||||
int first_word;
|
||||
int last_word;
|
||||
int ret_val = 0;
|
||||
void *ptr;
|
||||
u16 i;
|
||||
|
||||
if (eeprom->len == 0)
|
||||
|
|
@ -569,6 +569,10 @@ static int e1000_set_eeprom(struct net_device *netdev,
|
|||
|
||||
max_len = hw->nvm.word_size * 2;
|
||||
|
||||
if (check_add_overflow(eeprom->offset, eeprom->len, &total_len) ||
|
||||
total_len > max_len)
|
||||
return -EFBIG;
|
||||
|
||||
first_word = eeprom->offset >> 1;
|
||||
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
|
||||
eeprom_buff = kmalloc(max_len, GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -359,8 +359,8 @@ static void i40e_client_add_instance(struct i40e_pf *pf)
|
|||
if (i40e_client_get_params(vsi, &cdev->lan_info.params))
|
||||
goto free_cdev;
|
||||
|
||||
mac = list_first_entry(&cdev->lan_info.netdev->dev_addrs.list,
|
||||
struct netdev_hw_addr, list);
|
||||
mac = list_first_entry_or_null(&cdev->lan_info.netdev->dev_addrs.list,
|
||||
struct netdev_hw_addr, list);
|
||||
if (mac)
|
||||
ether_addr_copy(cdev->lan_info.lanmac, mac->addr);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -40,48 +40,6 @@ static struct i40e_vsi *i40e_dbg_find_vsi(struct i40e_pf *pf, int seid)
|
|||
* setup, adding or removing filters, or other things. Many of
|
||||
* these will be useful for some forms of unit testing.
|
||||
**************************************************************/
|
||||
static char i40e_dbg_command_buf[256] = "";
|
||||
|
||||
/**
|
||||
* i40e_dbg_command_read - read for command datum
|
||||
* @filp: the opened file
|
||||
* @buffer: where to write the data for the user to read
|
||||
* @count: the size of the user's buffer
|
||||
* @ppos: file position offset
|
||||
**/
|
||||
static ssize_t i40e_dbg_command_read(struct file *filp, char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct i40e_pf *pf = filp->private_data;
|
||||
struct i40e_vsi *main_vsi;
|
||||
int bytes_not_copied;
|
||||
int buf_size = 256;
|
||||
char *buf;
|
||||
int len;
|
||||
|
||||
/* don't allow partial reads */
|
||||
if (*ppos != 0)
|
||||
return 0;
|
||||
if (count < buf_size)
|
||||
return -ENOSPC;
|
||||
|
||||
buf = kzalloc(buf_size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOSPC;
|
||||
|
||||
main_vsi = i40e_pf_get_main_vsi(pf);
|
||||
len = snprintf(buf, buf_size, "%s: %s\n", main_vsi->netdev->name,
|
||||
i40e_dbg_command_buf);
|
||||
|
||||
bytes_not_copied = copy_to_user(buffer, buf, len);
|
||||
kfree(buf);
|
||||
|
||||
if (bytes_not_copied)
|
||||
return -EFAULT;
|
||||
|
||||
*ppos = len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static char *i40e_filter_state_string[] = {
|
||||
"INVALID",
|
||||
|
|
@ -1621,7 +1579,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
|
|||
static const struct file_operations i40e_dbg_command_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = i40e_dbg_command_read,
|
||||
.write = i40e_dbg_command_write,
|
||||
};
|
||||
|
||||
|
|
@ -1630,48 +1587,6 @@ static const struct file_operations i40e_dbg_command_fops = {
|
|||
* The netdev_ops entry in debugfs is for giving the driver commands
|
||||
* to be executed from the netdev operations.
|
||||
**************************************************************/
|
||||
static char i40e_dbg_netdev_ops_buf[256] = "";
|
||||
|
||||
/**
|
||||
* i40e_dbg_netdev_ops_read - read for netdev_ops datum
|
||||
* @filp: the opened file
|
||||
* @buffer: where to write the data for the user to read
|
||||
* @count: the size of the user's buffer
|
||||
* @ppos: file position offset
|
||||
**/
|
||||
static ssize_t i40e_dbg_netdev_ops_read(struct file *filp, char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct i40e_pf *pf = filp->private_data;
|
||||
struct i40e_vsi *main_vsi;
|
||||
int bytes_not_copied;
|
||||
int buf_size = 256;
|
||||
char *buf;
|
||||
int len;
|
||||
|
||||
/* don't allow partal reads */
|
||||
if (*ppos != 0)
|
||||
return 0;
|
||||
if (count < buf_size)
|
||||
return -ENOSPC;
|
||||
|
||||
buf = kzalloc(buf_size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOSPC;
|
||||
|
||||
main_vsi = i40e_pf_get_main_vsi(pf);
|
||||
len = snprintf(buf, buf_size, "%s: %s\n", main_vsi->netdev->name,
|
||||
i40e_dbg_netdev_ops_buf);
|
||||
|
||||
bytes_not_copied = copy_to_user(buffer, buf, len);
|
||||
kfree(buf);
|
||||
|
||||
if (bytes_not_copied)
|
||||
return -EFAULT;
|
||||
|
||||
*ppos = len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dbg_netdev_ops_write - write into netdev_ops datum
|
||||
|
|
@ -1685,35 +1600,36 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct i40e_pf *pf = filp->private_data;
|
||||
char *cmd_buf, *buf_tmp;
|
||||
int bytes_not_copied;
|
||||
struct i40e_vsi *vsi;
|
||||
char *buf_tmp;
|
||||
int vsi_seid;
|
||||
int i, cnt;
|
||||
|
||||
/* don't allow partial writes */
|
||||
if (*ppos != 0)
|
||||
return 0;
|
||||
if (count >= sizeof(i40e_dbg_netdev_ops_buf))
|
||||
return -ENOSPC;
|
||||
|
||||
memset(i40e_dbg_netdev_ops_buf, 0, sizeof(i40e_dbg_netdev_ops_buf));
|
||||
bytes_not_copied = copy_from_user(i40e_dbg_netdev_ops_buf,
|
||||
buffer, count);
|
||||
if (bytes_not_copied)
|
||||
cmd_buf = kzalloc(count + 1, GFP_KERNEL);
|
||||
if (!cmd_buf)
|
||||
return count;
|
||||
bytes_not_copied = copy_from_user(cmd_buf, buffer, count);
|
||||
if (bytes_not_copied) {
|
||||
kfree(cmd_buf);
|
||||
return -EFAULT;
|
||||
i40e_dbg_netdev_ops_buf[count] = '\0';
|
||||
}
|
||||
cmd_buf[count] = '\0';
|
||||
|
||||
buf_tmp = strchr(i40e_dbg_netdev_ops_buf, '\n');
|
||||
buf_tmp = strchr(cmd_buf, '\n');
|
||||
if (buf_tmp) {
|
||||
*buf_tmp = '\0';
|
||||
count = buf_tmp - i40e_dbg_netdev_ops_buf + 1;
|
||||
count = buf_tmp - cmd_buf + 1;
|
||||
}
|
||||
|
||||
if (strncmp(i40e_dbg_netdev_ops_buf, "change_mtu", 10) == 0) {
|
||||
if (strncmp(cmd_buf, "change_mtu", 10) == 0) {
|
||||
int mtu;
|
||||
|
||||
cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i %i",
|
||||
cnt = sscanf(&cmd_buf[11], "%i %i",
|
||||
&vsi_seid, &mtu);
|
||||
if (cnt != 2) {
|
||||
dev_info(&pf->pdev->dev, "change_mtu <vsi_seid> <mtu>\n");
|
||||
|
|
@ -1735,8 +1651,8 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
|
|||
dev_info(&pf->pdev->dev, "Could not acquire RTNL - please try again\n");
|
||||
}
|
||||
|
||||
} else if (strncmp(i40e_dbg_netdev_ops_buf, "set_rx_mode", 11) == 0) {
|
||||
cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i", &vsi_seid);
|
||||
} else if (strncmp(cmd_buf, "set_rx_mode", 11) == 0) {
|
||||
cnt = sscanf(&cmd_buf[11], "%i", &vsi_seid);
|
||||
if (cnt != 1) {
|
||||
dev_info(&pf->pdev->dev, "set_rx_mode <vsi_seid>\n");
|
||||
goto netdev_ops_write_done;
|
||||
|
|
@ -1756,8 +1672,8 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
|
|||
dev_info(&pf->pdev->dev, "Could not acquire RTNL - please try again\n");
|
||||
}
|
||||
|
||||
} else if (strncmp(i40e_dbg_netdev_ops_buf, "napi", 4) == 0) {
|
||||
cnt = sscanf(&i40e_dbg_netdev_ops_buf[4], "%i", &vsi_seid);
|
||||
} else if (strncmp(cmd_buf, "napi", 4) == 0) {
|
||||
cnt = sscanf(&cmd_buf[4], "%i", &vsi_seid);
|
||||
if (cnt != 1) {
|
||||
dev_info(&pf->pdev->dev, "napi <vsi_seid>\n");
|
||||
goto netdev_ops_write_done;
|
||||
|
|
@ -1775,21 +1691,20 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
|
|||
dev_info(&pf->pdev->dev, "napi called\n");
|
||||
}
|
||||
} else {
|
||||
dev_info(&pf->pdev->dev, "unknown command '%s'\n",
|
||||
i40e_dbg_netdev_ops_buf);
|
||||
dev_info(&pf->pdev->dev, "unknown command '%s'\n", cmd_buf);
|
||||
dev_info(&pf->pdev->dev, "available commands\n");
|
||||
dev_info(&pf->pdev->dev, " change_mtu <vsi_seid> <mtu>\n");
|
||||
dev_info(&pf->pdev->dev, " set_rx_mode <vsi_seid>\n");
|
||||
dev_info(&pf->pdev->dev, " napi <vsi_seid>\n");
|
||||
}
|
||||
netdev_ops_write_done:
|
||||
kfree(cmd_buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations i40e_dbg_netdev_ops_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = i40e_dbg_netdev_ops_read,
|
||||
.write = i40e_dbg_netdev_ops_write,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3176,12 +3176,14 @@ static irqreturn_t ice_ll_ts_intr(int __always_unused irq, void *data)
|
|||
hw = &pf->hw;
|
||||
tx = &pf->ptp.port.tx;
|
||||
spin_lock_irqsave(&tx->lock, flags);
|
||||
ice_ptp_complete_tx_single_tstamp(tx);
|
||||
if (tx->init) {
|
||||
ice_ptp_complete_tx_single_tstamp(tx);
|
||||
|
||||
idx = find_next_bit_wrap(tx->in_use, tx->len,
|
||||
tx->last_ll_ts_idx_read + 1);
|
||||
if (idx != tx->len)
|
||||
ice_ptp_req_tx_single_tstamp(tx, idx);
|
||||
idx = find_next_bit_wrap(tx->in_use, tx->len,
|
||||
tx->last_ll_ts_idx_read + 1);
|
||||
if (idx != tx->len)
|
||||
ice_ptp_req_tx_single_tstamp(tx, idx);
|
||||
}
|
||||
spin_unlock_irqrestore(&tx->lock, flags);
|
||||
|
||||
val = GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M |
|
||||
|
|
|
|||
|
|
@ -2701,16 +2701,19 @@ irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf)
|
|||
*/
|
||||
if (hw->dev_caps.ts_dev_info.ts_ll_int_read) {
|
||||
struct ice_ptp_tx *tx = &pf->ptp.port.tx;
|
||||
u8 idx;
|
||||
u8 idx, last;
|
||||
|
||||
if (!ice_pf_state_is_nominal(pf))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
spin_lock(&tx->lock);
|
||||
idx = find_next_bit_wrap(tx->in_use, tx->len,
|
||||
tx->last_ll_ts_idx_read + 1);
|
||||
if (idx != tx->len)
|
||||
ice_ptp_req_tx_single_tstamp(tx, idx);
|
||||
if (tx->init) {
|
||||
last = tx->last_ll_ts_idx_read + 1;
|
||||
idx = find_next_bit_wrap(tx->in_use, tx->len,
|
||||
last);
|
||||
if (idx != tx->len)
|
||||
ice_ptp_req_tx_single_tstamp(tx, idx);
|
||||
}
|
||||
spin_unlock(&tx->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
|
|||
|
|
@ -247,10 +247,10 @@ static void idpf_unplug_aux_dev(struct auxiliary_device *adev)
|
|||
if (!adev)
|
||||
return;
|
||||
|
||||
ida_free(&idpf_idc_ida, adev->id);
|
||||
|
||||
auxiliary_device_delete(adev);
|
||||
auxiliary_device_uninit(adev);
|
||||
|
||||
ida_free(&idpf_idc_ida, adev->id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2344,6 +2344,7 @@ static int idpf_set_mac(struct net_device *netdev, void *p)
|
|||
struct idpf_netdev_priv *np = netdev_priv(netdev);
|
||||
struct idpf_vport_config *vport_config;
|
||||
struct sockaddr *addr = p;
|
||||
u8 old_mac_addr[ETH_ALEN];
|
||||
struct idpf_vport *vport;
|
||||
int err = 0;
|
||||
|
||||
|
|
@ -2367,17 +2368,19 @@ static int idpf_set_mac(struct net_device *netdev, void *p)
|
|||
if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
|
||||
goto unlock_mutex;
|
||||
|
||||
ether_addr_copy(old_mac_addr, vport->default_mac_addr);
|
||||
ether_addr_copy(vport->default_mac_addr, addr->sa_data);
|
||||
vport_config = vport->adapter->vport_config[vport->idx];
|
||||
err = idpf_add_mac_filter(vport, np, addr->sa_data, false);
|
||||
if (err) {
|
||||
__idpf_del_mac_filter(vport_config, addr->sa_data);
|
||||
ether_addr_copy(vport->default_mac_addr, netdev->dev_addr);
|
||||
goto unlock_mutex;
|
||||
}
|
||||
|
||||
if (is_valid_ether_addr(vport->default_mac_addr))
|
||||
idpf_del_mac_filter(vport, np, vport->default_mac_addr, false);
|
||||
if (is_valid_ether_addr(old_mac_addr))
|
||||
__idpf_del_mac_filter(vport_config, old_mac_addr);
|
||||
|
||||
ether_addr_copy(vport->default_mac_addr, addr->sa_data);
|
||||
eth_hw_addr_set(netdev, addr->sa_data);
|
||||
|
||||
unlock_mutex:
|
||||
|
|
|
|||
|
|
@ -3765,6 +3765,16 @@ u32 idpf_get_vport_id(struct idpf_vport *vport)
|
|||
return le32_to_cpu(vport_msg->vport_id);
|
||||
}
|
||||
|
||||
static void idpf_set_mac_type(struct idpf_vport *vport,
|
||||
struct virtchnl2_mac_addr *mac_addr)
|
||||
{
|
||||
bool is_primary;
|
||||
|
||||
is_primary = ether_addr_equal(vport->default_mac_addr, mac_addr->addr);
|
||||
mac_addr->type = is_primary ? VIRTCHNL2_MAC_ADDR_PRIMARY :
|
||||
VIRTCHNL2_MAC_ADDR_EXTRA;
|
||||
}
|
||||
|
||||
/**
|
||||
* idpf_mac_filter_async_handler - Async callback for mac filters
|
||||
* @adapter: private data struct
|
||||
|
|
@ -3894,6 +3904,7 @@ int idpf_add_del_mac_filters(struct idpf_vport *vport,
|
|||
list) {
|
||||
if (add && f->add) {
|
||||
ether_addr_copy(mac_addr[i].addr, f->macaddr);
|
||||
idpf_set_mac_type(vport, &mac_addr[i]);
|
||||
i++;
|
||||
f->add = false;
|
||||
if (i == total_filters)
|
||||
|
|
@ -3901,6 +3912,7 @@ int idpf_add_del_mac_filters(struct idpf_vport *vport,
|
|||
}
|
||||
if (!add && f->remove) {
|
||||
ether_addr_copy(mac_addr[i].addr, f->macaddr);
|
||||
idpf_set_mac_type(vport, &mac_addr[i]);
|
||||
i++;
|
||||
f->remove = false;
|
||||
if (i == total_filters)
|
||||
|
|
|
|||
|
|
@ -3571,13 +3571,13 @@ ixgbe_get_eee_fw(struct ixgbe_adapter *adapter, struct ethtool_keee *edata)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(ixgbe_ls_map); ++i) {
|
||||
if (hw->phy.eee_speeds_supported & ixgbe_ls_map[i].mac_speed)
|
||||
linkmode_set_bit(ixgbe_lp_map[i].link_mode,
|
||||
linkmode_set_bit(ixgbe_ls_map[i].link_mode,
|
||||
edata->supported);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ixgbe_ls_map); ++i) {
|
||||
if (hw->phy.eee_speeds_advertised & ixgbe_ls_map[i].mac_speed)
|
||||
linkmode_set_bit(ixgbe_lp_map[i].link_mode,
|
||||
linkmode_set_bit(ixgbe_ls_map[i].link_mode,
|
||||
edata->advertised);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1761,6 +1761,13 @@ static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
bool gso = false;
|
||||
int tx_num;
|
||||
|
||||
if (skb_vlan_tag_present(skb) &&
|
||||
!eth_proto_is_802_3(eth_hdr(skb)->h_proto)) {
|
||||
skb = __vlan_hwaccel_push_inside(skb);
|
||||
if (!skb)
|
||||
goto dropped;
|
||||
}
|
||||
|
||||
/* normally we can rely on the stack not calling this more than once,
|
||||
* however we have 2 queues running on the same ring so we need to lock
|
||||
* the ring access
|
||||
|
|
@ -1806,8 +1813,9 @@ static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
|
||||
drop:
|
||||
spin_unlock(ð->page_lock);
|
||||
stats->tx_dropped++;
|
||||
dev_kfree_skb_any(skb);
|
||||
dropped:
|
||||
stats->tx_dropped++;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -267,8 +267,10 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
|
|||
pp.dma_dir = priv->dma_dir;
|
||||
|
||||
ring->pp = page_pool_create(&pp);
|
||||
if (!ring->pp)
|
||||
if (IS_ERR(ring->pp)) {
|
||||
err = PTR_ERR(ring->pp);
|
||||
goto err_ring;
|
||||
}
|
||||
|
||||
if (xdp_rxq_info_reg(&ring->xdp_rxq, priv->dev, queue_index, 0) < 0)
|
||||
goto err_pp;
|
||||
|
|
|
|||
|
|
@ -423,13 +423,16 @@ static void lan865x_remove(struct spi_device *spi)
|
|||
free_netdev(priv->netdev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id spidev_spi_ids[] = {
|
||||
static const struct spi_device_id lan865x_ids[] = {
|
||||
{ .name = "lan8650" },
|
||||
{ .name = "lan8651" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, lan865x_ids);
|
||||
|
||||
static const struct of_device_id lan865x_dt_ids[] = {
|
||||
{ .compatible = "microchip,lan8650" },
|
||||
{ .compatible = "microchip,lan8651" },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lan865x_dt_ids);
|
||||
|
|
@ -441,7 +444,7 @@ static struct spi_driver lan865x_driver = {
|
|||
},
|
||||
.probe = lan865x_probe,
|
||||
.remove = lan865x_remove,
|
||||
.id_table = spidev_spi_ids,
|
||||
.id_table = lan865x_ids,
|
||||
};
|
||||
module_spi_driver(lan865x_driver);
|
||||
|
||||
|
|
|
|||
|
|
@ -1249,7 +1249,8 @@ struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct net_device *netdev)
|
|||
|
||||
/* Set the SPI controller to pump at realtime priority */
|
||||
tc6->spi->rt = true;
|
||||
spi_setup(tc6->spi);
|
||||
if (spi_setup(tc6->spi) < 0)
|
||||
return NULL;
|
||||
|
||||
tc6->spi_ctrl_tx_buf = devm_kzalloc(&tc6->spi->dev,
|
||||
OA_TC6_CTRL_SPI_BUF_SIZE,
|
||||
|
|
|
|||
|
|
@ -1522,7 +1522,7 @@ static int am65_cpsw_nuss_tx_compl_packets(struct am65_cpsw_common *common,
|
|||
}
|
||||
}
|
||||
|
||||
if (single_port) {
|
||||
if (single_port && num_tx) {
|
||||
netif_txq = netdev_get_tx_queue(ndev, chn);
|
||||
netdev_tx_completed_queue(netif_txq, num_tx, total_bytes);
|
||||
am65_cpsw_nuss_tx_wake(tx_chn, ndev, netif_txq);
|
||||
|
|
|
|||
|
|
@ -1168,6 +1168,15 @@ static void axienet_dma_rx_cb(void *data, const struct dmaengine_result *result)
|
|||
&meta_max_len);
|
||||
dma_unmap_single(lp->dev, skbuf_dma->dma_address, lp->max_frm_size,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
if (IS_ERR(app_metadata)) {
|
||||
if (net_ratelimit())
|
||||
netdev_err(lp->ndev, "Failed to get RX metadata pointer\n");
|
||||
dev_kfree_skb_any(skb);
|
||||
lp->ndev->stats.rx_dropped++;
|
||||
goto rx_submit;
|
||||
}
|
||||
|
||||
/* TODO: Derive app word index programmatically */
|
||||
rx_len = (app_metadata[LEN_APP] & 0xFFFF);
|
||||
skb_put(skb, rx_len);
|
||||
|
|
@ -1180,6 +1189,7 @@ static void axienet_dma_rx_cb(void *data, const struct dmaengine_result *result)
|
|||
u64_stats_add(&lp->rx_bytes, rx_len);
|
||||
u64_stats_update_end(&lp->rx_stat_sync);
|
||||
|
||||
rx_submit:
|
||||
for (i = 0; i < CIRC_SPACE(lp->rx_ring_head, lp->rx_ring_tail,
|
||||
RX_BUF_NUM_DEFAULT); i++)
|
||||
axienet_rx_submit_desc(lp->ndev);
|
||||
|
|
|
|||
|
|
@ -1576,7 +1576,7 @@ do_reset(struct net_device *dev, int full)
|
|||
msleep(40); /* wait 40 msec to let it complete */
|
||||
}
|
||||
if (full_duplex)
|
||||
PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR | FullDuplex));
|
||||
PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR) | FullDuplex);
|
||||
} else { /* No MII */
|
||||
SelectPage(0);
|
||||
value = GetByte(XIRCREG_ESR); /* read the ESR */
|
||||
|
|
|
|||
|
|
@ -1844,7 +1844,7 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
if (tb_sa[MACSEC_SA_ATTR_PN]) {
|
||||
spin_lock_bh(&rx_sa->lock);
|
||||
rx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]);
|
||||
rx_sa->next_pn = nla_get_uint(tb_sa[MACSEC_SA_ATTR_PN]);
|
||||
spin_unlock_bh(&rx_sa->lock);
|
||||
}
|
||||
|
||||
|
|
@ -2086,7 +2086,7 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
spin_lock_bh(&tx_sa->lock);
|
||||
tx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]);
|
||||
tx_sa->next_pn = nla_get_uint(tb_sa[MACSEC_SA_ATTR_PN]);
|
||||
spin_unlock_bh(&tx_sa->lock);
|
||||
|
||||
if (tb_sa[MACSEC_SA_ATTR_ACTIVE])
|
||||
|
|
@ -2398,7 +2398,7 @@ static int macsec_upd_txsa(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
spin_lock_bh(&tx_sa->lock);
|
||||
prev_pn = tx_sa->next_pn_halves;
|
||||
tx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]);
|
||||
tx_sa->next_pn = nla_get_uint(tb_sa[MACSEC_SA_ATTR_PN]);
|
||||
spin_unlock_bh(&tx_sa->lock);
|
||||
}
|
||||
|
||||
|
|
@ -2496,7 +2496,7 @@ static int macsec_upd_rxsa(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
spin_lock_bh(&rx_sa->lock);
|
||||
prev_pn = rx_sa->next_pn_halves;
|
||||
rx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]);
|
||||
rx_sa->next_pn = nla_get_uint(tb_sa[MACSEC_SA_ATTR_PN]);
|
||||
spin_unlock_bh(&rx_sa->lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ static void mctp_usb_in_complete(struct urb *urb)
|
|||
struct mctp_usb_hdr *hdr;
|
||||
u8 pkt_len; /* length of MCTP packet, no USB header */
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
hdr = skb_pull_data(skb, sizeof(*hdr));
|
||||
if (!hdr)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#define MIIC_PRCMD 0x0
|
||||
#define MIIC_ESID_CODE 0x4
|
||||
|
||||
#define MIIC_MODCTRL 0x20
|
||||
#define MIIC_MODCTRL 0x8
|
||||
#define MIIC_MODCTRL_SW_MODE GENMASK(4, 0)
|
||||
|
||||
#define MIIC_CONVCTRL(port) (0x100 + (port) * 4)
|
||||
|
|
|
|||
|
|
@ -456,12 +456,12 @@ static void vsc85xx_dequeue_skb(struct vsc85xx_ptp *ptp)
|
|||
*p++ = (reg >> 24) & 0xff;
|
||||
}
|
||||
|
||||
len = skb_queue_len(&ptp->tx_queue);
|
||||
len = skb_queue_len_lockless(&ptp->tx_queue);
|
||||
if (len < 1)
|
||||
return;
|
||||
|
||||
while (len--) {
|
||||
skb = __skb_dequeue(&ptp->tx_queue);
|
||||
skb = skb_dequeue(&ptp->tx_queue);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
|
|
@ -486,7 +486,7 @@ static void vsc85xx_dequeue_skb(struct vsc85xx_ptp *ptp)
|
|||
* packet in the FIFO right now, reschedule it for later
|
||||
* packets.
|
||||
*/
|
||||
__skb_queue_tail(&ptp->tx_queue, skb);
|
||||
skb_queue_tail(&ptp->tx_queue, skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1068,6 +1068,7 @@ static int vsc85xx_hwtstamp(struct mii_timestamper *mii_ts,
|
|||
case HWTSTAMP_TX_ON:
|
||||
break;
|
||||
case HWTSTAMP_TX_OFF:
|
||||
skb_queue_purge(&vsc8531->ptp->tx_queue);
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
|
|
@ -1092,9 +1093,6 @@ static int vsc85xx_hwtstamp(struct mii_timestamper *mii_ts,
|
|||
|
||||
mutex_lock(&vsc8531->ts_lock);
|
||||
|
||||
__skb_queue_purge(&vsc8531->ptp->tx_queue);
|
||||
__skb_queue_head_init(&vsc8531->ptp->tx_queue);
|
||||
|
||||
/* Disable predictor while configuring the 1588 block */
|
||||
val = vsc85xx_ts_read_csr(phydev, PROCESSOR,
|
||||
MSCC_PHY_PTP_INGR_PREDICTOR);
|
||||
|
|
@ -1180,9 +1178,7 @@ static void vsc85xx_txtstamp(struct mii_timestamper *mii_ts,
|
|||
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
|
||||
mutex_lock(&vsc8531->ts_lock);
|
||||
__skb_queue_tail(&vsc8531->ptp->tx_queue, skb);
|
||||
mutex_unlock(&vsc8531->ts_lock);
|
||||
skb_queue_tail(&vsc8531->ptp->tx_queue, skb);
|
||||
return;
|
||||
|
||||
out:
|
||||
|
|
@ -1548,6 +1544,7 @@ void vsc8584_ptp_deinit(struct phy_device *phydev)
|
|||
if (vsc8531->ptp->ptp_clock) {
|
||||
ptp_clock_unregister(vsc8531->ptp->ptp_clock);
|
||||
skb_queue_purge(&vsc8531->rx_skbs_list);
|
||||
skb_queue_purge(&vsc8531->ptp->tx_queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1571,7 +1568,7 @@ irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev)
|
|||
if (rc & VSC85XX_1588_INT_FIFO_ADD) {
|
||||
vsc85xx_get_tx_ts(priv->ptp);
|
||||
} else if (rc & VSC85XX_1588_INT_FIFO_OVERFLOW) {
|
||||
__skb_queue_purge(&priv->ptp->tx_queue);
|
||||
skb_queue_purge(&priv->ptp->tx_queue);
|
||||
vsc85xx_ts_reset_fifo(phydev);
|
||||
}
|
||||
|
||||
|
|
@ -1591,6 +1588,7 @@ int vsc8584_ptp_probe(struct phy_device *phydev)
|
|||
mutex_init(&vsc8531->phc_lock);
|
||||
mutex_init(&vsc8531->ts_lock);
|
||||
skb_queue_head_init(&vsc8531->rx_skbs_list);
|
||||
skb_queue_head_init(&vsc8531->ptp->tx_queue);
|
||||
|
||||
/* Retrieve the shared load/save GPIO. Request it as non exclusive as
|
||||
* the same GPIO can be requested by all the PHYs of the same package.
|
||||
|
|
|
|||
|
|
@ -1016,6 +1016,42 @@ static void phylink_pcs_an_restart(struct phylink *pl)
|
|||
pl->pcs->ops->pcs_an_restart(pl->pcs);
|
||||
}
|
||||
|
||||
enum inband_type {
|
||||
INBAND_NONE,
|
||||
INBAND_CISCO_SGMII,
|
||||
INBAND_BASEX,
|
||||
};
|
||||
|
||||
static enum inband_type phylink_get_inband_type(phy_interface_t interface)
|
||||
{
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
case PHY_INTERFACE_MODE_QUSGMII:
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
case PHY_INTERFACE_MODE_10G_QXGMII:
|
||||
/* These protocols are designed for use with a PHY which
|
||||
* communicates its negotiation result back to the MAC via
|
||||
* inband communication. Note: there exist PHYs that run
|
||||
* with SGMII but do not send the inband data.
|
||||
*/
|
||||
return INBAND_CISCO_SGMII;
|
||||
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
/* 1000base-X is designed for use media-side for Fibre
|
||||
* connections, and thus the Autoneg bit needs to be
|
||||
* taken into account. We also do this for 2500base-X
|
||||
* as well, but drivers may not support this, so may
|
||||
* need to override this.
|
||||
*/
|
||||
return INBAND_BASEX;
|
||||
|
||||
default:
|
||||
return INBAND_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* phylink_pcs_neg_mode() - helper to determine PCS inband mode
|
||||
* @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||
|
|
@ -1043,46 +1079,19 @@ static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
|
|||
unsigned int pcs_ib_caps = 0;
|
||||
unsigned int phy_ib_caps = 0;
|
||||
unsigned int neg_mode, mode;
|
||||
enum {
|
||||
INBAND_CISCO_SGMII,
|
||||
INBAND_BASEX,
|
||||
} type;
|
||||
enum inband_type type;
|
||||
|
||||
type = phylink_get_inband_type(interface);
|
||||
if (type == INBAND_NONE) {
|
||||
pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE;
|
||||
pl->act_link_an_mode = pl->req_link_an_mode;
|
||||
return;
|
||||
}
|
||||
|
||||
mode = pl->req_link_an_mode;
|
||||
|
||||
pl->phy_ib_mode = 0;
|
||||
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
case PHY_INTERFACE_MODE_QUSGMII:
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
case PHY_INTERFACE_MODE_10G_QXGMII:
|
||||
/* These protocols are designed for use with a PHY which
|
||||
* communicates its negotiation result back to the MAC via
|
||||
* inband communication. Note: there exist PHYs that run
|
||||
* with SGMII but do not send the inband data.
|
||||
*/
|
||||
type = INBAND_CISCO_SGMII;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
/* 1000base-X is designed for use media-side for Fibre
|
||||
* connections, and thus the Autoneg bit needs to be
|
||||
* taken into account. We also do this for 2500base-X
|
||||
* as well, but drivers may not support this, so may
|
||||
* need to override this.
|
||||
*/
|
||||
type = INBAND_BASEX;
|
||||
break;
|
||||
|
||||
default:
|
||||
pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE;
|
||||
pl->act_link_an_mode = mode;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pcs)
|
||||
pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface);
|
||||
|
||||
|
|
@ -2132,9 +2141,6 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
|
|||
__ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported,
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, phy->advertising);
|
||||
|
||||
if (phy_interrupt_is_valid(phy))
|
||||
phy_request_interrupt(phy);
|
||||
|
||||
if (pl->config->mac_managed_pm)
|
||||
phy->mac_managed_pm = true;
|
||||
|
||||
|
|
@ -2151,6 +2157,9 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
|
|||
ret = 0;
|
||||
}
|
||||
|
||||
if (ret == 0 && phy_interrupt_is_valid(phy))
|
||||
phy_request_interrupt(phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -3625,6 +3634,7 @@ static int phylink_sfp_config_optical(struct phylink *pl)
|
|||
{
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
|
||||
struct phylink_link_state config;
|
||||
enum inband_type inband_type;
|
||||
phy_interface_t interface;
|
||||
int ret;
|
||||
|
||||
|
|
@ -3671,6 +3681,23 @@ static int phylink_sfp_config_optical(struct phylink *pl)
|
|||
phylink_dbg(pl, "optical SFP: chosen %s interface\n",
|
||||
phy_modes(interface));
|
||||
|
||||
inband_type = phylink_get_inband_type(interface);
|
||||
if (inband_type == INBAND_NONE) {
|
||||
/* If this is the sole interface, and there is no inband
|
||||
* support, clear the advertising mask and Autoneg bit in
|
||||
* the support mask. Otherwise, just clear the Autoneg bit
|
||||
* in the advertising mask.
|
||||
*/
|
||||
if (phy_interface_weight(pl->sfp_interfaces) == 1) {
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
pl->sfp_support);
|
||||
linkmode_zero(config.advertising);
|
||||
} else {
|
||||
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
config.advertising);
|
||||
}
|
||||
}
|
||||
|
||||
if (!phylink_validate_pcs_inband_autoneg(pl, interface,
|
||||
config.advertising)) {
|
||||
phylink_err(pl, "autoneg setting not compatible with PCS");
|
||||
|
|
|
|||
|
|
@ -492,6 +492,9 @@ static const struct sfp_quirk sfp_quirks[] = {
|
|||
SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex,
|
||||
sfp_fixup_nokia),
|
||||
|
||||
// FLYPRO SFP-10GT-CS-30M uses Rollball protocol to talk to the PHY.
|
||||
SFP_QUIRK_F("FLYPRO", "SFP-10GT-CS-30M", sfp_fixup_rollball),
|
||||
|
||||
// Fiberstore SFP-10G-T doesn't identify as copper, uses the Rollball
|
||||
// protocol to talk to the PHY and needs 4 sec wait before probing the
|
||||
// PHY.
|
||||
|
|
|
|||
|
|
@ -1744,7 +1744,6 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb)
|
|||
*/
|
||||
if (net_ratelimit())
|
||||
netdev_err(ppp->dev, "ppp: compressor dropped pkt\n");
|
||||
kfree_skb(skb);
|
||||
consume_skb(new_skb);
|
||||
new_skb = NULL;
|
||||
}
|
||||
|
|
@ -1845,9 +1844,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
|
|||
"down - pkt dropped.\n");
|
||||
goto drop;
|
||||
}
|
||||
skb = pad_compress_skb(ppp, skb);
|
||||
if (!skb)
|
||||
new_skb = pad_compress_skb(ppp, skb);
|
||||
if (!new_skb)
|
||||
goto drop;
|
||||
skb = new_skb;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1445,6 +1445,10 @@ static enum skb_drop_reason vxlan_snoop(struct net_device *dev,
|
|||
if (READ_ONCE(f->updated) != now)
|
||||
WRITE_ONCE(f->updated, now);
|
||||
|
||||
/* Don't override an fdb with nexthop with a learnt entry */
|
||||
if (rcu_access_pointer(f->nh))
|
||||
return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS;
|
||||
|
||||
if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip) &&
|
||||
rdst->remote_ifindex == ifindex))
|
||||
return SKB_NOT_DROPPED_YET;
|
||||
|
|
@ -1453,10 +1457,6 @@ static enum skb_drop_reason vxlan_snoop(struct net_device *dev,
|
|||
if (f->state & (NUD_PERMANENT | NUD_NOARP))
|
||||
return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS;
|
||||
|
||||
/* Don't override an fdb with nexthop with a learnt entry */
|
||||
if (rcu_access_pointer(f->nh))
|
||||
return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS;
|
||||
|
||||
if (net_ratelimit())
|
||||
netdev_info(dev,
|
||||
"%pM migrated from %pIS to %pIS\n",
|
||||
|
|
@ -1877,6 +1877,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
|||
n = neigh_lookup(&arp_tbl, &tip, dev);
|
||||
|
||||
if (n) {
|
||||
struct vxlan_rdst *rdst = NULL;
|
||||
struct vxlan_fdb *f;
|
||||
struct sk_buff *reply;
|
||||
|
||||
|
|
@ -1887,7 +1888,9 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
|||
|
||||
rcu_read_lock();
|
||||
f = vxlan_find_mac_tx(vxlan, n->ha, vni);
|
||||
if (f && vxlan_addr_any(&(first_remote_rcu(f)->remote_ip))) {
|
||||
if (f)
|
||||
rdst = first_remote_rcu(f);
|
||||
if (rdst && vxlan_addr_any(&rdst->remote_ip)) {
|
||||
/* bridge-local neighbor */
|
||||
neigh_release(n);
|
||||
rcu_read_unlock();
|
||||
|
|
@ -2044,6 +2047,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
|||
n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev);
|
||||
|
||||
if (n) {
|
||||
struct vxlan_rdst *rdst = NULL;
|
||||
struct vxlan_fdb *f;
|
||||
struct sk_buff *reply;
|
||||
|
||||
|
|
@ -2053,7 +2057,9 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
|||
}
|
||||
|
||||
f = vxlan_find_mac_tx(vxlan, n->ha, vni);
|
||||
if (f && vxlan_addr_any(&(first_remote_rcu(f)->remote_ip))) {
|
||||
if (f)
|
||||
rdst = first_remote_rcu(f);
|
||||
if (rdst && vxlan_addr_any(&rdst->remote_ip)) {
|
||||
/* bridge-local neighbor */
|
||||
neigh_release(n);
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -61,9 +61,7 @@ static inline struct hlist_head *vs_head(struct net *net, __be16 port)
|
|||
return &vn->sock_list[hash_32(ntohs(port), PORT_HASH_BITS)];
|
||||
}
|
||||
|
||||
/* First remote destination for a forwarding entry.
|
||||
* Guaranteed to be non-NULL because remotes are never deleted.
|
||||
*/
|
||||
/* First remote destination for a forwarding entry. */
|
||||
static inline struct vxlan_rdst *first_remote_rcu(struct vxlan_fdb *fdb)
|
||||
{
|
||||
if (rcu_access_pointer(fdb->nh))
|
||||
|
|
|
|||
|
|
@ -411,6 +411,8 @@ struct ath11k_vif {
|
|||
bool do_not_send_tmpl;
|
||||
struct ath11k_arp_ns_offload arp_ns_offload;
|
||||
struct ath11k_rekey_data rekey_data;
|
||||
u32 num_stations;
|
||||
bool reinstall_group_keys;
|
||||
|
||||
struct ath11k_reg_tpc_power_info reg_tpc_info;
|
||||
|
||||
|
|
|
|||
|
|
@ -4317,6 +4317,40 @@ static int ath11k_clear_peer_keys(struct ath11k_vif *arvif,
|
|||
return first_errno;
|
||||
}
|
||||
|
||||
static int ath11k_set_group_keys(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
const u8 *addr = arvif->bssid;
|
||||
int i, ret, first_errno = 0;
|
||||
struct ath11k_peer *peer;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath11k_peer_find(ab, arvif->vdev_id, addr);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
if (!peer)
|
||||
return -ENOENT;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
|
||||
struct ieee80211_key_conf *key = peer->keys[i];
|
||||
|
||||
if (!key || (key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
||||
continue;
|
||||
|
||||
ret = ath11k_install_key(arvif, key, SET_KEY, addr,
|
||||
WMI_KEY_GROUP);
|
||||
if (ret < 0 && first_errno == 0)
|
||||
first_errno = ret;
|
||||
|
||||
if (ret < 0)
|
||||
ath11k_warn(ab, "failed to set group key of idx %d for vdev %d: %d\n",
|
||||
i, arvif->vdev_id, ret);
|
||||
}
|
||||
|
||||
return first_errno;
|
||||
}
|
||||
|
||||
static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
|
|
@ -4326,6 +4360,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
struct ath11k_peer *peer;
|
||||
struct ath11k_sta *arsta;
|
||||
bool is_ap_with_no_sta;
|
||||
const u8 *peer_addr;
|
||||
int ret = 0;
|
||||
u32 flags = 0;
|
||||
|
|
@ -4386,16 +4421,57 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
else
|
||||
flags |= WMI_KEY_GROUP;
|
||||
|
||||
ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"%s for peer %pM on vdev %d flags 0x%X, type = %d, num_sta %d\n",
|
||||
cmd == SET_KEY ? "SET_KEY" : "DEL_KEY", peer_addr, arvif->vdev_id,
|
||||
flags, arvif->vdev_type, arvif->num_stations);
|
||||
|
||||
ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret);
|
||||
goto exit;
|
||||
/* Allow group key clearing only in AP mode when no stations are
|
||||
* associated. There is a known race condition in firmware where
|
||||
* group addressed packets may be dropped if the key is cleared
|
||||
* and immediately set again during rekey.
|
||||
*
|
||||
* During GTK rekey, mac80211 issues a clear key (if the old key
|
||||
* exists) followed by an install key operation for same key
|
||||
* index. This causes ath11k to send two WMI commands in quick
|
||||
* succession: one to clear the old key and another to install the
|
||||
* new key in the same slot.
|
||||
*
|
||||
* Under certain conditions—especially under high load or time
|
||||
* sensitive scenarios, firmware may process these commands
|
||||
* asynchronously in a way that firmware assumes the key is
|
||||
* cleared whereas hardware has a valid key. This inconsistency
|
||||
* between hardware and firmware leads to group addressed packet
|
||||
* drops after rekey.
|
||||
* Only setting the same key again can restore a valid key in
|
||||
* firmware and allow packets to be transmitted.
|
||||
*
|
||||
* There is a use case where an AP can transition from Secure mode
|
||||
* to open mode without a vdev restart by just deleting all
|
||||
* associated peers and clearing key, Hence allow clear key for
|
||||
* that case alone. Mark arvif->reinstall_group_keys in such cases
|
||||
* and reinstall the same key when the first peer is added,
|
||||
* allowing firmware to recover from the race if it had occurred.
|
||||
*/
|
||||
|
||||
is_ap_with_no_sta = (vif->type == NL80211_IFTYPE_AP &&
|
||||
!arvif->num_stations);
|
||||
if ((flags & WMI_KEY_PAIRWISE) || cmd == SET_KEY || is_ap_with_no_sta) {
|
||||
ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to offload PN replay detection %d\n",
|
||||
ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((flags & WMI_KEY_GROUP) && cmd == SET_KEY && is_ap_with_no_sta)
|
||||
arvif->reinstall_group_keys = true;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
|
|
@ -4994,6 +5070,7 @@ static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif,
|
|||
return -ENOBUFS;
|
||||
|
||||
ar->num_stations++;
|
||||
arvif->num_stations++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -5009,6 +5086,7 @@ static void ath11k_mac_dec_num_stations(struct ath11k_vif *arvif,
|
|||
return;
|
||||
|
||||
ar->num_stations--;
|
||||
arvif->num_stations--;
|
||||
}
|
||||
|
||||
static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar,
|
||||
|
|
@ -9540,6 +9618,21 @@ static int ath11k_mac_station_add(struct ath11k *ar,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
/* Driver allows the DEL KEY followed by SET KEY sequence for
|
||||
* group keys for only when there is no clients associated, if at
|
||||
* all firmware has entered the race during that window,
|
||||
* reinstalling the same key when the first sta connects will allow
|
||||
* firmware to recover from the race.
|
||||
*/
|
||||
if (arvif->num_stations == 1 && arvif->reinstall_group_keys) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC, "set group keys on 1st station add for vdev %d\n",
|
||||
arvif->vdev_id);
|
||||
ret = ath11k_set_group_keys(arvif);
|
||||
if (ret)
|
||||
goto dec_num_station;
|
||||
arvif->reinstall_group_keys = false;
|
||||
}
|
||||
|
||||
arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
|
||||
if (!arsta->rx_stats) {
|
||||
ret = -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -2423,6 +2423,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
|
|||
|
||||
eml_cap = arg->ml.eml_cap;
|
||||
if (u16_get_bits(eml_cap, IEEE80211_EML_CAP_EMLSR_SUPP)) {
|
||||
ml_params->flags |= cpu_to_le32(ATH12K_WMI_FLAG_MLO_EMLSR_SUPPORT);
|
||||
/* Padding delay */
|
||||
eml_pad_delay = ieee80211_emlsr_pad_delay_in_us(eml_cap);
|
||||
ml_params->emlsr_padding_delay_us = cpu_to_le32(eml_pad_delay);
|
||||
|
|
|
|||
|
|
@ -393,10 +393,8 @@ void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg)
|
|||
if (!cfg->btcoex)
|
||||
return;
|
||||
|
||||
if (cfg->btcoex->timer_on) {
|
||||
cfg->btcoex->timer_on = false;
|
||||
timer_shutdown_sync(&cfg->btcoex->timer);
|
||||
}
|
||||
timer_shutdown_sync(&cfg->btcoex->timer);
|
||||
cfg->btcoex->timer_on = false;
|
||||
|
||||
cancel_work_sync(&cfg->btcoex->work);
|
||||
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(acpi_dsm_size) != DSM_FUNC_NUM_FUNCS);
|
||||
|
||||
if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size)))
|
||||
if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size) || !func))
|
||||
return -EINVAL;
|
||||
|
||||
expected_size = acpi_dsm_size[func];
|
||||
|
|
@ -178,6 +178,29 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
|||
if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!fwrt->acpi_dsm_funcs_valid) {
|
||||
ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV,
|
||||
DSM_FUNC_QUERY,
|
||||
&iwl_guid, &tmp,
|
||||
acpi_dsm_size[DSM_FUNC_QUERY]);
|
||||
if (ret) {
|
||||
/* always indicate BIT(0) to avoid re-reading */
|
||||
fwrt->acpi_dsm_funcs_valid = BIT(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n",
|
||||
(u32)tmp);
|
||||
/* always indicate BIT(0) to avoid re-reading */
|
||||
fwrt->acpi_dsm_funcs_valid = tmp | BIT(0);
|
||||
}
|
||||
|
||||
if (!(fwrt->acpi_dsm_funcs_valid & BIT(func))) {
|
||||
IWL_DEBUG_RADIO(fwrt, "ACPI DSM %d not indicated as valid\n",
|
||||
func);
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func,
|
||||
&iwl_guid, &tmp, expected_size);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -113,6 +113,10 @@ struct iwl_txf_iter_data {
|
|||
* @phy_filters: specific phy filters as read from WPFC BIOS table
|
||||
* @ppag_bios_rev: PPAG BIOS revision
|
||||
* @ppag_bios_source: see &enum bios_source
|
||||
* @acpi_dsm_funcs_valid: bitmap indicating which DSM values are valid,
|
||||
* zero (default initialization) means it hasn't been read yet,
|
||||
* and BIT(0) is set when it has since function 0 also has this
|
||||
* bitmap and is always supported
|
||||
*/
|
||||
struct iwl_fw_runtime {
|
||||
struct iwl_trans *trans;
|
||||
|
|
@ -189,6 +193,10 @@ struct iwl_fw_runtime {
|
|||
bool uats_valid;
|
||||
u8 uefi_tables_lock_status;
|
||||
struct iwl_phy_specific_cfg phy_filters;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
u32 acpi_dsm_funcs_valid;
|
||||
#endif
|
||||
};
|
||||
|
||||
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
||||
|
|
|
|||
|
|
@ -747,6 +747,12 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!(data->functions[DSM_FUNC_QUERY] & BIT(func))) {
|
||||
IWL_DEBUG_RADIO(fwrt, "DSM func %d not in 0x%x\n",
|
||||
func, data->functions[DSM_FUNC_QUERY]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*value = data->functions[func];
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
|
|
|
|||
|
|
@ -673,6 +673,8 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
|
||||
IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_sff_name,
|
||||
DEVICE(0x0082), SUBDEV_MASKED(0xC000, 0xF000)),
|
||||
IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_sff_name,
|
||||
DEVICE(0x0085), SUBDEV_MASKED(0xC000, 0xF000)),
|
||||
IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_d_name,
|
||||
DEVICE(0x0082), SUBDEV(0x4820)),
|
||||
IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_mow1_name,
|
||||
|
|
@ -729,10 +731,10 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
DEVICE(0x0083), SUBDEV_MASKED(0x5, 0xF)),
|
||||
IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name,
|
||||
DEVICE(0x0083), SUBDEV_MASKED(0x6, 0xF)),
|
||||
IWL_DEV_INFO(iwl1000_bgn_cfg, iwl1000_bgn_name,
|
||||
DEVICE(0x0084), SUBDEV_MASKED(0x5, 0xF)),
|
||||
IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name,
|
||||
DEVICE(0x0084), SUBDEV(0x1216)),
|
||||
IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name,
|
||||
DEVICE(0x0084), SUBDEV(0x1316)),
|
||||
DEVICE(0x0084), SUBDEV_MASKED(0x6, 0xF)),
|
||||
|
||||
/* 100 Series WiFi */
|
||||
IWL_DEV_INFO(iwl100_bgn_cfg, iwl100_bgn_name,
|
||||
|
|
@ -964,6 +966,12 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
DEVICE(0x24F3), SUBDEV(0x0004)),
|
||||
IWL_DEV_INFO(iwl8260_cfg, iwl8260_2n_name,
|
||||
DEVICE(0x24F3), SUBDEV(0x0044)),
|
||||
IWL_DEV_INFO(iwl8260_cfg, iwl8260_2ac_name,
|
||||
DEVICE(0x24F4)),
|
||||
IWL_DEV_INFO(iwl8260_cfg, iwl4165_2ac_name,
|
||||
DEVICE(0x24F5)),
|
||||
IWL_DEV_INFO(iwl8260_cfg, iwl4165_2ac_name,
|
||||
DEVICE(0x24F6)),
|
||||
IWL_DEV_INFO(iwl8265_cfg, iwl8265_2ac_name,
|
||||
DEVICE(0x24FD)),
|
||||
IWL_DEV_INFO(iwl8265_cfg, iwl8275_2ac_name,
|
||||
|
|
@ -1222,11 +1230,15 @@ static int _iwl_pci_resume(struct device *device, bool restore)
|
|||
* Note: MAC (bits 0:7) will be cleared upon suspend even with wowlan,
|
||||
* but not bits [15:8]. So if we have bits set in lower word, assume
|
||||
* the device is alive.
|
||||
* Alternatively, if the scratch value is 0xFFFFFFFF, then we no longer
|
||||
* have access to the device and consider it powered off.
|
||||
* For older devices, just try silently to grab the NIC.
|
||||
*/
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
if (!(iwl_read32(trans, CSR_FUNC_SCRATCH) &
|
||||
CSR_FUNC_SCRATCH_POWER_OFF_MASK))
|
||||
u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH);
|
||||
|
||||
if (!(scratch & CSR_FUNC_SCRATCH_POWER_OFF_MASK) ||
|
||||
scratch == ~0U)
|
||||
device_was_powered_off = true;
|
||||
} else {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -2092,7 +2092,8 @@ static void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans,
|
|||
break;
|
||||
}
|
||||
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
|
||||
trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
len = DIV_ROUND_UP(len, 4);
|
||||
|
||||
if (WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX))
|
||||
|
|
|
|||
|
|
@ -1151,10 +1151,13 @@ static int lbs_associate(struct lbs_private *priv,
|
|||
/* add SSID TLV */
|
||||
rcu_read_lock();
|
||||
ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
|
||||
if (ssid_eid)
|
||||
pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]);
|
||||
else
|
||||
if (ssid_eid) {
|
||||
u32 ssid_len = min(ssid_eid[1], IEEE80211_MAX_SSID_LEN);
|
||||
|
||||
pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_len);
|
||||
} else {
|
||||
lbs_deb_assoc("no SSID\n");
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
/* add DS param TLV */
|
||||
|
|
|
|||
|
|
@ -4673,8 +4673,9 @@ int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
|
|||
* additional active scan request for hidden SSIDs on passive channels.
|
||||
*/
|
||||
adapter->num_in_chan_stats = 2 * (n_channels_bg + n_channels_a);
|
||||
adapter->chan_stats = vmalloc(array_size(sizeof(*adapter->chan_stats),
|
||||
adapter->num_in_chan_stats));
|
||||
adapter->chan_stats = kcalloc(adapter->num_in_chan_stats,
|
||||
sizeof(*adapter->chan_stats),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!adapter->chan_stats)
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -642,7 +642,7 @@ static int _mwifiex_fw_dpc(const struct firmware *firmware, void *context)
|
|||
goto done;
|
||||
|
||||
err_add_intf:
|
||||
vfree(adapter->chan_stats);
|
||||
kfree(adapter->chan_stats);
|
||||
err_init_chan_scan:
|
||||
wiphy_unregister(adapter->wiphy);
|
||||
wiphy_free(adapter->wiphy);
|
||||
|
|
@ -1485,7 +1485,7 @@ static void mwifiex_uninit_sw(struct mwifiex_adapter *adapter)
|
|||
wiphy_free(adapter->wiphy);
|
||||
adapter->wiphy = NULL;
|
||||
|
||||
vfree(adapter->chan_stats);
|
||||
kfree(adapter->chan_stats);
|
||||
mwifiex_free_cmd_buffers(adapter);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -818,6 +818,43 @@ void mt76_free_device(struct mt76_dev *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_free_device);
|
||||
|
||||
static void mt76_reset_phy(struct mt76_phy *phy)
|
||||
{
|
||||
if (!phy)
|
||||
return;
|
||||
|
||||
INIT_LIST_HEAD(&phy->tx_list);
|
||||
}
|
||||
|
||||
void mt76_reset_device(struct mt76_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) {
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
wcid = rcu_dereference(dev->wcid[i]);
|
||||
if (!wcid)
|
||||
continue;
|
||||
|
||||
wcid->sta = 0;
|
||||
mt76_wcid_cleanup(dev, wcid);
|
||||
rcu_assign_pointer(dev->wcid[i], NULL);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
INIT_LIST_HEAD(&dev->wcid_list);
|
||||
INIT_LIST_HEAD(&dev->sta_poll_list);
|
||||
dev->vif_mask = 0;
|
||||
memset(dev->wcid_mask, 0, sizeof(dev->wcid_mask));
|
||||
|
||||
mt76_reset_phy(&dev->phy);
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phys); i++)
|
||||
mt76_reset_phy(dev->phys[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_reset_device);
|
||||
|
||||
struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
@ -1679,6 +1716,10 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
|||
skb_queue_splice_tail_init(&wcid->tx_pending, &list);
|
||||
spin_unlock(&wcid->tx_pending.lock);
|
||||
|
||||
spin_lock(&wcid->tx_offchannel.lock);
|
||||
skb_queue_splice_tail_init(&wcid->tx_offchannel, &list);
|
||||
spin_unlock(&wcid->tx_offchannel.lock);
|
||||
|
||||
spin_unlock_bh(&phy->tx_lock);
|
||||
|
||||
while ((skb = __skb_dequeue(&list)) != NULL) {
|
||||
|
|
@ -1690,7 +1731,7 @@ EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
|
|||
|
||||
void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||
{
|
||||
if (test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
if (test_bit(MT76_MCU_RESET, &dev->phy.state) || !wcid->sta)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
|
|
|
|||
|
|
@ -1243,6 +1243,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
|||
struct ieee80211_rate *rates, int n_rates);
|
||||
void mt76_unregister_device(struct mt76_dev *dev);
|
||||
void mt76_free_device(struct mt76_dev *dev);
|
||||
void mt76_reset_device(struct mt76_dev *dev);
|
||||
void mt76_unregister_phy(struct mt76_phy *phy);
|
||||
|
||||
struct mt76_phy *mt76_alloc_radio_phy(struct mt76_dev *dev, unsigned int size,
|
||||
|
|
|
|||
|
|
@ -1460,17 +1460,15 @@ mt7915_mac_full_reset(struct mt7915_dev *dev)
|
|||
if (i == 10)
|
||||
dev_err(dev->mt76.dev, "chip full reset failed\n");
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
while (!list_empty(&dev->mt76.sta_poll_list))
|
||||
list_del_init(dev->mt76.sta_poll_list.next);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
memset(dev->mt76.wcid_mask, 0, sizeof(dev->mt76.wcid_mask));
|
||||
dev->mt76.vif_mask = 0;
|
||||
dev->phy.omac_mask = 0;
|
||||
if (phy2)
|
||||
phy2->omac_mask = 0;
|
||||
|
||||
mt76_reset_device(&dev->mt76);
|
||||
|
||||
INIT_LIST_HEAD(&dev->sta_rc_list);
|
||||
INIT_LIST_HEAD(&dev->twt_list);
|
||||
|
||||
i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
|
||||
dev->mt76.global_wcid.idx = i;
|
||||
dev->recovery.hw_full_reset = false;
|
||||
|
|
|
|||
|
|
@ -1459,11 +1459,8 @@ static int mt7921_pre_channel_switch(struct ieee80211_hw *hw,
|
|||
if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Avoid beacon loss due to the CAC(Channel Availability Check) time
|
||||
* of the AP.
|
||||
*/
|
||||
if (!cfg80211_chandef_usable(hw->wiphy, &chsw->chandef,
|
||||
IEEE80211_CHAN_RADAR))
|
||||
IEEE80211_CHAN_DISABLED))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1449,7 +1449,7 @@ void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
|||
sta = wcid_to_sta(wcid);
|
||||
|
||||
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt76_connac2_tx_check_aggr(sta, txwi);
|
||||
mt7925_tx_check_aggr(sta, e->skb, wcid);
|
||||
|
||||
skb_pull(e->skb, headroom);
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
|
|
|
|||
|
|
@ -1191,6 +1191,9 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
|||
struct mt792x_bss_conf *mconf;
|
||||
struct mt792x_link_sta *mlink;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
break;
|
||||
|
||||
link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
|
||||
if (!link_sta)
|
||||
continue;
|
||||
|
|
@ -2069,8 +2072,10 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
GFP_KERNEL);
|
||||
mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink),
|
||||
GFP_KERNEL);
|
||||
if (!mconf || !mlink)
|
||||
if (!mconf || !mlink) {
|
||||
mt792x_mutex_release(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
mconfs[link_id] = mconf;
|
||||
|
|
|
|||
|
|
@ -1834,13 +1834,13 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb,
|
|||
struct tlv *tlv;
|
||||
u16 eml_cap;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld));
|
||||
eht_mld = (struct sta_rec_eht_mld *)tlv;
|
||||
eht_mld->mld_type = 0xff;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
ext_capa = cfg80211_get_iftype_ext_capa(wiphy,
|
||||
ieee80211_vif_type_p2p(vif));
|
||||
if (!ext_capa)
|
||||
|
|
@ -1912,6 +1912,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
|||
struct mt76_dev *dev = phy->dev;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct sk_buff *skb;
|
||||
int conn_state;
|
||||
|
||||
mconf = mt792x_vif_to_link(mvif, info->wcid->link_id);
|
||||
|
||||
|
|
@ -1920,10 +1921,13 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
|||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
conn_state = info->enable ? CONN_STATE_PORT_SECURE :
|
||||
CONN_STATE_DISCONNECT;
|
||||
|
||||
if (info->enable && info->link_sta) {
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
|
||||
info->link_sta,
|
||||
info->enable, info->newly);
|
||||
conn_state, info->newly);
|
||||
mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta);
|
||||
mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
|
|||
int i;
|
||||
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
if (!wcid)
|
||||
if (!wcid || !wcid->sta)
|
||||
return NULL;
|
||||
|
||||
if (!mt7996_band_valid(dev, band_idx))
|
||||
|
|
@ -903,8 +903,12 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
|||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
|
||||
mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
|
||||
if (mvif)
|
||||
mlink = rcu_dereference(mvif->mt76.link[link_id]);
|
||||
if (mvif) {
|
||||
if (wcid->offchannel)
|
||||
mlink = rcu_dereference(mvif->mt76.offchannel_link);
|
||||
if (!mlink)
|
||||
mlink = rcu_dereference(mvif->mt76.link[link_id]);
|
||||
}
|
||||
|
||||
if (mlink) {
|
||||
omac_idx = mlink->omac_idx;
|
||||
|
|
@ -1243,8 +1247,10 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
|||
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
sta = wcid_to_sta(wcid);
|
||||
if (!sta)
|
||||
if (!sta) {
|
||||
link_sta = NULL;
|
||||
goto next;
|
||||
}
|
||||
|
||||
link_sta = rcu_dereference(sta->link[wcid->link_id]);
|
||||
if (!link_sta)
|
||||
|
|
@ -1694,17 +1700,37 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state)
|
|||
static void
|
||||
mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_hw *hw = priv;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct mt7996_phy *phy = priv;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
unsigned int link_id;
|
||||
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_AP:
|
||||
mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link || link->phy != phy)
|
||||
continue;
|
||||
|
||||
mt7996_mcu_add_beacon(dev->mt76.hw, vif, link_conf);
|
||||
}
|
||||
}
|
||||
|
||||
void mt7996_mac_update_beacons(struct mt7996_phy *phy)
|
||||
{
|
||||
ieee80211_iterate_active_interfaces(phy->mt76->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, phy);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1712,25 +1738,15 @@ mt7996_update_beacons(struct mt7996_dev *dev)
|
|||
{
|
||||
struct mt76_phy *phy2, *phy3;
|
||||
|
||||
ieee80211_iterate_active_interfaces(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, dev->mt76.hw);
|
||||
mt7996_mac_update_beacons(&dev->phy);
|
||||
|
||||
phy2 = dev->mt76.phys[MT_BAND1];
|
||||
if (!phy2)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces(phy2->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, phy2->hw);
|
||||
if (phy2)
|
||||
mt7996_mac_update_beacons(phy2->priv);
|
||||
|
||||
phy3 = dev->mt76.phys[MT_BAND2];
|
||||
if (!phy3)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces(phy3->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, phy3->hw);
|
||||
if (phy3)
|
||||
mt7996_mac_update_beacons(phy3->priv);
|
||||
}
|
||||
|
||||
void mt7996_tx_token_put(struct mt7996_dev *dev)
|
||||
|
|
|
|||
|
|
@ -516,6 +516,9 @@ int mt7996_set_channel(struct mt76_phy *mphy)
|
|||
struct mt7996_phy *phy = mphy->priv;
|
||||
int ret;
|
||||
|
||||
if (mphy->offchannel)
|
||||
mt7996_mac_update_beacons(phy);
|
||||
|
||||
ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
@ -533,6 +536,8 @@ int mt7996_set_channel(struct mt76_phy *mphy)
|
|||
|
||||
mt7996_mac_reset_counters(phy);
|
||||
phy->noise = 0;
|
||||
if (!mphy->offchannel)
|
||||
mt7996_mac_update_beacons(phy);
|
||||
|
||||
out:
|
||||
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
|
||||
|
|
|
|||
|
|
@ -1879,8 +1879,8 @@ mt7996_mcu_get_mmps_mode(enum ieee80211_smps_mode smps)
|
|||
int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
|
||||
void *data, u16 version)
|
||||
{
|
||||
struct uni_header hdr = {};
|
||||
struct ra_fixed_rate *req;
|
||||
struct uni_header hdr;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
int len;
|
||||
|
|
@ -2755,13 +2755,15 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt76_vif_link *mlink = mt76_vif_conf_link(&dev->mt76, vif, link_conf);
|
||||
struct mt7996_vif_link *link = mt7996_vif_conf_link(dev, vif, link_conf);
|
||||
struct mt76_vif_link *mlink = link ? &link->mt76 : NULL;
|
||||
struct ieee80211_mutable_offsets offs;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct sk_buff *skb, *rskb;
|
||||
struct tlv *tlv;
|
||||
struct bss_bcn_content_tlv *bcn;
|
||||
int len, extra_len = 0;
|
||||
bool enabled = link_conf->enable_beacon;
|
||||
|
||||
if (link_conf->nontransmitted)
|
||||
return 0;
|
||||
|
|
@ -2769,13 +2771,16 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
if (!mlink)
|
||||
return -EINVAL;
|
||||
|
||||
if (link->phy && link->phy->mt76->offchannel)
|
||||
enabled = false;
|
||||
|
||||
rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink,
|
||||
MT7996_MAX_BSS_OFFLOAD_SIZE);
|
||||
if (IS_ERR(rskb))
|
||||
return PTR_ERR(rskb);
|
||||
|
||||
skb = ieee80211_beacon_get_template(hw, vif, &offs, link_conf->link_id);
|
||||
if (link_conf->enable_beacon && !skb) {
|
||||
if (enabled && !skb) {
|
||||
dev_kfree_skb(rskb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -2794,7 +2799,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
len = ALIGN(sizeof(*bcn) + MT_TXD_SIZE + extra_len, 4);
|
||||
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len);
|
||||
bcn = (struct bss_bcn_content_tlv *)tlv;
|
||||
bcn->enable = link_conf->enable_beacon;
|
||||
bcn->enable = enabled;
|
||||
if (!bcn->enable)
|
||||
goto out;
|
||||
|
||||
|
|
@ -3372,7 +3377,7 @@ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans)
|
|||
{
|
||||
struct {
|
||||
u8 __rsv[4];
|
||||
} __packed hdr;
|
||||
} __packed hdr = {};
|
||||
struct hdr_trans_blacklist *req_blacklist;
|
||||
struct hdr_trans_en *req_en;
|
||||
struct sk_buff *skb;
|
||||
|
|
|
|||
|
|
@ -732,6 +732,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
|||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed);
|
||||
void mt7996_mac_update_beacons(struct mt7996_phy *phy);
|
||||
void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
|
||||
void mt7996_mac_work(struct work_struct *work);
|
||||
void mt7996_mac_reset_work(struct work_struct *work);
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
|||
struct mt76_wcid *wcid, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
struct sk_buff_head *head;
|
||||
|
||||
if (mt76_testmode_enabled(phy)) {
|
||||
|
|
@ -349,7 +350,8 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
|||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
|
||||
|
||||
if ((info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
|
||||
(info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK))
|
||||
((info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK) &&
|
||||
ieee80211_is_probe_req(hdr->frame_control)))
|
||||
head = &wcid->tx_offchannel;
|
||||
else
|
||||
head = &wcid->tx_pending;
|
||||
|
|
@ -644,6 +646,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid,
|
|||
static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
||||
{
|
||||
LIST_HEAD(tx_list);
|
||||
int ret = 0;
|
||||
|
||||
if (list_empty(&phy->tx_list))
|
||||
return;
|
||||
|
|
@ -655,13 +658,13 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
|||
list_splice_init(&phy->tx_list, &tx_list);
|
||||
while (!list_empty(&tx_list)) {
|
||||
struct mt76_wcid *wcid;
|
||||
int ret;
|
||||
|
||||
wcid = list_first_entry(&tx_list, struct mt76_wcid, tx_list);
|
||||
list_del_init(&wcid->tx_list);
|
||||
|
||||
spin_unlock(&phy->tx_lock);
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel);
|
||||
if (ret >= 0)
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel);
|
||||
if (ret >= 0 && !phy->offchannel)
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_pending);
|
||||
spin_lock(&phy->tx_lock);
|
||||
|
|
@ -670,9 +673,6 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
|||
!skb_queue_empty(&wcid->tx_offchannel) &&
|
||||
list_empty(&wcid->tx_list))
|
||||
list_add_tail(&wcid->tx_list, &phy->tx_list);
|
||||
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&phy->tx_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ static const struct wilc_cfg_word g_cfg_word[] = {
|
|||
};
|
||||
|
||||
static const struct wilc_cfg_str g_cfg_str[] = {
|
||||
{WID_FIRMWARE_VERSION, NULL},
|
||||
{WID_MAC_ADDR, NULL},
|
||||
{WID_ASSOC_RES_INFO, NULL},
|
||||
{WID_NIL, NULL}
|
||||
{WID_FIRMWARE_VERSION, 0, NULL},
|
||||
{WID_MAC_ADDR, 0, NULL},
|
||||
{WID_ASSOC_RES_INFO, 0, NULL},
|
||||
{WID_NIL, 0, NULL}
|
||||
};
|
||||
|
||||
#define WILC_RESP_MSG_TYPE_CONFIG_REPLY 'R'
|
||||
|
|
@ -147,44 +147,58 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size)
|
|||
|
||||
switch (FIELD_GET(WILC_WID_TYPE, wid)) {
|
||||
case WID_CHAR:
|
||||
len = 3;
|
||||
if (len + 2 > size)
|
||||
return;
|
||||
|
||||
while (cfg->b[i].id != WID_NIL && cfg->b[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->b[i].id == wid)
|
||||
cfg->b[i].val = info[4];
|
||||
|
||||
len = 3;
|
||||
break;
|
||||
|
||||
case WID_SHORT:
|
||||
len = 4;
|
||||
if (len + 2 > size)
|
||||
return;
|
||||
|
||||
while (cfg->hw[i].id != WID_NIL && cfg->hw[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->hw[i].id == wid)
|
||||
cfg->hw[i].val = get_unaligned_le16(&info[4]);
|
||||
|
||||
len = 4;
|
||||
break;
|
||||
|
||||
case WID_INT:
|
||||
len = 6;
|
||||
if (len + 2 > size)
|
||||
return;
|
||||
|
||||
while (cfg->w[i].id != WID_NIL && cfg->w[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->w[i].id == wid)
|
||||
cfg->w[i].val = get_unaligned_le32(&info[4]);
|
||||
|
||||
len = 6;
|
||||
break;
|
||||
|
||||
case WID_STR:
|
||||
len = 2 + get_unaligned_le16(&info[2]);
|
||||
|
||||
while (cfg->s[i].id != WID_NIL && cfg->s[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->s[i].id == wid)
|
||||
memcpy(cfg->s[i].str, &info[2],
|
||||
get_unaligned_le16(&info[2]) + 2);
|
||||
if (cfg->s[i].id == wid) {
|
||||
if (len > cfg->s[i].len || (len + 2 > size))
|
||||
return;
|
||||
|
||||
memcpy(cfg->s[i].str, &info[2],
|
||||
len);
|
||||
}
|
||||
|
||||
len = 2 + get_unaligned_le16(&info[2]);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -384,12 +398,15 @@ int wilc_wlan_cfg_init(struct wilc *wl)
|
|||
/* store the string cfg parameters */
|
||||
wl->cfg.s[i].id = WID_FIRMWARE_VERSION;
|
||||
wl->cfg.s[i].str = str_vals->firmware_version;
|
||||
wl->cfg.s[i].len = sizeof(str_vals->firmware_version);
|
||||
i++;
|
||||
wl->cfg.s[i].id = WID_MAC_ADDR;
|
||||
wl->cfg.s[i].str = str_vals->mac_address;
|
||||
wl->cfg.s[i].len = sizeof(str_vals->mac_address);
|
||||
i++;
|
||||
wl->cfg.s[i].id = WID_ASSOC_RES_INFO;
|
||||
wl->cfg.s[i].str = str_vals->assoc_rsp;
|
||||
wl->cfg.s[i].len = sizeof(str_vals->assoc_rsp);
|
||||
i++;
|
||||
wl->cfg.s[i].id = WID_NIL;
|
||||
wl->cfg.s[i].str = NULL;
|
||||
|
|
|
|||
|
|
@ -24,12 +24,13 @@ struct wilc_cfg_word {
|
|||
|
||||
struct wilc_cfg_str {
|
||||
u16 id;
|
||||
u16 len;
|
||||
u8 *str;
|
||||
};
|
||||
|
||||
struct wilc_cfg_str_vals {
|
||||
u8 mac_address[7];
|
||||
u8 firmware_version[129];
|
||||
u8 mac_address[8];
|
||||
u8 firmware_version[130];
|
||||
u8 assoc_rsp[WILC_MAX_ASSOC_RESP_FRAME_SIZE];
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ config RT2800PCI
|
|||
select RT2X00_LIB_PCI
|
||||
select RT2X00_LIB_FIRMWARE
|
||||
select RT2X00_LIB_CRYPTO
|
||||
select CRC_CCITT
|
||||
select EEPROM_93CX6
|
||||
help
|
||||
This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
|
||||
|
|
@ -142,7 +141,6 @@ config RT2800USB
|
|||
select RT2X00_LIB_USB
|
||||
select RT2X00_LIB_FIRMWARE
|
||||
select RT2X00_LIB_CRYPTO
|
||||
select CRC_CCITT
|
||||
help
|
||||
This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
|
||||
Supported chips: RT2770, RT2870 & RT3070, RT3071 & RT3072
|
||||
|
|
@ -217,6 +215,7 @@ config RT2800SOC
|
|||
|
||||
config RT2800_LIB
|
||||
tristate
|
||||
select CRC_CCITT
|
||||
|
||||
config RT2800_LIB_MMIO
|
||||
tristate
|
||||
|
|
@ -225,6 +224,7 @@ config RT2800_LIB_MMIO
|
|||
|
||||
config RT2X00_LIB_MMIO
|
||||
tristate
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB_PCI
|
||||
tristate
|
||||
|
|
|
|||
|
|
@ -1291,7 +1291,7 @@ static void cw1200_do_join(struct cw1200_common *priv)
|
|||
rcu_read_lock();
|
||||
ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
|
||||
if (ssidie) {
|
||||
join.ssid_len = ssidie[1];
|
||||
join.ssid_len = min(ssidie[1], IEEE80211_MAX_SSID_LEN);
|
||||
memcpy(join.ssid, &ssidie[2], join.ssid_len);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
|
|
|||
|
|
@ -4557,8 +4557,7 @@ ptp_ocp_detach(struct ptp_ocp *bp)
|
|||
ptp_ocp_debugfs_remove_device(bp);
|
||||
ptp_ocp_detach_sysfs(bp);
|
||||
ptp_ocp_attr_group_del(bp);
|
||||
if (timer_pending(&bp->watchdog))
|
||||
timer_delete_sync(&bp->watchdog);
|
||||
timer_delete_sync(&bp->watchdog);
|
||||
if (bp->ts0)
|
||||
ptp_ocp_unregister_ext(bp->ts0);
|
||||
if (bp->ts1)
|
||||
|
|
|
|||
|
|
@ -169,6 +169,11 @@ static inline bool phy_interface_empty(const unsigned long *intf)
|
|||
return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX);
|
||||
}
|
||||
|
||||
static inline unsigned int phy_interface_weight(const unsigned long *intf)
|
||||
{
|
||||
return bitmap_weight(intf, PHY_INTERFACE_MODE_MAX);
|
||||
}
|
||||
|
||||
static inline void phy_interface_and(unsigned long *dst, const unsigned long *a,
|
||||
const unsigned long *b)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ struct sk_filter;
|
|||
* @sk_ack_backlog: current listen backlog
|
||||
* @sk_max_ack_backlog: listen backlog set in listen()
|
||||
* @sk_uid: user id of owner
|
||||
* @sk_ino: inode number (zero if orphaned)
|
||||
* @sk_prefer_busy_poll: prefer busypolling over softirq processing
|
||||
* @sk_busy_poll_budget: napi processing budget when busypolling
|
||||
* @sk_priority: %SO_PRIORITY setting
|
||||
|
|
@ -518,6 +519,7 @@ struct sock {
|
|||
u32 sk_ack_backlog;
|
||||
u32 sk_max_ack_backlog;
|
||||
kuid_t sk_uid;
|
||||
unsigned long sk_ino;
|
||||
spinlock_t sk_peer_lock;
|
||||
int sk_bind_phc;
|
||||
struct pid *sk_peer_pid;
|
||||
|
|
@ -2056,6 +2058,10 @@ static inline int sk_rx_queue_get(const struct sock *sk)
|
|||
static inline void sk_set_socket(struct sock *sk, struct socket *sock)
|
||||
{
|
||||
sk->sk_socket = sock;
|
||||
if (sock) {
|
||||
WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid);
|
||||
WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino);
|
||||
}
|
||||
}
|
||||
|
||||
static inline wait_queue_head_t *sk_sleep(struct sock *sk)
|
||||
|
|
@ -2077,6 +2083,7 @@ static inline void sock_orphan(struct sock *sk)
|
|||
sk_set_socket(sk, NULL);
|
||||
sk->sk_wq = NULL;
|
||||
/* Note: sk_uid is unchanged. */
|
||||
WRITE_ONCE(sk->sk_ino, 0);
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
|
|
@ -2087,20 +2094,22 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
|
|||
rcu_assign_pointer(sk->sk_wq, &parent->wq);
|
||||
parent->sk = sk;
|
||||
sk_set_socket(sk, parent);
|
||||
WRITE_ONCE(sk->sk_uid, SOCK_INODE(parent)->i_uid);
|
||||
security_sock_graft(sk, parent);
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
static inline unsigned long sock_i_ino(const struct sock *sk)
|
||||
{
|
||||
/* Paired with WRITE_ONCE() in sock_graft() and sock_orphan() */
|
||||
return READ_ONCE(sk->sk_ino);
|
||||
}
|
||||
|
||||
static inline kuid_t sk_uid(const struct sock *sk)
|
||||
{
|
||||
/* Paired with WRITE_ONCE() in sockfs_setattr() */
|
||||
return READ_ONCE(sk->sk_uid);
|
||||
}
|
||||
|
||||
unsigned long __sock_i_ino(struct sock *sk);
|
||||
unsigned long sock_i_ino(struct sock *sk);
|
||||
|
||||
static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk)
|
||||
{
|
||||
return sk ? sk_uid(sk) : make_kuid(net->user_ns, 0);
|
||||
|
|
|
|||
|
|
@ -1784,10 +1784,12 @@ enum nft_synproxy_attributes {
|
|||
* enum nft_device_attributes - nf_tables device netlink attributes
|
||||
*
|
||||
* @NFTA_DEVICE_NAME: name of this device (NLA_STRING)
|
||||
* @NFTA_DEVICE_PREFIX: device name prefix, a simple wildcard (NLA_STRING)
|
||||
*/
|
||||
enum nft_devices_attributes {
|
||||
NFTA_DEVICE_UNSPEC,
|
||||
NFTA_DEVICE_NAME,
|
||||
NFTA_DEVICE_PREFIX,
|
||||
__NFTA_DEVICE_MAX
|
||||
};
|
||||
#define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1)
|
||||
|
|
|
|||
|
|
@ -112,7 +112,9 @@ struct atm_dev *atm_dev_register(const char *type, struct device *parent,
|
|||
|
||||
if (atm_proc_dev_register(dev) < 0) {
|
||||
pr_err("atm_proc_dev_register failed for dev %s\n", type);
|
||||
goto out_fail;
|
||||
mutex_unlock(&atm_dev_mutex);
|
||||
kfree(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (atm_register_sysfs(dev, parent) < 0) {
|
||||
|
|
@ -128,7 +130,7 @@ struct atm_dev *atm_dev_register(const char *type, struct device *parent,
|
|||
return dev;
|
||||
|
||||
out_fail:
|
||||
kfree(dev);
|
||||
put_device(&dev->class_dev);
|
||||
dev = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -433,6 +433,10 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||
int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *ptype, struct net_device *orig_dev)
|
||||
{
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return NET_RX_DROP;
|
||||
|
||||
skb_orphan(skb);
|
||||
|
||||
if (!net_eq(dev_net(dev), &init_net)) {
|
||||
|
|
|
|||
|
|
@ -1687,7 +1687,12 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
|||
|
||||
coding_len = ntohs(coded_packet_tmp.coded_len);
|
||||
|
||||
if (coding_len > skb->len)
|
||||
/* ensure dst buffer is large enough (payload only) */
|
||||
if (coding_len + h_size > skb->len)
|
||||
return NULL;
|
||||
|
||||
/* ensure src buffer is large enough (payload only) */
|
||||
if (coding_len + h_size > nc_packet->skb->len)
|
||||
return NULL;
|
||||
|
||||
/* Here the magic is reversed:
|
||||
|
|
|
|||
|
|
@ -1422,7 +1422,10 @@ static int l2cap_sock_release(struct socket *sock)
|
|||
if (!sk)
|
||||
return 0;
|
||||
|
||||
lock_sock_nested(sk, L2CAP_NESTING_PARENT);
|
||||
l2cap_sock_cleanup_listen(sk);
|
||||
release_sock(sk);
|
||||
|
||||
bt_sock_unlink(&l2cap_sk_list, sk);
|
||||
|
||||
err = l2cap_sock_shutdown(sock, SHUT_RDWR);
|
||||
|
|
|
|||
|
|
@ -626,9 +626,6 @@ static unsigned int br_nf_local_in(void *priv,
|
|||
break;
|
||||
}
|
||||
|
||||
ct = container_of(nfct, struct nf_conn, ct_general);
|
||||
WARN_ON_ONCE(!nf_ct_is_confirmed(ct));
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -90,10 +90,12 @@ static void est_timer(struct timer_list *t)
|
|||
rate = (b_packets - est->last_packets) << (10 - est->intvl_log);
|
||||
rate = (rate >> est->ewma_log) - (est->avpps >> est->ewma_log);
|
||||
|
||||
preempt_disable_nested();
|
||||
write_seqcount_begin(&est->seq);
|
||||
est->avbps += brate;
|
||||
est->avpps += rate;
|
||||
write_seqcount_end(&est->seq);
|
||||
preempt_enable_nested();
|
||||
|
||||
est->last_bytes = b_bytes;
|
||||
est->last_packets = b_packets;
|
||||
|
|
|
|||
|
|
@ -2780,28 +2780,6 @@ void sock_pfree(struct sk_buff *skb)
|
|||
EXPORT_SYMBOL(sock_pfree);
|
||||
#endif /* CONFIG_INET */
|
||||
|
||||
unsigned long __sock_i_ino(struct sock *sk)
|
||||
{
|
||||
unsigned long ino;
|
||||
|
||||
read_lock(&sk->sk_callback_lock);
|
||||
ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0;
|
||||
read_unlock(&sk->sk_callback_lock);
|
||||
return ino;
|
||||
}
|
||||
EXPORT_SYMBOL(__sock_i_ino);
|
||||
|
||||
unsigned long sock_i_ino(struct sock *sk)
|
||||
{
|
||||
unsigned long ino;
|
||||
|
||||
local_bh_disable();
|
||||
ino = __sock_i_ino(sk);
|
||||
local_bh_enable();
|
||||
return ino;
|
||||
}
|
||||
EXPORT_SYMBOL(sock_i_ino);
|
||||
|
||||
/*
|
||||
* Allocate a skb from the socket's send buffer.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -340,14 +340,13 @@ static void inetdev_destroy(struct in_device *in_dev)
|
|||
|
||||
static int __init inet_blackhole_dev_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
struct in_device *in_dev;
|
||||
|
||||
rtnl_lock();
|
||||
if (!inetdev_init(blackhole_netdev))
|
||||
err = -ENOMEM;
|
||||
in_dev = inetdev_init(blackhole_netdev);
|
||||
rtnl_unlock();
|
||||
|
||||
return err;
|
||||
return PTR_ERR_OR_ZERO(in_dev);
|
||||
}
|
||||
late_initcall(inet_blackhole_dev_init);
|
||||
|
||||
|
|
|
|||
|
|
@ -799,11 +799,12 @@ void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info)
|
|||
struct sk_buff *cloned_skb = NULL;
|
||||
struct ip_options opts = { 0 };
|
||||
enum ip_conntrack_info ctinfo;
|
||||
enum ip_conntrack_dir dir;
|
||||
struct nf_conn *ct;
|
||||
__be32 orig_ip;
|
||||
|
||||
ct = nf_ct_get(skb_in, &ctinfo);
|
||||
if (!ct || !(ct->status & IPS_SRC_NAT)) {
|
||||
if (!ct || !(READ_ONCE(ct->status) & IPS_NAT_MASK)) {
|
||||
__icmp_send(skb_in, type, code, info, &opts);
|
||||
return;
|
||||
}
|
||||
|
|
@ -818,7 +819,8 @@ void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info)
|
|||
goto out;
|
||||
|
||||
orig_ip = ip_hdr(skb_in)->saddr;
|
||||
ip_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.ip;
|
||||
dir = CTINFO2DIR(ctinfo);
|
||||
ip_hdr(skb_in)->saddr = ct->tuplehash[dir].tuple.src.u3.ip;
|
||||
__icmp_send(skb_in, type, code, info, &opts);
|
||||
ip_hdr(skb_in)->saddr = orig_ip;
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -494,10 +494,8 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
|
|||
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
|
||||
accept_rpl_seg = net->ipv6.devconf_all->rpl_seg_enabled;
|
||||
if (accept_rpl_seg > idev->cnf.rpl_seg_enabled)
|
||||
accept_rpl_seg = idev->cnf.rpl_seg_enabled;
|
||||
|
||||
accept_rpl_seg = min(READ_ONCE(net->ipv6.devconf_all->rpl_seg_enabled),
|
||||
READ_ONCE(idev->cnf.rpl_seg_enabled));
|
||||
if (!accept_rpl_seg) {
|
||||
kfree_skb(skb);
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -54,11 +54,12 @@ void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info)
|
|||
struct inet6_skb_parm parm = { 0 };
|
||||
struct sk_buff *cloned_skb = NULL;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
enum ip_conntrack_dir dir;
|
||||
struct in6_addr orig_ip;
|
||||
struct nf_conn *ct;
|
||||
|
||||
ct = nf_ct_get(skb_in, &ctinfo);
|
||||
if (!ct || !(ct->status & IPS_SRC_NAT)) {
|
||||
if (!ct || !(READ_ONCE(ct->status) & IPS_NAT_MASK)) {
|
||||
__icmpv6_send(skb_in, type, code, info, &parm);
|
||||
return;
|
||||
}
|
||||
|
|
@ -73,7 +74,8 @@ void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info)
|
|||
goto out;
|
||||
|
||||
orig_ip = ipv6_hdr(skb_in)->saddr;
|
||||
ipv6_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.in6;
|
||||
dir = CTINFO2DIR(ctinfo);
|
||||
ipv6_hdr(skb_in)->saddr = ct->tuplehash[dir].tuple.src.u3.in6;
|
||||
__icmpv6_send(skb_in, type, code, info, &parm);
|
||||
ipv6_hdr(skb_in)->saddr = orig_ip;
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -1431,17 +1431,17 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
|||
ireq = inet_rsk(req);
|
||||
|
||||
if (sk_acceptq_is_full(sk))
|
||||
goto out_overflow;
|
||||
goto exit_overflow;
|
||||
|
||||
if (!dst) {
|
||||
dst = inet6_csk_route_req(sk, &fl6, req, IPPROTO_TCP);
|
||||
if (!dst)
|
||||
goto out;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
newsk = tcp_create_openreq_child(sk, req, skb);
|
||||
if (!newsk)
|
||||
goto out_nonewsk;
|
||||
goto exit_nonewsk;
|
||||
|
||||
/*
|
||||
* No need to charge this sock to the relevant IPv6 refcnt debug socks
|
||||
|
|
@ -1525,25 +1525,19 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
|||
const union tcp_md5_addr *addr;
|
||||
|
||||
addr = (union tcp_md5_addr *)&newsk->sk_v6_daddr;
|
||||
if (tcp_md5_key_copy(newsk, addr, AF_INET6, 128, l3index, key)) {
|
||||
inet_csk_prepare_forced_close(newsk);
|
||||
tcp_done(newsk);
|
||||
goto out;
|
||||
}
|
||||
if (tcp_md5_key_copy(newsk, addr, AF_INET6, 128, l3index, key))
|
||||
goto put_and_exit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_TCP_AO
|
||||
/* Copy over tcp_ao_info if any */
|
||||
if (tcp_ao_copy_all_matching(sk, newsk, req, skb, AF_INET6))
|
||||
goto out; /* OOM */
|
||||
goto put_and_exit; /* OOM */
|
||||
#endif
|
||||
|
||||
if (__inet_inherit_port(sk, newsk) < 0) {
|
||||
inet_csk_prepare_forced_close(newsk);
|
||||
tcp_done(newsk);
|
||||
goto out;
|
||||
}
|
||||
if (__inet_inherit_port(sk, newsk) < 0)
|
||||
goto put_and_exit;
|
||||
*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash),
|
||||
&found_dup_sk);
|
||||
if (*own_req) {
|
||||
|
|
@ -1570,13 +1564,17 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
|||
|
||||
return newsk;
|
||||
|
||||
out_overflow:
|
||||
exit_overflow:
|
||||
__NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
|
||||
out_nonewsk:
|
||||
exit_nonewsk:
|
||||
dst_release(dst);
|
||||
out:
|
||||
exit:
|
||||
tcp_listendrop(sk);
|
||||
return NULL;
|
||||
put_and_exit:
|
||||
inet_csk_prepare_forced_close(newsk);
|
||||
tcp_done(newsk);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
|
||||
|
|
|
|||
|
|
@ -1416,7 +1416,7 @@ drv_get_ftm_responder_stats(struct ieee80211_local *local,
|
|||
struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_ftm_responder_stats *ftm_stats)
|
||||
{
|
||||
u32 ret = -EOPNOTSUPP;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
might_sleep();
|
||||
lockdep_assert_wiphy(local->hw.wiphy);
|
||||
|
|
|
|||
|
|
@ -1111,7 +1111,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
int result, i;
|
||||
enum nl80211_band band;
|
||||
int channels, max_bitrates;
|
||||
bool supp_ht, supp_vht, supp_he, supp_eht;
|
||||
bool supp_ht, supp_vht, supp_he, supp_eht, supp_s1g;
|
||||
struct cfg80211_chan_def dflt_chandef = {};
|
||||
|
||||
if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
|
||||
|
|
@ -1227,6 +1227,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
supp_vht = false;
|
||||
supp_he = false;
|
||||
supp_eht = false;
|
||||
supp_s1g = false;
|
||||
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
||||
const struct ieee80211_sband_iftype_data *iftd;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
|
@ -1274,6 +1275,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
max_bitrates = sband->n_bitrates;
|
||||
supp_ht = supp_ht || sband->ht_cap.ht_supported;
|
||||
supp_vht = supp_vht || sband->vht_cap.vht_supported;
|
||||
supp_s1g = supp_s1g || sband->s1g_cap.s1g;
|
||||
|
||||
for_each_sband_iftype_data(sband, i, iftd) {
|
||||
u8 he_40_mhz_cap;
|
||||
|
|
@ -1406,6 +1408,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
local->scan_ies_len +=
|
||||
2 + sizeof(struct ieee80211_vht_cap);
|
||||
|
||||
if (supp_s1g)
|
||||
local->scan_ies_len += 2 + sizeof(struct ieee80211_s1g_cap);
|
||||
|
||||
/*
|
||||
* HE cap element is variable in size - set len to allow max size */
|
||||
if (supp_he) {
|
||||
|
|
|
|||
|
|
@ -1189,6 +1189,14 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
|
|||
"required MCSes not supported, disabling EHT\n");
|
||||
}
|
||||
|
||||
if (conn->mode >= IEEE80211_CONN_MODE_EHT &&
|
||||
channel->band != NL80211_BAND_2GHZ &&
|
||||
conn->bw_limit == IEEE80211_CONN_BW_LIMIT_40) {
|
||||
conn->mode = IEEE80211_CONN_MODE_HE;
|
||||
link_id_info(sdata, link_id,
|
||||
"required bandwidth not supported, disabling EHT\n");
|
||||
}
|
||||
|
||||
/* the mode can only decrease, so this must terminate */
|
||||
if (ap_mode != conn->mode) {
|
||||
kfree(elems);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* KUnit tests for channel mode functions
|
||||
*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#include <net/cfg80211.h>
|
||||
#include <kunit/test.h>
|
||||
|
|
@ -28,6 +28,10 @@ static const struct determine_chan_mode_case {
|
|||
u8 vht_basic_mcs_1_4, vht_basic_mcs_5_8;
|
||||
u8 he_basic_mcs_1_4, he_basic_mcs_5_8;
|
||||
u8 eht_mcs7_min_nss;
|
||||
u16 eht_disabled_subchannels;
|
||||
u8 eht_bw;
|
||||
enum ieee80211_conn_bw_limit conn_bw_limit;
|
||||
enum ieee80211_conn_bw_limit expected_bw_limit;
|
||||
int error;
|
||||
} determine_chan_mode_cases[] = {
|
||||
{
|
||||
|
|
@ -128,6 +132,14 @@ static const struct determine_chan_mode_case {
|
|||
.conn_mode = IEEE80211_CONN_MODE_EHT,
|
||||
.eht_mcs7_min_nss = 0x15,
|
||||
.error = EINVAL,
|
||||
}, {
|
||||
.desc = "80 MHz EHT is downgraded to 40 MHz HE due to puncturing",
|
||||
.conn_mode = IEEE80211_CONN_MODE_EHT,
|
||||
.expected_mode = IEEE80211_CONN_MODE_HE,
|
||||
.conn_bw_limit = IEEE80211_CONN_BW_LIMIT_80,
|
||||
.expected_bw_limit = IEEE80211_CONN_BW_LIMIT_40,
|
||||
.eht_disabled_subchannels = 0x08,
|
||||
.eht_bw = IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ,
|
||||
}
|
||||
};
|
||||
KUNIT_ARRAY_PARAM_DESC(determine_chan_mode, determine_chan_mode_cases, desc)
|
||||
|
|
@ -138,7 +150,7 @@ static void test_determine_chan_mode(struct kunit *test)
|
|||
struct t_sdata *t_sdata = T_SDATA(test);
|
||||
struct ieee80211_conn_settings conn = {
|
||||
.mode = params->conn_mode,
|
||||
.bw_limit = IEEE80211_CONN_BW_LIMIT_20,
|
||||
.bw_limit = params->conn_bw_limit,
|
||||
};
|
||||
struct cfg80211_bss cbss = {
|
||||
.channel = &t_sdata->band_5ghz.channels[0],
|
||||
|
|
@ -191,14 +203,21 @@ static void test_determine_chan_mode(struct kunit *test)
|
|||
0x7f, 0x01, 0x00, 0x88, 0x88, 0x88, 0x00, 0x00,
|
||||
0x00,
|
||||
/* EHT Operation */
|
||||
WLAN_EID_EXTENSION, 0x09, WLAN_EID_EXT_EHT_OPERATION,
|
||||
0x01, params->eht_mcs7_min_nss ? params->eht_mcs7_min_nss : 0x11,
|
||||
0x00, 0x00, 0x00, 0x00, 0x24, 0x00,
|
||||
WLAN_EID_EXTENSION, 0x0b, WLAN_EID_EXT_EHT_OPERATION,
|
||||
0x03, params->eht_mcs7_min_nss ? params->eht_mcs7_min_nss : 0x11,
|
||||
0x00, 0x00, 0x00, params->eht_bw,
|
||||
params->eht_bw == IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ ? 42 : 36,
|
||||
0x00,
|
||||
u16_get_bits(params->eht_disabled_subchannels, 0xff),
|
||||
u16_get_bits(params->eht_disabled_subchannels, 0xff00),
|
||||
};
|
||||
struct ieee80211_chan_req chanreq = {};
|
||||
struct cfg80211_chan_def ap_chandef = {};
|
||||
struct ieee802_11_elems *elems;
|
||||
|
||||
/* To force EHT downgrade to HE on punctured 80 MHz downgraded to 40 MHz */
|
||||
set_bit(IEEE80211_HW_DISALLOW_PUNCTURING, t_sdata->local.hw.flags);
|
||||
|
||||
if (params->strict)
|
||||
set_bit(IEEE80211_HW_STRICT, t_sdata->local.hw.flags);
|
||||
else
|
||||
|
|
@ -237,6 +256,7 @@ static void test_determine_chan_mode(struct kunit *test)
|
|||
} else {
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, elems);
|
||||
KUNIT_ASSERT_EQ(test, conn.mode, params->expected_mode);
|
||||
KUNIT_ASSERT_EQ(test, conn.bw_limit, params->expected_bw_limit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ static int mctp_getsockopt(struct socket *sock, int level, int optname,
|
|||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
|
||||
/* helpers for reading/writing the tag ioc, handling compatibility across the
|
||||
|
|
|
|||
|
|
@ -378,6 +378,7 @@ static void mctp_skb_set_flow(struct sk_buff *skb, struct mctp_sk_key *key) {}
|
|||
static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) {}
|
||||
#endif
|
||||
|
||||
/* takes ownership of skb, both in success and failure cases */
|
||||
static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
|
||||
{
|
||||
struct mctp_hdr *hdr = mctp_hdr(skb);
|
||||
|
|
@ -387,8 +388,10 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
|
|||
& MCTP_HDR_SEQ_MASK;
|
||||
|
||||
if (!key->reasm_head) {
|
||||
/* Since we're manipulating the shared frag_list, ensure it isn't
|
||||
* shared with any other SKBs.
|
||||
/* Since we're manipulating the shared frag_list, ensure it
|
||||
* isn't shared with any other SKBs. In the cloned case,
|
||||
* this will free the skb; callers can no longer access it
|
||||
* safely.
|
||||
*/
|
||||
key->reasm_head = skb_unshare(skb, GFP_ATOMIC);
|
||||
if (!key->reasm_head)
|
||||
|
|
@ -402,10 +405,10 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
|
|||
exp_seq = (key->last_seq + 1) & MCTP_HDR_SEQ_MASK;
|
||||
|
||||
if (this_seq != exp_seq)
|
||||
return -EINVAL;
|
||||
goto err_free;
|
||||
|
||||
if (key->reasm_head->len + skb->len > mctp_message_maxlen)
|
||||
return -EINVAL;
|
||||
goto err_free;
|
||||
|
||||
skb->next = NULL;
|
||||
skb->sk = NULL;
|
||||
|
|
@ -419,6 +422,10 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
|
|||
key->reasm_head->truesize += skb->truesize;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int mctp_dst_input(struct mctp_dst *dst, struct sk_buff *skb)
|
||||
|
|
@ -532,18 +539,16 @@ static int mctp_dst_input(struct mctp_dst *dst, struct sk_buff *skb)
|
|||
* key isn't observable yet
|
||||
*/
|
||||
mctp_frag_queue(key, skb);
|
||||
skb = NULL;
|
||||
|
||||
/* if the key_add fails, we've raced with another
|
||||
* SOM packet with the same src, dest and tag. There's
|
||||
* no way to distinguish future packets, so all we
|
||||
* can do is drop; we'll free the skb on exit from
|
||||
* this function.
|
||||
* can do is drop.
|
||||
*/
|
||||
rc = mctp_key_add(key, msk);
|
||||
if (!rc) {
|
||||
if (!rc)
|
||||
trace_mctp_key_acquire(key);
|
||||
skb = NULL;
|
||||
}
|
||||
|
||||
/* we don't need to release key->lock on exit, so
|
||||
* clean up here and suppress the unlock via
|
||||
|
|
@ -561,8 +566,7 @@ static int mctp_dst_input(struct mctp_dst *dst, struct sk_buff *skb)
|
|||
key = NULL;
|
||||
} else {
|
||||
rc = mctp_frag_queue(key, skb);
|
||||
if (!rc)
|
||||
skb = NULL;
|
||||
skb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -572,17 +576,16 @@ static int mctp_dst_input(struct mctp_dst *dst, struct sk_buff *skb)
|
|||
*/
|
||||
|
||||
/* we need to be continuing an existing reassembly... */
|
||||
if (!key->reasm_head)
|
||||
if (!key->reasm_head) {
|
||||
rc = -EINVAL;
|
||||
else
|
||||
} else {
|
||||
rc = mctp_frag_queue(key, skb);
|
||||
skb = NULL;
|
||||
}
|
||||
|
||||
if (rc)
|
||||
goto out_unlock;
|
||||
|
||||
/* we've queued; the queue owns the skb now */
|
||||
skb = NULL;
|
||||
|
||||
/* end of message? deliver to socket, and we're done with
|
||||
* the reassembly/response key
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3554,7 +3554,6 @@ void mptcp_sock_graft(struct sock *sk, struct socket *parent)
|
|||
write_lock_bh(&sk->sk_callback_lock);
|
||||
rcu_assign_pointer(sk->sk_wq, &parent->wq);
|
||||
sk_set_socket(sk, parent);
|
||||
WRITE_ONCE(sk->sk_uid, SOCK_INODE(parent)->i_uid);
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
|
|||
(cur->tuple.src.l3num == NFPROTO_UNSPEC ||
|
||||
cur->tuple.src.l3num == me->tuple.src.l3num) &&
|
||||
cur->tuple.dst.protonum == me->tuple.dst.protonum) {
|
||||
ret = -EEXIST;
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
@ -379,7 +379,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
|
|||
hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) {
|
||||
if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple,
|
||||
&mask)) {
|
||||
ret = -EEXIST;
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1959,6 +1959,18 @@ static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats)
|
|||
return -ENOSPC;
|
||||
}
|
||||
|
||||
static bool hook_is_prefix(struct nft_hook *hook)
|
||||
{
|
||||
return strlen(hook->ifname) >= hook->ifnamelen;
|
||||
}
|
||||
|
||||
static int nft_nla_put_hook_dev(struct sk_buff *skb, struct nft_hook *hook)
|
||||
{
|
||||
int attr = hook_is_prefix(hook) ? NFTA_DEVICE_PREFIX : NFTA_DEVICE_NAME;
|
||||
|
||||
return nla_put_string(skb, attr, hook->ifname);
|
||||
}
|
||||
|
||||
static int nft_dump_basechain_hook(struct sk_buff *skb,
|
||||
const struct net *net, int family,
|
||||
const struct nft_base_chain *basechain,
|
||||
|
|
@ -1990,16 +2002,15 @@ static int nft_dump_basechain_hook(struct sk_buff *skb,
|
|||
if (!first)
|
||||
first = hook;
|
||||
|
||||
if (nla_put(skb, NFTA_DEVICE_NAME,
|
||||
hook->ifnamelen, hook->ifname))
|
||||
if (nft_nla_put_hook_dev(skb, hook))
|
||||
goto nla_put_failure;
|
||||
n++;
|
||||
}
|
||||
nla_nest_end(skb, nest_devs);
|
||||
|
||||
if (n == 1 &&
|
||||
nla_put(skb, NFTA_HOOK_DEV,
|
||||
first->ifnamelen, first->ifname))
|
||||
!hook_is_prefix(first) &&
|
||||
nla_put_string(skb, NFTA_HOOK_DEV, first->ifname))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
nla_nest_end(skb, nest);
|
||||
|
|
@ -2310,7 +2321,8 @@ void nf_tables_chain_destroy(struct nft_chain *chain)
|
|||
}
|
||||
|
||||
static struct nft_hook *nft_netdev_hook_alloc(struct net *net,
|
||||
const struct nlattr *attr)
|
||||
const struct nlattr *attr,
|
||||
bool prefix)
|
||||
{
|
||||
struct nf_hook_ops *ops;
|
||||
struct net_device *dev;
|
||||
|
|
@ -2327,7 +2339,8 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net,
|
|||
if (err < 0)
|
||||
goto err_hook_free;
|
||||
|
||||
hook->ifnamelen = nla_len(attr);
|
||||
/* include the terminating NUL-char when comparing non-prefixes */
|
||||
hook->ifnamelen = strlen(hook->ifname) + !prefix;
|
||||
|
||||
/* nf_tables_netdev_event() is called under rtnl_mutex, this is
|
||||
* indirectly serializing all the other holders of the commit_mutex with
|
||||
|
|
@ -2374,14 +2387,22 @@ static int nf_tables_parse_netdev_hooks(struct net *net,
|
|||
struct nft_hook *hook, *next;
|
||||
const struct nlattr *tmp;
|
||||
int rem, n = 0, err;
|
||||
bool prefix;
|
||||
|
||||
nla_for_each_nested(tmp, attr, rem) {
|
||||
if (nla_type(tmp) != NFTA_DEVICE_NAME) {
|
||||
switch (nla_type(tmp)) {
|
||||
case NFTA_DEVICE_NAME:
|
||||
prefix = false;
|
||||
break;
|
||||
case NFTA_DEVICE_PREFIX:
|
||||
prefix = true;
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
goto err_hook;
|
||||
}
|
||||
|
||||
hook = nft_netdev_hook_alloc(net, tmp);
|
||||
hook = nft_netdev_hook_alloc(net, tmp, prefix);
|
||||
if (IS_ERR(hook)) {
|
||||
NL_SET_BAD_ATTR(extack, tmp);
|
||||
err = PTR_ERR(hook);
|
||||
|
|
@ -2427,7 +2448,7 @@ static int nft_chain_parse_netdev(struct net *net, struct nlattr *tb[],
|
|||
int err;
|
||||
|
||||
if (tb[NFTA_HOOK_DEV]) {
|
||||
hook = nft_netdev_hook_alloc(net, tb[NFTA_HOOK_DEV]);
|
||||
hook = nft_netdev_hook_alloc(net, tb[NFTA_HOOK_DEV], false);
|
||||
if (IS_ERR(hook)) {
|
||||
NL_SET_BAD_ATTR(extack, tb[NFTA_HOOK_DEV]);
|
||||
return PTR_ERR(hook);
|
||||
|
|
@ -9458,8 +9479,7 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
|
|||
|
||||
list_for_each_entry_rcu(hook, hook_list, list,
|
||||
lockdep_commit_lock_is_held(net)) {
|
||||
if (nla_put(skb, NFTA_DEVICE_NAME,
|
||||
hook->ifnamelen, hook->ifname))
|
||||
if (nft_nla_put_hook_dev(skb, hook))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
nla_nest_end(skb, nest_devs);
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
|||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq,
|
||||
NLM_F_MULTI,
|
||||
__sock_i_ino(sk)) < 0) {
|
||||
sock_i_ino(sk)) < 0) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -426,8 +426,6 @@ smc_clc_msg_decl_valid(struct smc_clc_msg_decline *dclc)
|
|||
{
|
||||
struct smc_clc_msg_hdr *hdr = &dclc->hdr;
|
||||
|
||||
if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D)
|
||||
return false;
|
||||
if (hdr->version == SMC_V1) {
|
||||
if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -742,6 +742,9 @@ bool smc_ib_is_sg_need_sync(struct smc_link *lnk,
|
|||
unsigned int i;
|
||||
bool ret = false;
|
||||
|
||||
if (!lnk->smcibdev->ibdev->dma_device)
|
||||
return ret;
|
||||
|
||||
/* for now there is just one DMA address */
|
||||
for_each_sg(buf_slot->sgt[lnk->link_idx].sgl, sg,
|
||||
buf_slot->sgt[lnk->link_idx].nents, i) {
|
||||
|
|
|
|||
|
|
@ -1916,7 +1916,8 @@ cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
|
|||
*/
|
||||
|
||||
f = rcu_access_pointer(new->pub.beacon_ies);
|
||||
kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head);
|
||||
if (!new->pub.hidden_beacon_bss)
|
||||
kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -900,13 +900,16 @@ void __cfg80211_connect_result(struct net_device *dev,
|
|||
if (!wdev->u.client.ssid_len) {
|
||||
rcu_read_lock();
|
||||
for_each_valid_link(cr, link) {
|
||||
u32 ssid_len;
|
||||
|
||||
ssid = ieee80211_bss_get_elem(cr->links[link].bss,
|
||||
WLAN_EID_SSID);
|
||||
|
||||
if (!ssid || !ssid->datalen)
|
||||
continue;
|
||||
|
||||
memcpy(wdev->u.client.ssid, ssid->data, ssid->datalen);
|
||||
ssid_len = min(ssid->datalen, IEEE80211_MAX_SSID_LEN);
|
||||
memcpy(wdev->u.client.ssid, ssid->data, ssid_len);
|
||||
wdev->u.client.ssid_len = ssid->datalen;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -830,7 +830,7 @@ class TypeArrayNest(Type):
|
|||
'ynl_attr_for_each_nested(attr2, attr) {',
|
||||
'\tif (ynl_attr_validate(yarg, attr2))',
|
||||
'\t\treturn YNL_PARSE_CB_ERROR;',
|
||||
f'\t{var}->_count.{self.c_name}++;',
|
||||
f'\tn_{self.c_name}++;',
|
||||
'}']
|
||||
return get_lines, None, local_vars
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ def test_receive(cfg, ipver="6", extra_args=None):
|
|||
ip_args = f"-{ipver} -S {cfg.remote_addr_v[ipver]} -D {cfg.addr_v[ipver]}"
|
||||
|
||||
rx_cmd = f"{cfg.bin_local} -i {cfg.ifname} -n 100 {ip_args} -r 1 -R {extra_args}"
|
||||
tx_cmd = f"{cfg.bin_remote} -i {cfg.ifname} -n 100 {ip_args} -r 1 -T {extra_args}"
|
||||
tx_cmd = f"{cfg.bin_remote} -i {cfg.remote_ifname} -n 100 {ip_args} -r 1 -T {extra_args}"
|
||||
|
||||
with bkg(rx_cmd, exit_wait=True):
|
||||
wait_port_listen(34000, proto="udp")
|
||||
|
|
@ -37,7 +37,7 @@ def test_transmit(cfg, ipver="6", extra_args=None):
|
|||
if extra_args != "-U -Z":
|
||||
extra_args += " -r 1"
|
||||
|
||||
rx_cmd = f"{cfg.bin_remote} -i {cfg.ifname} -L 1 -n 100 {ip_args} -R {extra_args}"
|
||||
rx_cmd = f"{cfg.bin_remote} -i {cfg.remote_ifname} -L 1 -n 100 {ip_args} -R {extra_args}"
|
||||
tx_cmd = f"{cfg.bin_local} -i {cfg.ifname} -L 1 -n 100 {ip_args} -T {extra_args}"
|
||||
|
||||
with bkg(rx_cmd, host=cfg.remote, exit_wait=True):
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ TEST_GEN_PROGS += bind_wildcard
|
|||
TEST_GEN_PROGS += bind_timewait
|
||||
TEST_PROGS += test_vxlan_mdb.sh
|
||||
TEST_PROGS += test_bridge_neigh_suppress.sh
|
||||
TEST_PROGS += test_vxlan_nh.sh
|
||||
TEST_PROGS += test_vxlan_nolocalbypass.sh
|
||||
TEST_PROGS += test_bridge_backup_port.sh
|
||||
TEST_PROGS += test_neigh.sh
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ static void *setup(void *arg)
|
|||
int *array = (int *)arg;
|
||||
|
||||
for (i = 0; i < MAX_CONNECTIONS; i++) {
|
||||
sock_fd = bind_socket(SO_REUSEADDR | SO_REUSEPORT, setup_addr);
|
||||
sock_fd = bind_socket(SO_REUSEPORT, setup_addr);
|
||||
if (sock_fd < 0) {
|
||||
ret = sock_fd;
|
||||
pthread_exit(&ret);
|
||||
|
|
@ -103,7 +103,7 @@ int main(int argc, const char *argv[])
|
|||
|
||||
setup_addr = use_v6 ? setup_addr_v6 : setup_addr_v4;
|
||||
|
||||
listener_fd = bind_socket(SO_REUSEADDR | SO_REUSEPORT, setup_addr);
|
||||
listener_fd = bind_socket(SO_REUSEPORT, setup_addr);
|
||||
if (listen(listener_fd, 100) < 0) {
|
||||
perror("listen failed");
|
||||
return -1;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user