Pull networking fixes from Jakub Kicinski: "Including fixes from Bluetooth, netfilter, BPF and WiFi. I didn't collect precise data but feels like we've got a lot of 6.5 fixes here. WiFi fixes are most user-awaited. Current release - regressions: - Bluetooth: fix hci_link_tx_to RCU lock usage Current release - new code bugs: - bpf: mprog: fix maximum program check on mprog attachment - eth: ti: icssg-prueth: fix signedness bug in prueth_init_tx_chns() Previous releases - regressions: - ipv6: tcp: add a missing nf_reset_ct() in 3WHS handling - vringh: don't use vringh_kiov_advance() in vringh_iov_xfer(), it doesn't handle zero length like we expected - wifi: - cfg80211: fix cqm_config access race, fix crashes with brcmfmac - iwlwifi: mvm: handle PS changes in vif_cfg_changed - mac80211: fix mesh id corruption on 32 bit systems - mt76: mt76x02: fix MT76x0 external LNA gain handling - Bluetooth: fix handling of HCI_QUIRK_STRICT_DUPLICATE_FILTER - l2tp: fix handling of transhdrlen in __ip{,6}_append_data() - dsa: mv88e6xxx: avoid EEPROM timeout when EEPROM is absent - eth: stmmac: fix the incorrect parameter after refactoring Previous releases - always broken: - net: replace calls to sock->ops->connect() with kernel_connect(), prevent address rewrite in kernel_bind(); otherwise BPF hooks may modify arguments, unexpectedly to the caller - tcp: fix delayed ACKs when reads and writes align with MSS - bpf: - verifier: unconditionally reset backtrack_state masks on global func exit - s390: let arch_prepare_bpf_trampoline return program size, fix struct_ops offsets - sockmap: fix accounting of available bytes in presence of PEEKs - sockmap: reject sk_msg egress redirects to non-TCP sockets - ipv4/fib: send netlink notify when delete source address routes - ethtool: plca: fix width of reads when parsing netlink commands - netfilter: nft_payload: rebuild vlan header on h_proto access - Bluetooth: hci_codec: fix leaking memory of local_codecs - eth: intel: ice: always add legacy 32byte RXDID in supported_rxdids - eth: stmmac: - dwmac-stm32: fix resume on STM32 MCU - remove buggy and unneeded stmmac_poll_controller, depend on NAPI - ibmveth: always recompute TCP pseudo-header checksum, fix use of the driver with Open vSwitch - wifi: - rtw88: rtw8723d: fix MAC address offset in EEPROM - mt76: fix lock dependency problem for wed_lock - mwifiex: sanity check data reported by the device - iwlwifi: ensure ack flag is properly cleared - iwlwifi: mvm: fix a memory corruption due to bad pointer arithm - iwlwifi: mvm: fix incorrect usage of scan API Misc: - wifi: mac80211: work around Cisco AP 9115 VHT MPDU length" * tag 'net-6.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (99 commits) MAINTAINERS: update Matthieu's email address mptcp: userspace pm allow creating id 0 subflow mptcp: fix delegated action races net: stmmac: remove unneeded stmmac_poll_controller net: lan743x: also select PHYLIB net: ethernet: mediatek: disable irq before schedule napi net: mana: Fix oversized sge0 for GSO packets net: mana: Fix the tso_bytes calculation net: mana: Fix TX CQE error handling netlink: annotate data-races around sk->sk_err sctp: update hb timer immediately after users change hb_interval sctp: update transport state when processing a dupcook packet tcp: fix delayed ACKs for MSS boundary condition tcp: fix quick-ack counting to count actual ACKs of new data page_pool: fix documentation typos tipc: fix a potential deadlock on &tx->lock net: stmmac: dwmac-stm32: fix resume on STM32 MCU ipv4: Set offload_failed flag in fibmatch results netfilter: nf_tables: nft_set_rbtree: fix spurious insertion failure netfilter: nf_tables: Deduplicate nft_register_obj audit logs ...
Unified · Split
| @@ -377,6 +377,7 @@ Matthew Wilcox <willy@infradead.org> <willy@debian.org> · 376 unmodified lines | |||
| 377 | Matthew Wilcox <willy@infradead.org> <willy@linux.intel.com> | 377 | Matthew Wilcox <willy@infradead.org> <willy@linux.intel.com> |
| 378 | Matthew Wilcox <willy@infradead.org> <willy@parisc-linux.org> | 378 | Matthew Wilcox <willy@infradead.org> <willy@parisc-linux.org> |
| 379 | Matthias Fuchs <socketcan@esd.eu> <matthias.fuchs@esd.eu> | 379 | Matthias Fuchs <socketcan@esd.eu> <matthias.fuchs@esd.eu> |
| 380 | Matthieu Baerts <matttbe@kernel.org> <matthieu.baerts@tessares.net> | ||
| 380 | Matthieu CASTET <castet.matthieu@free.fr> | 381 | Matthieu CASTET <castet.matthieu@free.fr> |
| 381 | Matti Vaittinen <mazziesaccount@gmail.com> <matti.vaittinen@fi.rohmeurope.com> | 382 | Matti Vaittinen <mazziesaccount@gmail.com> <matti.vaittinen@fi.rohmeurope.com> |
| 382 | Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting> | 383 | Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting> |
| @@ -470,7 +470,6 @@ F: drivers/hwmon/adm1029.c · 469 unmodified lines | |||
| 470 | ADM8211 WIRELESS DRIVER | 470 | ADM8211 WIRELESS DRIVER |
| 471 | L: linux-wireless@vger.kernel.org | 471 | L: linux-wireless@vger.kernel.org |
| 472 | S: Orphan | 472 | S: Orphan |
| 473 | W: https://wireless.wiki.kernel.org/ | ||
| 474 | F: drivers/net/wireless/admtek/adm8211.* | 473 | F: drivers/net/wireless/admtek/adm8211.* |
| 475 | 474 | ||
| 476 | ADP1653 FLASH CONTROLLER DRIVER | 475 | ADP1653 FLASH CONTROLLER DRIVER |
| @@ -9531,10 +9530,8 @@ F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml · 9054 unmodified lines | |||
| 9531 | F: drivers/iio/pressure/mprls0025pa.c | 9530 | F: drivers/iio/pressure/mprls0025pa.c |
| 9532 | 9531 | ||
| 9533 | HOST AP DRIVER | 9532 | HOST AP DRIVER |
| 9534 | M: Jouni Malinen <j@w1.fi> | ||
| 9535 | L: linux-wireless@vger.kernel.org | 9533 | L: linux-wireless@vger.kernel.org |
| 9536 | S: Obsolete | 9534 | S: Obsolete |
| 9537 | W: http://w1.fi/hostap-driver.html | ||
| 9538 | F: drivers/net/wireless/intersil/hostap/ | 9535 | F: drivers/net/wireless/intersil/hostap/ |
| 9539 | 9536 | ||
| 9540 | HP BIOSCFG DRIVER | 9537 | HP BIOSCFG DRIVER |
| @@ -14947,7 +14944,7 @@ K: macsec · 5406 unmodified lines | |||
| 14947 | K: \bmdo_ | 14944 | K: \bmdo_ |
| 14948 | 14945 | ||
| 14949 | NETWORKING [MPTCP] | 14946 | NETWORKING [MPTCP] |
| 14950 | M: Matthieu Baerts <matthieu.baerts@tessares.net> | 14947 | M: Matthieu Baerts <matttbe@kernel.org> |
| 14951 | M: Mat Martineau <martineau@kernel.org> | 14948 | M: Mat Martineau <martineau@kernel.org> |
| 14952 | L: netdev@vger.kernel.org | 14949 | L: netdev@vger.kernel.org |
| 14953 | L: mptcp@lists.linux.dev | 14950 | L: mptcp@lists.linux.dev |
| @@ -17602,6 +17599,7 @@ M: Kalle Valo <kvalo@kernel.org> · 2648 unmodified lines | |||
| 17602 | M: Jeff Johnson <quic_jjohnson@quicinc.com> | 17599 | M: Jeff Johnson <quic_jjohnson@quicinc.com> |
| 17603 | L: ath12k@lists.infradead.org | 17600 | L: ath12k@lists.infradead.org |
| 17604 | S: Supported | 17601 | S: Supported |
| 17602 | W: https://wireless.wiki.kernel.org/en/users/Drivers/ath12k | ||
| 17605 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git | 17603 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git |
| 17606 | F: drivers/net/wireless/ath/ath12k/ | 17604 | F: drivers/net/wireless/ath/ath12k/ |
| 17607 | 17605 | ||
| @@ -18132,8 +18130,6 @@ REALTEK WIRELESS DRIVER (rtlwifi family) · 524 unmodified lines | |||
| 18132 | M: Ping-Ke Shih <pkshih@realtek.com> | 18130 | M: Ping-Ke Shih <pkshih@realtek.com> |
| 18133 | L: linux-wireless@vger.kernel.org | 18131 | L: linux-wireless@vger.kernel.org |
| 18134 | S: Maintained | 18132 | S: Maintained |
| 18135 | W: https://wireless.wiki.kernel.org/ | ||
| 18136 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | ||
| 18137 | F: drivers/net/wireless/realtek/rtlwifi/ | 18133 | F: drivers/net/wireless/realtek/rtlwifi/ |
| 18138 | 18134 | ||
| 18139 | REALTEK WIRELESS DRIVER (rtw88) | 18135 | REALTEK WIRELESS DRIVER (rtw88) |
| @@ -18661,7 +18657,6 @@ F: drivers/media/dvb-frontends/rtl2832_sdr* · 521 unmodified lines | |||
| 18661 | RTL8180 WIRELESS DRIVER | 18657 | RTL8180 WIRELESS DRIVER |
| 18662 | L: linux-wireless@vger.kernel.org | 18658 | L: linux-wireless@vger.kernel.org |
| 18663 | S: Orphan | 18659 | S: Orphan |
| 18664 | W: https://wireless.wiki.kernel.org/ | ||
| 18665 | F: drivers/net/wireless/realtek/rtl818x/rtl8180/ | 18660 | F: drivers/net/wireless/realtek/rtl818x/rtl8180/ |
| 18666 | 18661 | ||
| 18667 | RTL8187 WIRELESS DRIVER | 18662 | RTL8187 WIRELESS DRIVER |
| @@ -18669,14 +18664,12 @@ M: Hin-Tak Leung <hintak.leung@gmail.com> · 1 unmodified line | |||
| 18669 | M: Larry Finger <Larry.Finger@lwfinger.net> | 18664 | M: Larry Finger <Larry.Finger@lwfinger.net> |
| 18670 | L: linux-wireless@vger.kernel.org | 18665 | L: linux-wireless@vger.kernel.org |
| 18671 | S: Maintained | 18666 | S: Maintained |
| 18672 | W: https://wireless.wiki.kernel.org/ | ||
| 18673 | F: drivers/net/wireless/realtek/rtl818x/rtl8187/ | 18667 | F: drivers/net/wireless/realtek/rtl818x/rtl8187/ |
| 18674 | 18668 | ||
| 18675 | RTL8XXXU WIRELESS DRIVER (rtl8xxxu) | 18669 | RTL8XXXU WIRELESS DRIVER (rtl8xxxu) |
| 18676 | M: Jes Sorensen <Jes.Sorensen@gmail.com> | 18670 | M: Jes Sorensen <Jes.Sorensen@gmail.com> |
| 18677 | L: linux-wireless@vger.kernel.org | 18671 | L: linux-wireless@vger.kernel.org |
| 18678 | S: Maintained | 18672 | S: Maintained |
| 18679 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel | ||
| 18680 | F: drivers/net/wireless/realtek/rtl8xxxu/ | 18673 | F: drivers/net/wireless/realtek/rtl8xxxu/ |
| 18681 | 18674 | ||
| 18682 | RTRS TRANSPORT DRIVERS | 18675 | RTRS TRANSPORT DRIVERS |
| @@ -21658,7 +21651,6 @@ L: linux-wireless@vger.kernel.org · 2975 unmodified lines | |||
| 21658 | S: Orphan | 21651 | S: Orphan |
| 21659 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx | 21652 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx |
| 21660 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl1251 | 21653 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl1251 |
| 21661 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git | ||
| 21662 | F: drivers/net/wireless/ti/ | 21654 | F: drivers/net/wireless/ti/ |
| 21663 | 21655 | ||
| 21664 | TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER | 21656 | TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER |
| @@ -2513,7 +2513,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, · 2512 unmodified lines | |||
| 2513 | return -E2BIG; | 2513 | return -E2BIG; |
| 2514 | } | 2514 | } |
| 2515 | 2515 | ||
| 2516 | return ret; | 2516 | return tjit.common.prg; |
| 2517 | } | 2517 | } |
| 2518 | 2518 | ||
| 2519 | bool bpf_jit_supports_subprog_tailcalls(void) | 2519 | bool bpf_jit_supports_subprog_tailcalls(void) |
| @@ -4419,6 +4419,7 @@ static int btusb_probe(struct usb_interface *intf, · 4418 unmodified lines | |||
| 4419 | 4419 | ||
| 4420 | if (id->driver_info & BTUSB_QCA_ROME) { | 4420 | if (id->driver_info & BTUSB_QCA_ROME) { |
| 4421 | data->setup_on_usb = btusb_setup_qca; | 4421 | data->setup_on_usb = btusb_setup_qca; |
| 4422 | hdev->shutdown = btusb_shutdown_qca; | ||
| 4422 | hdev->set_bdaddr = btusb_set_bdaddr_ath3012; | 4423 | hdev->set_bdaddr = btusb_set_bdaddr_ath3012; |
| 4423 | hdev->cmd_timeout = btusb_qca_cmd_timeout; | 4424 | hdev->cmd_timeout = btusb_qca_cmd_timeout; |
| 4424 | set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); | 4425 | set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); |
| @@ -558,6 +558,9 @@ int k3_udma_glue_tx_get_irq(struct k3_udma_glue_tx_channel *tx_chn) · 557 unmodified lines | |||
| 558 | tx_chn->virq = k3_ringacc_get_ring_irq_num(tx_chn->ringtxcq); | 558 | tx_chn->virq = k3_ringacc_get_ring_irq_num(tx_chn->ringtxcq); |
| 559 | } | 559 | } |
| 560 | 560 | ||
| 561 | if (!tx_chn->virq) | ||
| 562 | return -ENXIO; | ||
| 563 | |||
| 561 | return tx_chn->virq; | 564 | return tx_chn->virq; |
| 562 | } | 565 | } |
| 563 | EXPORT_SYMBOL_GPL(k3_udma_glue_tx_get_irq); | 566 | EXPORT_SYMBOL_GPL(k3_udma_glue_tx_get_irq); |
| @@ -2958,14 +2958,16 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) · 2957 unmodified lines | |||
| 2958 | * from the wrong location resulting in the switch booting | 2958 | * from the wrong location resulting in the switch booting |
| 2959 | * to wrong mode and inoperable. | 2959 | * to wrong mode and inoperable. |
| 2960 | */ | 2960 | */ |
| 2961 | mv88e6xxx_g1_wait_eeprom_done(chip); | 2961 | if (chip->info->ops->get_eeprom) |
| 2962 | mv88e6xxx_g2_eeprom_wait(chip); | ||
| 2962 | 2963 | ||
| 2963 | gpiod_set_value_cansleep(gpiod, 1); | 2964 | gpiod_set_value_cansleep(gpiod, 1); |
| 2964 | usleep_range(10000, 20000); | 2965 | usleep_range(10000, 20000); |
| 2965 | gpiod_set_value_cansleep(gpiod, 0); | 2966 | gpiod_set_value_cansleep(gpiod, 0); |
| 2966 | usleep_range(10000, 20000); | 2967 | usleep_range(10000, 20000); |
| 2967 | 2968 | ||
| 2968 | mv88e6xxx_g1_wait_eeprom_done(chip); | 2969 | if (chip->info->ops->get_eeprom) |
| 2970 | mv88e6xxx_g2_eeprom_wait(chip); | ||
| 2969 | } | 2971 | } |
| 2970 | } | 2972 | } |
| 2971 | 2973 | ||
| @@ -75,37 +75,6 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip) · 74 unmodified lines | |||
| 75 | return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); | 75 | return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip) | ||
| 79 | { | ||
| 80 | const unsigned long timeout = jiffies + 1 * HZ; | ||
| 81 | u16 val; | ||
| 82 | int err; | ||
| 83 | |||
| 84 | /* Wait up to 1 second for the switch to finish reading the | ||
| 85 | * EEPROM. | ||
| 86 | */ | ||
| 87 | while (time_before(jiffies, timeout)) { | ||
| 88 | err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val); | ||
| 89 | if (err) { | ||
| 90 | dev_err(chip->dev, "Error reading status"); | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | /* If the switch is still resetting, it may not | ||
| 95 | * respond on the bus, and so MDIO read returns | ||
| 96 | * 0xffff. Differentiate between that, and waiting for | ||
| 97 | * the EEPROM to be done by bit 0 being set. | ||
| 98 | */ | ||
| 99 | if (val != 0xffff && | ||
| 100 | val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE)) | ||
| 101 | return; | ||
| 102 | |||
| 103 | usleep_range(1000, 2000); | ||
| 104 | } | ||
| 105 | |||
| 106 | dev_err(chip->dev, "Timeout waiting for EEPROM done"); | ||
| 107 | } | ||
| 108 | |||
| 109 | /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 | 78 | /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 |
| 110 | * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 | 79 | * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 |
| 111 | * Offset 0x03: Switch MAC Address Register Bytes 4 & 5 | 80 | * Offset 0x03: Switch MAC Address Register Bytes 4 & 5 |
| @@ -282,7 +282,6 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr); · 281 unmodified lines | |||
| 282 | int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); | 282 | int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); |
| 283 | int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); | 283 | int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); |
| 284 | int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); | 284 | int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); |
| 285 | void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip); | ||
| 286 | 285 | ||
| 287 | int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); | 286 | int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); |
| 288 | int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); | 287 | int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); |
| @@ -340,7 +340,7 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip) · 339 unmodified lines | |||
| 340 | * Offset 0x15: EEPROM Addr (for 8-bit data access) | 340 | * Offset 0x15: EEPROM Addr (for 8-bit data access) |
| 341 | */ | 341 | */ |
| 342 | 342 | ||
| 343 | static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) | 343 | int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) |
| 344 | { | 344 | { |
| 345 | int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY); | 345 | int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY); |
| 346 | int err; | 346 | int err; |
| @@ -365,6 +365,7 @@ int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip); · 364 unmodified lines | |||
| 365 | 365 | ||
| 366 | int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, | 366 | int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, |
| 367 | int port); | 367 | int port); |
| 368 | int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip); | ||
| 368 | 369 | ||
| 369 | extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; | 370 | extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; |
| 370 | extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops; | 371 | extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops; |
| @@ -1303,24 +1303,23 @@ static void ibmveth_rx_csum_helper(struct sk_buff *skb, · 1302 unmodified lines | |||
| 1303 | * the user space for finding a flow. During this process, OVS computes | 1303 | * the user space for finding a flow. During this process, OVS computes |
| 1304 | * checksum on the first packet when CHECKSUM_PARTIAL flag is set. | 1304 | * checksum on the first packet when CHECKSUM_PARTIAL flag is set. |
| 1305 | * | 1305 | * |
| 1306 | * So, re-compute TCP pseudo header checksum when configured for | 1306 | * So, re-compute TCP pseudo header checksum. |
| 1307 | * trunk mode. | ||
| 1308 | */ | 1307 | */ |
| 1308 | |||
| 1309 | if (iph_proto == IPPROTO_TCP) { | 1309 | if (iph_proto == IPPROTO_TCP) { |
| 1310 | struct tcphdr *tcph = (struct tcphdr *)(skb->data + iphlen); | 1310 | struct tcphdr *tcph = (struct tcphdr *)(skb->data + iphlen); |
| 1311 | |||
| 1311 | if (tcph->check == 0x0000) { | 1312 | if (tcph->check == 0x0000) { |
| 1312 | /* Recompute TCP pseudo header checksum */ | 1313 | /* Recompute TCP pseudo header checksum */ |
| 1313 | if (adapter->is_active_trunk) { | 1314 | tcphdrlen = skb->len - iphlen; |
| 1314 | tcphdrlen = skb->len - iphlen; | 1315 | if (skb_proto == ETH_P_IP) |
| 1315 | if (skb_proto == ETH_P_IP) | 1316 | tcph->check = |
| 1316 | tcph->check = | 1317 | ~csum_tcpudp_magic(iph->saddr, |
| 1317 | ~csum_tcpudp_magic(iph->saddr, | 1318 | iph->daddr, tcphdrlen, iph_proto, 0); |
| 1318 | iph->daddr, tcphdrlen, iph_proto, 0); | 1319 | else if (skb_proto == ETH_P_IPV6) |
| 1319 | else if (skb_proto == ETH_P_IPV6) | 1320 | tcph->check = |
| 1320 | tcph->check = | 1321 | ~csum_ipv6_magic(&iph6->saddr, |
| 1321 | ~csum_ipv6_magic(&iph6->saddr, | 1322 | &iph6->daddr, tcphdrlen, iph_proto, 0); |
| 1322 | &iph6->daddr, tcphdrlen, iph_proto, 0); | ||
| 1323 | } | ||
| 1324 | /* Setup SKB fields for checksum offload */ | 1323 | /* Setup SKB fields for checksum offload */ |
| 1325 | skb_partial_csum_set(skb, iphlen, | 1324 | skb_partial_csum_set(skb, iphlen, |
| 1326 | offsetof(struct tcphdr, check)); | 1325 | offsetof(struct tcphdr, check)); |
| @@ -2617,12 +2617,14 @@ static int ice_vc_query_rxdid(struct ice_vf *vf) · 2616 unmodified lines | |||
| 2617 | goto err; | 2617 | goto err; |
| 2618 | } | 2618 | } |
| 2619 | 2619 | ||
| 2620 | /* Read flexiflag registers to determine whether the | 2620 | /* RXDIDs supported by DDP package can be read from the register |
| 2621 | * corresponding RXDID is configured and supported or not. | 2621 | * to get the supported RXDID bitmap. But the legacy 32byte RXDID |
| 2622 | * Since Legacy 16byte descriptor format is not supported, | 2622 | * is not listed in DDP package, add it in the bitmap manually. |
| 2623 | * start from Legacy 32byte descriptor. | 2623 | * Legacy 16byte descriptor is not supported. |
| 2624 | */ | 2624 | */ |
| 2625 | for (i = ICE_RXDID_LEGACY_1; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) { | 2625 | rxdid->supported_rxdids |= BIT(ICE_RXDID_LEGACY_1); |
| 2626 | |||
| 2627 | for (i = ICE_RXDID_FLEX_NIC; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) { | ||
| 2626 | regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0)); | 2628 | regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0)); |
| 2627 | if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) | 2629 | if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) |
| 2628 | & GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M) | 2630 | & GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M) |
| @@ -2195,7 +2195,7 @@ struct rx_ring_info { · 2194 unmodified lines | |||
| 2195 | struct sk_buff *skb; | 2195 | struct sk_buff *skb; |
| 2196 | dma_addr_t data_addr; | 2196 | dma_addr_t data_addr; |
| 2197 | DEFINE_DMA_UNMAP_LEN(data_size); | 2197 | DEFINE_DMA_UNMAP_LEN(data_size); |
| 2198 | dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT]; | 2198 | dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT ?: 1]; |
| 2199 | }; | 2199 | }; |
| 2200 | 2200 | ||
| 2201 | enum flow_control { | 2201 | enum flow_control { |
| @@ -3171,8 +3171,8 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth) · 3170 unmodified lines | |||
| 3171 | 3171 | ||
| 3172 | eth->rx_events++; | 3172 | eth->rx_events++; |
| 3173 | if (likely(napi_schedule_prep(ð->rx_napi))) { | 3173 | if (likely(napi_schedule_prep(ð->rx_napi))) { |
| 3174 | __napi_schedule(ð->rx_napi); | ||
| 3175 | mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); | 3174 | mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); |
| 3175 | __napi_schedule(ð->rx_napi); | ||
| 3176 | } | 3176 | } |
| 3177 | 3177 | ||
| 3178 | return IRQ_HANDLED; | 3178 | return IRQ_HANDLED; |
| @@ -3184,8 +3184,8 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth) · 5 unmodified lines | |||
| 3184 | 3184 | ||
| 3185 | eth->tx_events++; | 3185 | eth->tx_events++; |
| 3186 | if (likely(napi_schedule_prep(ð->tx_napi))) { | 3186 | if (likely(napi_schedule_prep(ð->tx_napi))) { |
| 3187 | __napi_schedule(ð->tx_napi); | ||
| 3188 | mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); | 3187 | mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); |
| 3188 | __napi_schedule(ð->tx_napi); | ||
| 3189 | } | 3189 | } |
| 3190 | 3190 | ||
| 3191 | return IRQ_HANDLED; | 3191 | return IRQ_HANDLED; |
| @@ -46,6 +46,7 @@ config LAN743X · 45 unmodified lines | |||
| 46 | tristate "LAN743x support" | 46 | tristate "LAN743x support" |
| 47 | depends on PCI | 47 | depends on PCI |
| 48 | depends on PTP_1588_CLOCK_OPTIONAL | 48 | depends on PTP_1588_CLOCK_OPTIONAL |
| 49 | select PHYLIB | ||
| 49 | select FIXED_PHY | 50 | select FIXED_PHY |
| 50 | select CRC16 | 51 | select CRC16 |
| 51 | select CRC32 | 52 | select CRC32 |
| @@ -91,63 +91,137 @@ static unsigned int mana_checksum_info(struct sk_buff *skb) · 90 unmodified lines | |||
| 91 | return 0; | 91 | return 0; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static void mana_add_sge(struct mana_tx_package *tp, struct mana_skb_head *ash, | ||
| 95 | int sg_i, dma_addr_t da, int sge_len, u32 gpa_mkey) | ||
| 96 | { | ||
| 97 | ash->dma_handle[sg_i] = da; | ||
| 98 | ash->size[sg_i] = sge_len; | ||
| 99 | |||
| 100 | tp->wqe_req.sgl[sg_i].address = da; | ||
| 101 | tp->wqe_req.sgl[sg_i].mem_key = gpa_mkey; | ||
| 102 | tp->wqe_req.sgl[sg_i].size = sge_len; | ||
| 103 | } | ||
| 104 | |||
| 94 | static int mana_map_skb(struct sk_buff *skb, struct mana_port_context *apc, | 105 | static int mana_map_skb(struct sk_buff *skb, struct mana_port_context *apc, |
| 95 | struct mana_tx_package *tp) | 106 | struct mana_tx_package *tp, int gso_hs) |
| 96 | { | 107 | { |
| 97 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; | 108 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; |
| 109 | int hsg = 1; /* num of SGEs of linear part */ | ||
| 98 | struct gdma_dev *gd = apc->ac->gdma_dev; | 110 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 111 | int skb_hlen = skb_headlen(skb); | ||
| 112 | int sge0_len, sge1_len = 0; | ||
| 99 | struct gdma_context *gc; | 113 | struct gdma_context *gc; |
| 100 | struct device *dev; | 114 | struct device *dev; |
| 101 | skb_frag_t *frag; | 115 | skb_frag_t *frag; |
| 102 | dma_addr_t da; | 116 | dma_addr_t da; |
| 117 | int sg_i; | ||
| 103 | int i; | 118 | int i; |
| 104 | 119 | ||
| 105 | gc = gd->gdma_context; | 120 | gc = gd->gdma_context; |
| 106 | dev = gc->dev; | 121 | dev = gc->dev; |
| 107 | da = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); | ||
| 108 | 122 | ||
| 123 | if (gso_hs && gso_hs < skb_hlen) { | ||
| 124 | sge0_len = gso_hs; | ||
| 125 | sge1_len = skb_hlen - gso_hs; | ||
| 126 | } else { | ||
| 127 | sge0_len = skb_hlen; | ||
| 128 | } | ||
| 129 | |||
| 130 | da = dma_map_single(dev, skb->data, sge0_len, DMA_TO_DEVICE); | ||
| 109 | if (dma_mapping_error(dev, da)) | 131 | if (dma_mapping_error(dev, da)) |
| 110 | return -ENOMEM; | 132 | return -ENOMEM; |
| 111 | 133 | ||
| 112 | ash->dma_handle[0] = da; | 134 | mana_add_sge(tp, ash, 0, da, sge0_len, gd->gpa_mkey); |
| 113 | ash->size[0] = skb_headlen(skb); | ||
| 114 | 135 | ||
| 115 | tp->wqe_req.sgl[0].address = ash->dma_handle[0]; | 136 | if (sge1_len) { |
| 116 | tp->wqe_req.sgl[0].mem_key = gd->gpa_mkey; | 137 | sg_i = 1; |
| 117 | tp->wqe_req.sgl[0].size = ash->size[0]; | 138 | da = dma_map_single(dev, skb->data + sge0_len, sge1_len, |
| 139 | DMA_TO_DEVICE); | ||
| 140 | if (dma_mapping_error(dev, da)) | ||
| 141 | goto frag_err; | ||
| 142 | |||
| 143 | mana_add_sge(tp, ash, sg_i, da, sge1_len, gd->gpa_mkey); | ||
| 144 | hsg = 2; | ||
| 145 | } | ||
| 118 | 146 | ||
| 119 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 147 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
| 148 | sg_i = hsg + i; | ||
| 149 | |||
| 120 | frag = &skb_shinfo(skb)->frags[i]; | 150 | frag = &skb_shinfo(skb)->frags[i]; |
| 121 | da = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), | 151 | da = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), |
| 122 | DMA_TO_DEVICE); | 152 | DMA_TO_DEVICE); |
| 123 | |||
| 124 | if (dma_mapping_error(dev, da)) | 153 | if (dma_mapping_error(dev, da)) |
| 125 | goto frag_err; | 154 | goto frag_err; |
| 126 | 155 | ||
| 127 | ash->dma_handle[i + 1] = da; | 156 | mana_add_sge(tp, ash, sg_i, da, skb_frag_size(frag), |
| 128 | ash->size[i + 1] = skb_frag_size(frag); | 157 | gd->gpa_mkey); |
| 129 | |||
| 130 | tp->wqe_req.sgl[i + 1].address = ash->dma_handle[i + 1]; | ||
| 131 | tp->wqe_req.sgl[i + 1].mem_key = gd->gpa_mkey; | ||
| 132 | tp->wqe_req.sgl[i + 1].size = ash->size[i + 1]; | ||
| 133 | } | 158 | } |
| 134 | 159 | ||
| 135 | return 0; | 160 | return 0; |
| 136 | 161 | ||
| 137 | frag_err: | 162 | frag_err: |
| 138 | for (i = i - 1; i >= 0; i--) | 163 | for (i = sg_i - 1; i >= hsg; i--) |
| 139 | dma_unmap_page(dev, ash->dma_handle[i + 1], ash->size[i + 1], | 164 | dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], |
| 140 | DMA_TO_DEVICE); | 165 | DMA_TO_DEVICE); |
| 141 | 166 | ||
| 142 | dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE); | 167 | for (i = hsg - 1; i >= 0; i--) |
| 168 | dma_unmap_single(dev, ash->dma_handle[i], ash->size[i], | ||
| 169 | DMA_TO_DEVICE); | ||
| 143 | 170 | ||
| 144 | return -ENOMEM; | 171 | return -ENOMEM; |
| 145 | } | 172 | } |
| 146 | 173 | ||
| 174 | /* Handle the case when GSO SKB linear length is too large. | ||
| 175 | * MANA NIC requires GSO packets to put only the packet header to SGE0. | ||
| 176 | * So, we need 2 SGEs for the skb linear part which contains more than the | ||
| 177 | * header. | ||
| 178 | * Return a positive value for the number of SGEs, or a negative value | ||
| 179 | * for an error. | ||
| 180 | */ | ||
| 181 | static int mana_fix_skb_head(struct net_device *ndev, struct sk_buff *skb, | ||
| 182 | int gso_hs) | ||
| 183 | { | ||
| 184 | int num_sge = 1 + skb_shinfo(skb)->nr_frags; | ||
| 185 | int skb_hlen = skb_headlen(skb); | ||
| 186 | |||
| 187 | if (gso_hs < skb_hlen) { | ||
| 188 | num_sge++; | ||
| 189 | } else if (gso_hs > skb_hlen) { | ||
| 190 | if (net_ratelimit()) | ||
| 191 | netdev_err(ndev, | ||
| 192 | "TX nonlinear head: hs:%d, skb_hlen:%d\n", | ||
| 193 | gso_hs, skb_hlen); | ||
| 194 | |||
| 195 | return -EINVAL; | ||
| 196 | } | ||
| 197 | |||
| 198 | return num_sge; | ||
| 199 | } | ||
| 200 | |||
| 201 | /* Get the GSO packet's header size */ | ||
| 202 | static int mana_get_gso_hs(struct sk_buff *skb) | ||
| 203 | { | ||
| 204 | int gso_hs; | ||
| 205 | |||
| 206 | if (skb->encapsulation) { | ||
| 207 | gso_hs = skb_inner_tcp_all_headers(skb); | ||
| 208 | } else { | ||
| 209 | if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) { | ||
| 210 | gso_hs = skb_transport_offset(skb) + | ||
| 211 | sizeof(struct udphdr); | ||
| 212 | } else { | ||
| 213 | gso_hs = skb_tcp_all_headers(skb); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | return gso_hs; | ||
| 218 | } | ||
| 219 | |||
| 147 | netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) | 220 | netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
| 148 | { | 221 | { |
| 149 | enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT; | 222 | enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT; |
| 150 | struct mana_port_context *apc = netdev_priv(ndev); | 223 | struct mana_port_context *apc = netdev_priv(ndev); |
| 224 | int gso_hs = 0; /* zero for non-GSO pkts */ | ||
| 151 | u16 txq_idx = skb_get_queue_mapping(skb); | 225 | u16 txq_idx = skb_get_queue_mapping(skb); |
| 152 | struct gdma_dev *gd = apc->ac->gdma_dev; | 226 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 153 | bool ipv4 = false, ipv6 = false; | 227 | bool ipv4 = false, ipv6 = false; |
| @@ -159,7 +233,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 5 unmodified lines | |||
| 159 | struct mana_txq *txq; | 233 | struct mana_txq *txq; |
| 160 | struct mana_cq *cq; | 234 | struct mana_cq *cq; |
| 161 | int err, len; | 235 | int err, len; |
| 162 | u16 ihs; | ||
| 163 | 236 | ||
| 164 | if (unlikely(!apc->port_is_up)) | 237 | if (unlikely(!apc->port_is_up)) |
| 165 | goto tx_drop; | 238 | goto tx_drop; |
| @@ -209,19 +282,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 43 unmodified lines | |||
| 209 | pkg.wqe_req.client_data_unit = 0; | 282 | pkg.wqe_req.client_data_unit = 0; |
| 210 | 283 | ||
| 211 | pkg.wqe_req.num_sge = 1 + skb_shinfo(skb)->nr_frags; | 284 | pkg.wqe_req.num_sge = 1 + skb_shinfo(skb)->nr_frags; |
| 212 | WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES); | ||
| 213 | |||
| 214 | if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) { | ||
| 215 | pkg.wqe_req.sgl = pkg.sgl_array; | ||
| 216 | } else { | ||
| 217 | pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge, | ||
| 218 | sizeof(struct gdma_sge), | ||
| 219 | GFP_ATOMIC); | ||
| 220 | if (!pkg.sgl_ptr) | ||
| 221 | goto tx_drop_count; | ||
| 222 | |||
| 223 | pkg.wqe_req.sgl = pkg.sgl_ptr; | ||
| 224 | } | ||
| 225 | 285 | ||
| 226 | if (skb->protocol == htons(ETH_P_IP)) | 286 | if (skb->protocol == htons(ETH_P_IP)) |
| 227 | ipv4 = true; | 287 | ipv4 = true; |
| @@ -229,6 +289,26 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 1 unmodified line | |||
| 229 | ipv6 = true; | 289 | ipv6 = true; |
| 230 | 290 | ||
| 231 | if (skb_is_gso(skb)) { | 291 | if (skb_is_gso(skb)) { |
| 292 | int num_sge; | ||
| 293 | |||
| 294 | gso_hs = mana_get_gso_hs(skb); | ||
| 295 | |||
| 296 | num_sge = mana_fix_skb_head(ndev, skb, gso_hs); | ||
| 297 | if (num_sge > 0) | ||
| 298 | pkg.wqe_req.num_sge = num_sge; | ||
| 299 | else | ||
| 300 | goto tx_drop_count; | ||
| 301 | |||
| 302 | u64_stats_update_begin(&tx_stats->syncp); | ||
| 303 | if (skb->encapsulation) { | ||
| 304 | tx_stats->tso_inner_packets++; | ||
| 305 | tx_stats->tso_inner_bytes += skb->len - gso_hs; | ||
| 306 | } else { | ||
| 307 | tx_stats->tso_packets++; | ||
| 308 | tx_stats->tso_bytes += skb->len - gso_hs; | ||
| 309 | } | ||
| 310 | u64_stats_update_end(&tx_stats->syncp); | ||
| 311 | |||
| 232 | pkg.tx_oob.s_oob.is_outer_ipv4 = ipv4; | 312 | pkg.tx_oob.s_oob.is_outer_ipv4 = ipv4; |
| 233 | pkg.tx_oob.s_oob.is_outer_ipv6 = ipv6; | 313 | pkg.tx_oob.s_oob.is_outer_ipv6 = ipv6; |
| 234 | 314 | ||
| @@ -252,28 +332,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 17 unmodified lines | |||
| 252 | &ipv6_hdr(skb)->daddr, 0, | 332 | &ipv6_hdr(skb)->daddr, 0, |
| 253 | IPPROTO_TCP, 0); | 333 | IPPROTO_TCP, 0); |
| 254 | } | 334 | } |
| 255 | |||
| 256 | if (skb->encapsulation) { | ||
| 257 | ihs = skb_inner_tcp_all_headers(skb); | ||
| 258 | u64_stats_update_begin(&tx_stats->syncp); | ||
| 259 | tx_stats->tso_inner_packets++; | ||
| 260 | tx_stats->tso_inner_bytes += skb->len - ihs; | ||
| 261 | u64_stats_update_end(&tx_stats->syncp); | ||
| 262 | } else { | ||
| 263 | if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) { | ||
| 264 | ihs = skb_transport_offset(skb) + sizeof(struct udphdr); | ||
| 265 | } else { | ||
| 266 | ihs = skb_tcp_all_headers(skb); | ||
| 267 | if (ipv6_has_hopopt_jumbo(skb)) | ||
| 268 | ihs -= sizeof(struct hop_jumbo_hdr); | ||
| 269 | } | ||
| 270 | |||
| 271 | u64_stats_update_begin(&tx_stats->syncp); | ||
| 272 | tx_stats->tso_packets++; | ||
| 273 | tx_stats->tso_bytes += skb->len - ihs; | ||
| 274 | u64_stats_update_end(&tx_stats->syncp); | ||
| 275 | } | ||
| 276 | |||
| 277 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { | 335 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { |
| 278 | csum_type = mana_checksum_info(skb); | 336 | csum_type = mana_checksum_info(skb); |
| 279 | 337 | ||
| @@ -296,11 +354,25 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 16 unmodified lines | |||
| 296 | } else { | 354 | } else { |
| 297 | /* Can't do offload of this type of checksum */ | 355 | /* Can't do offload of this type of checksum */ |
| 298 | if (skb_checksum_help(skb)) | 356 | if (skb_checksum_help(skb)) |
| 299 | goto free_sgl_ptr; | 357 | goto tx_drop_count; |
| 300 | } | 358 | } |
| 301 | } | 359 | } |
| 302 | 360 | ||
| 303 | if (mana_map_skb(skb, apc, &pkg)) { | 361 | WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES); |
| 362 | |||
| 363 | if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) { | ||
| 364 | pkg.wqe_req.sgl = pkg.sgl_array; | ||
| 365 | } else { | ||
| 366 | pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge, | ||
| 367 | sizeof(struct gdma_sge), | ||
| 368 | GFP_ATOMIC); | ||
| 369 | if (!pkg.sgl_ptr) | ||
| 370 | goto tx_drop_count; | ||
| 371 | |||
| 372 | pkg.wqe_req.sgl = pkg.sgl_ptr; | ||
| 373 | } | ||
| 374 | |||
| 375 | if (mana_map_skb(skb, apc, &pkg, gso_hs)) { | ||
| 304 | u64_stats_update_begin(&tx_stats->syncp); | 376 | u64_stats_update_begin(&tx_stats->syncp); |
| 305 | tx_stats->mana_map_err++; | 377 | tx_stats->mana_map_err++; |
| 306 | u64_stats_update_end(&tx_stats->syncp); | 378 | u64_stats_update_end(&tx_stats->syncp); |
| @@ -1258,11 +1330,16 @@ static void mana_unmap_skb(struct sk_buff *skb, struct mana_port_context *apc) · 951 unmodified lines | |||
| 1258 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; | 1330 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; |
| 1259 | struct gdma_context *gc = apc->ac->gdma_dev->gdma_context; | 1331 | struct gdma_context *gc = apc->ac->gdma_dev->gdma_context; |
| 1260 | struct device *dev = gc->dev; | 1332 | struct device *dev = gc->dev; |
| 1261 | int i; | 1333 | int hsg, i; |
| 1262 | 1334 | ||
| 1263 | dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE); | 1335 | /* Number of SGEs of linear part */ |
| 1336 | hsg = (skb_is_gso(skb) && skb_headlen(skb) > ash->size[0]) ? 2 : 1; | ||
| 1264 | 1337 | ||
| 1265 | for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++) | 1338 | for (i = 0; i < hsg; i++) |
| 1339 | dma_unmap_single(dev, ash->dma_handle[i], ash->size[i], | ||
| 1340 | DMA_TO_DEVICE); | ||
| 1341 | |||
| 1342 | for (i = hsg; i < skb_shinfo(skb)->nr_frags + hsg; i++) | ||
| 1266 | dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], | 1343 | dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], |
| 1267 | DMA_TO_DEVICE); | 1344 | DMA_TO_DEVICE); |
| 1268 | } | 1345 | } |
| @@ -1317,19 +1394,23 @@ static void mana_poll_tx_cq(struct mana_cq *cq) · 48 unmodified lines | |||
| 1317 | case CQE_TX_VPORT_IDX_OUT_OF_RANGE: | 1394 | case CQE_TX_VPORT_IDX_OUT_OF_RANGE: |
| 1318 | case CQE_TX_VPORT_DISABLED: | 1395 | case CQE_TX_VPORT_DISABLED: |
| 1319 | case CQE_TX_VLAN_TAGGING_VIOLATION: | 1396 | case CQE_TX_VLAN_TAGGING_VIOLATION: |
| 1320 | WARN_ONCE(1, "TX: CQE error %d: ignored.\n", | 1397 | if (net_ratelimit()) |
| 1321 | cqe_oob->cqe_hdr.cqe_type); | 1398 | netdev_err(ndev, "TX: CQE error %d\n", |
| 1399 | cqe_oob->cqe_hdr.cqe_type); | ||
| 1400 | |||
| 1322 | apc->eth_stats.tx_cqe_err++; | 1401 | apc->eth_stats.tx_cqe_err++; |
| 1323 | break; | 1402 | break; |
| 1324 | 1403 | ||
| 1325 | default: | 1404 | default: |
| 1326 | /* If the CQE type is unexpected, log an error, assert, | 1405 | /* If the CQE type is unknown, log an error, |
| 1327 | * and go through the error path. | 1406 | * and still free the SKB, update tail, etc. |
| 1328 | */ | 1407 | */ |
| 1329 | WARN_ONCE(1, "TX: Unexpected CQE type %d: HW BUG?\n", | 1408 | if (net_ratelimit()) |
| 1330 | cqe_oob->cqe_hdr.cqe_type); | 1409 | netdev_err(ndev, "TX: unknown CQE type %d\n", |
| 1410 | cqe_oob->cqe_hdr.cqe_type); | ||
| 1411 | |||
| 1331 | apc->eth_stats.tx_cqe_unknown_type++; | 1412 | apc->eth_stats.tx_cqe_unknown_type++; |
| 1332 | return; | 1413 | break; |
| 1333 | } | 1414 | } |
| 1334 | 1415 | ||
| 1335 | if (WARN_ON_ONCE(txq->gdma_txq_id != completions[i].wq_num)) | 1416 | if (WARN_ON_ONCE(txq->gdma_txq_id != completions[i].wq_num)) |
| @@ -110,9 +110,9 @@ struct qed_ll2_info { · 109 unmodified lines | |||
| 110 | enum core_tx_dest tx_dest; | 110 | enum core_tx_dest tx_dest; |
| 111 | u8 tx_stats_en; | 111 | u8 tx_stats_en; |
| 112 | bool main_func_queue; | 112 | bool main_func_queue; |
| 113 | struct qed_ll2_cbs cbs; | ||
| 113 | struct qed_ll2_rx_queue rx_queue; | 114 | struct qed_ll2_rx_queue rx_queue; |
| 114 | struct qed_ll2_tx_queue tx_queue; | 115 | struct qed_ll2_tx_queue tx_queue; |
| 115 | struct qed_ll2_cbs cbs; | ||
| 116 | }; | 116 | }; |
| 117 | 117 | ||
| 118 | extern const struct qed_ll2_ops qed_ll2_ops_pass; | 118 | extern const struct qed_ll2_ops qed_ll2_ops_pass; |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | * Copyright (C) 2022 Renesas Electronics Corporation | 4 | * Copyright (C) 2022 Renesas Electronics Corporation |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/clk.h> | ||
| 7 | #include <linux/dma-mapping.h> | 8 | #include <linux/dma-mapping.h> |
| 8 | #include <linux/err.h> | 9 | #include <linux/err.h> |
| 9 | #include <linux/etherdevice.h> | 10 | #include <linux/etherdevice.h> |
| @@ -1049,7 +1050,7 @@ static void rswitch_rmac_setting(struct rswitch_etha *etha, const u8 *mac) · 1039 unmodified lines | |||
| 1049 | static void rswitch_etha_enable_mii(struct rswitch_etha *etha) | 1050 | static void rswitch_etha_enable_mii(struct rswitch_etha *etha) |
| 1050 | { | 1051 | { |
| 1051 | rswitch_modify(etha->addr, MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK, | 1052 | rswitch_modify(etha->addr, MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK, |
| 1052 | MPIC_PSMCS(0x05) | MPIC_PSMHT(0x06)); | 1053 | MPIC_PSMCS(etha->psmcs) | MPIC_PSMHT(0x06)); |
| 1053 | rswitch_modify(etha->addr, MPSM, 0, MPSM_MFF_C45); | 1054 | rswitch_modify(etha->addr, MPSM, 0, MPSM_MFF_C45); |
| 1054 | } | 1055 | } |
| 1055 | 1056 | ||
| @@ -1693,6 +1694,12 @@ static void rswitch_etha_init(struct rswitch_private *priv, int index) · 637 unmodified lines | |||
| 1693 | etha->index = index; | 1694 | etha->index = index; |
| 1694 | etha->addr = priv->addr + RSWITCH_ETHA_OFFSET + index * RSWITCH_ETHA_SIZE; | 1695 | etha->addr = priv->addr + RSWITCH_ETHA_OFFSET + index * RSWITCH_ETHA_SIZE; |
| 1695 | etha->coma_addr = priv->addr; | 1696 | etha->coma_addr = priv->addr; |
| 1697 | |||
| 1698 | /* MPIC.PSMCS = (clk [MHz] / (MDC frequency [MHz] * 2) - 1. | ||
| 1699 | * Calculating PSMCS value as MDC frequency = 2.5MHz. So, multiply | ||
| 1700 | * both the numerator and the denominator by 10. | ||
| 1701 | */ | ||
| 1702 | etha->psmcs = clk_get_rate(priv->clk) / 100000 / (25 * 2) - 1; | ||
| 1696 | } | 1703 | } |
| 1697 | 1704 | ||
| 1698 | static int rswitch_device_alloc(struct rswitch_private *priv, int index) | 1705 | static int rswitch_device_alloc(struct rswitch_private *priv, int index) |
| @@ -1900,6 +1907,10 @@ static int renesas_eth_sw_probe(struct platform_device *pdev) · 201 unmodified lines | |||
| 1900 | return -ENOMEM; | 1907 | return -ENOMEM; |
| 1901 | spin_lock_init(&priv->lock); | 1908 | spin_lock_init(&priv->lock); |
| 1902 | 1909 | ||
| 1910 | priv->clk = devm_clk_get(&pdev->dev, NULL); | ||
| 1911 | if (IS_ERR(priv->clk)) | ||
| 1912 | return PTR_ERR(priv->clk); | ||
| 1913 | |||
| 1903 | attr = soc_device_match(rswitch_soc_no_speed_change); | 1914 | attr = soc_device_match(rswitch_soc_no_speed_change); |
| 1904 | if (attr) | 1915 | if (attr) |
| 1905 | priv->etha_no_runtime_change = true; | 1916 | priv->etha_no_runtime_change = true; |
| @@ -915,6 +915,7 @@ struct rswitch_etha { · 914 unmodified lines | |||
| 915 | bool external_phy; | 915 | bool external_phy; |
| 916 | struct mii_bus *mii; | 916 | struct mii_bus *mii; |
| 917 | phy_interface_t phy_interface; | 917 | phy_interface_t phy_interface; |
| 918 | u32 psmcs; | ||
| 918 | u8 mac_addr[MAX_ADDR_LEN]; | 919 | u8 mac_addr[MAX_ADDR_LEN]; |
| 919 | int link; | 920 | int link; |
| 920 | int speed; | 921 | int speed; |
| @@ -1012,6 +1013,7 @@ struct rswitch_private { · 91 unmodified lines | |||
| 1012 | struct rswitch_mfwd mfwd; | 1013 | struct rswitch_mfwd mfwd; |
| 1013 | 1014 | ||
| 1014 | spinlock_t lock; /* lock interrupt registers' control */ | 1015 | spinlock_t lock; /* lock interrupt registers' control */ |
| 1016 | struct clk *clk; | ||
| 1015 | 1017 | ||
| 1016 | bool etha_no_runtime_change; | 1018 | bool etha_no_runtime_change; |
| 1017 | bool gwca_halt; | 1019 | bool gwca_halt; |
| @@ -104,6 +104,7 @@ struct stm32_ops { · 103 unmodified lines | |||
| 104 | int (*parse_data)(struct stm32_dwmac *dwmac, | 104 | int (*parse_data)(struct stm32_dwmac *dwmac, |
| 105 | struct device *dev); | 105 | struct device *dev); |
| 106 | u32 syscfg_eth_mask; | 106 | u32 syscfg_eth_mask; |
| 107 | bool clk_rx_enable_in_suspend; | ||
| 107 | }; | 108 | }; |
| 108 | 109 | ||
| 109 | static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) | 110 | static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) |
| @@ -121,7 +122,8 @@ static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) · 11 unmodified lines | |||
| 121 | if (ret) | 122 | if (ret) |
| 122 | return ret; | 123 | return ret; |
| 123 | 124 | ||
| 124 | if (!dwmac->dev->power.is_suspended) { | 125 | if (!dwmac->ops->clk_rx_enable_in_suspend || |
| 126 | !dwmac->dev->power.is_suspended) { | ||
| 125 | ret = clk_prepare_enable(dwmac->clk_rx); | 127 | ret = clk_prepare_enable(dwmac->clk_rx); |
| 126 | if (ret) { | 128 | if (ret) { |
| 127 | clk_disable_unprepare(dwmac->clk_tx); | 129 | clk_disable_unprepare(dwmac->clk_tx); |
| @@ -513,7 +515,8 @@ static struct stm32_ops stm32mp1_dwmac_data = { · 385 unmodified lines | |||
| 513 | .suspend = stm32mp1_suspend, | 515 | .suspend = stm32mp1_suspend, |
| 514 | .resume = stm32mp1_resume, | 516 | .resume = stm32mp1_resume, |
| 515 | .parse_data = stm32mp1_parse_data, | 517 | .parse_data = stm32mp1_parse_data, |
| 516 | .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK | 518 | .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK, |
| 519 | .clk_rx_enable_in_suspend = true | ||
| 517 | }; | 520 | }; |
| 518 | 521 | ||
| 519 | static const struct of_device_id stm32_dwmac_match[] = { | 522 | static const struct of_device_id stm32_dwmac_match[] = { |
| @@ -6002,33 +6002,6 @@ static irqreturn_t stmmac_msi_intr_rx(int irq, void *data) · 6001 unmodified lines | |||
| 6002 | return IRQ_HANDLED; | 6002 | return IRQ_HANDLED; |
| 6003 | } | 6003 | } |
| 6004 | 6004 | ||
| 6005 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 6006 | /* Polling receive - used by NETCONSOLE and other diagnostic tools | ||
| 6007 | * to allow network I/O with interrupts disabled. | ||
| 6008 | */ | ||
| 6009 | static void stmmac_poll_controller(struct net_device *dev) | ||
| 6010 | { | ||
| 6011 | struct stmmac_priv *priv = netdev_priv(dev); | ||
| 6012 | int i; | ||
| 6013 | |||
| 6014 | /* If adapter is down, do nothing */ | ||
| 6015 | if (test_bit(STMMAC_DOWN, &priv->state)) | ||
| 6016 | return; | ||
| 6017 | |||
| 6018 | if (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN) { | ||
| 6019 | for (i = 0; i < priv->plat->rx_queues_to_use; i++) | ||
| 6020 | stmmac_msi_intr_rx(0, &priv->dma_conf.rx_queue[i]); | ||
| 6021 | |||
| 6022 | for (i = 0; i < priv->plat->tx_queues_to_use; i++) | ||
| 6023 | stmmac_msi_intr_tx(0, &priv->dma_conf.tx_queue[i]); | ||
| 6024 | } else { | ||
| 6025 | disable_irq(dev->irq); | ||
| 6026 | stmmac_interrupt(dev->irq, dev); | ||
| 6027 | enable_irq(dev->irq); | ||
| 6028 | } | ||
| 6029 | } | ||
| 6030 | #endif | ||
| 6031 | |||
| 6032 | /** | 6005 | /** |
| 6033 | * stmmac_ioctl - Entry point for the Ioctl | 6006 | * stmmac_ioctl - Entry point for the Ioctl |
| 6034 | * @dev: Device pointer. | 6007 | * @dev: Device pointer. |
| @@ -6989,9 +6962,6 @@ static const struct net_device_ops stmmac_netdev_ops = { · 954 unmodified lines | |||
| 6989 | .ndo_get_stats64 = stmmac_get_stats64, | 6962 | .ndo_get_stats64 = stmmac_get_stats64, |
| 6990 | .ndo_setup_tc = stmmac_setup_tc, | 6963 | .ndo_setup_tc = stmmac_setup_tc, |
| 6991 | .ndo_select_queue = stmmac_select_queue, | 6964 | .ndo_select_queue = stmmac_select_queue, |
| 6992 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 6993 | .ndo_poll_controller = stmmac_poll_controller, | ||
| 6994 | #endif | ||
| 6995 | .ndo_set_mac_address = stmmac_set_mac_address, | 6965 | .ndo_set_mac_address = stmmac_set_mac_address, |
| 6996 | .ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid, | 6966 | .ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid, |
| 6997 | .ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid, | 6967 | .ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid, |
| @@ -901,7 +901,7 @@ static int __maybe_unused stmmac_pltfr_resume(struct device *dev) · 900 unmodified lines | |||
| 901 | struct platform_device *pdev = to_platform_device(dev); | 901 | struct platform_device *pdev = to_platform_device(dev); |
| 902 | int ret; | 902 | int ret; |
| 903 | 903 | ||
| 904 | ret = stmmac_pltfr_init(pdev, priv->plat->bsp_priv); | 904 | ret = stmmac_pltfr_init(pdev, priv->plat); |
| 905 | if (ret) | 905 | if (ret) |
| 906 | return ret; | 906 | return ret; |
| 907 | 907 | ||
| @@ -1747,9 +1747,10 @@ static int am65_cpsw_nuss_init_tx_chns(struct am65_cpsw_common *common) · 1746 unmodified lines | |||
| 1747 | } | 1747 | } |
| 1748 | 1748 | ||
| 1749 | tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); | 1749 | tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); |
| 1750 | if (tx_chn->irq <= 0) { | 1750 | if (tx_chn->irq < 0) { |
| 1751 | dev_err(dev, "Failed to get tx dma irq %d\n", | 1751 | dev_err(dev, "Failed to get tx dma irq %d\n", |
| 1752 | tx_chn->irq); | 1752 | tx_chn->irq); |
| 1753 | ret = tx_chn->irq; | ||
| 1753 | goto err; | 1754 | goto err; |
| 1754 | } | 1755 | } |
| 1755 | 1756 | ||
| @@ -316,12 +316,12 @@ static int prueth_init_tx_chns(struct prueth_emac *emac) · 315 unmodified lines | |||
| 316 | goto fail; | 316 | goto fail; |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); | 319 | ret = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); |
| 320 | if (tx_chn->irq <= 0) { | 320 | if (ret < 0) { |
| 321 | ret = -EINVAL; | ||
| 322 | netdev_err(ndev, "failed to get tx irq\n"); | 321 | netdev_err(ndev, "failed to get tx irq\n"); |
| 323 | goto fail; | 322 | goto fail; |
| 324 | } | 323 | } |
| 324 | tx_chn->irq = ret; | ||
| 325 | 325 | ||
| 326 | snprintf(tx_chn->name, sizeof(tx_chn->name), "%s-tx%d", | 326 | snprintf(tx_chn->name, sizeof(tx_chn->name), "%s-tx%d", |
| 327 | dev_name(dev), tx_chn->id); | 327 | dev_name(dev), tx_chn->id); |
| @@ -90,7 +90,9 @@ static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index, · 89 unmodified lines | |||
| 90 | ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN | 90 | ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN |
| 91 | | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 91 | | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 92 | 0, index, &buf, 4); | 92 | 0, index, &buf, 4); |
| 93 | if (unlikely(ret < 0)) { | 93 | if (unlikely(ret < 4)) { |
| 94 | ret = ret < 0 ? ret : -ENODATA; | ||
| 95 | |||
| 94 | netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n", | 96 | netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n", |
| 95 | index, ret); | 97 | index, ret); |
| 96 | return ret; | 98 | return ret; |
| @@ -34,6 +34,8 @@ · 33 unmodified lines | |||
| 34 | #define TDM_PPPOHT_SLIC_MAXIN | 34 | #define TDM_PPPOHT_SLIC_MAXIN |
| 35 | #define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S) | 35 | #define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S) |
| 36 | 36 | ||
| 37 | static int uhdlc_close(struct net_device *dev); | ||
| 38 | |||
| 37 | static struct ucc_tdm_info utdm_primary_info = { | 39 | static struct ucc_tdm_info utdm_primary_info = { |
| 38 | .uf_info = { | 40 | .uf_info = { |
| 39 | .tsa = 0, | 41 | .tsa = 0, |
| @@ -708,6 +710,7 @@ static int uhdlc_open(struct net_device *dev) · 668 unmodified lines | |||
| 708 | hdlc_device *hdlc = dev_to_hdlc(dev); | 710 | hdlc_device *hdlc = dev_to_hdlc(dev); |
| 709 | struct ucc_hdlc_private *priv = hdlc->priv; | 711 | struct ucc_hdlc_private *priv = hdlc->priv; |
| 710 | struct ucc_tdm *utdm = priv->utdm; | 712 | struct ucc_tdm *utdm = priv->utdm; |
| 713 | int rc = 0; | ||
| 711 | 714 | ||
| 712 | if (priv->hdlc_busy != 1) { | 715 | if (priv->hdlc_busy != 1) { |
| 713 | if (request_irq(priv->ut_info->uf_info.irq, | 716 | if (request_irq(priv->ut_info->uf_info.irq, |
| @@ -731,10 +734,13 @@ static int uhdlc_open(struct net_device *dev) · 17 unmodified lines | |||
| 731 | napi_enable(&priv->napi); | 734 | napi_enable(&priv->napi); |
| 732 | netdev_reset_queue(dev); | 735 | netdev_reset_queue(dev); |
| 733 | netif_start_queue(dev); | 736 | netif_start_queue(dev); |
| 734 | hdlc_open(dev); | 737 | |
| 738 | rc = hdlc_open(dev); | ||
| 739 | if (rc) | ||
| 740 | uhdlc_close(dev); | ||
| 735 | } | 741 | } |
| 736 | 742 | ||
| 737 | return 0; | 743 | return rc; |
| 738 | } | 744 | } |
| 739 | 745 | ||
| 740 | static void uhdlc_memclean(struct ucc_hdlc_private *priv) | 746 | static void uhdlc_memclean(struct ucc_hdlc_private *priv) |
| @@ -824,6 +830,8 @@ static int uhdlc_close(struct net_device *dev) · 83 unmodified lines | |||
| 824 | netdev_reset_queue(dev); | 830 | netdev_reset_queue(dev); |
| 825 | priv->hdlc_busy = 0; | 831 | priv->hdlc_busy = 0; |
| 826 | 832 | ||
| 833 | hdlc_close(dev); | ||
| 834 | |||
| 827 | return 0; | 835 | return 0; |
| 828 | } | 836 | } |
| 829 | 837 | ||
| @@ -442,7 +442,12 @@ struct brcmf_scan_params_v2_le { · 441 unmodified lines | |||
| 442 | * fixed parameter portion is assumed, otherwise | 442 | * fixed parameter portion is assumed, otherwise |
| 443 | * ssid in the fixed portion is ignored | 443 | * ssid in the fixed portion is ignored |
| 444 | */ | 444 | */ |
| 445 | __le16 channel_list[1]; /* list of chanspecs */ | 445 | union { |
| 446 | __le16 padding; /* Reserve space for at least 1 entry for abort | ||
| 447 | * which uses an on stack brcmf_scan_params_v2_le | ||
| 448 | */ | ||
| 449 | DECLARE_FLEX_ARRAY(__le16, channel_list); /* chanspecs */ | ||
| 450 | }; | ||
| 446 | }; | 451 | }; |
| 447 | 452 | ||
| 448 | struct brcmf_scan_results { | 453 | struct brcmf_scan_results { |
| @@ -702,7 +707,7 @@ struct brcmf_sta_info_le { · 253 unmodified lines | |||
| 702 | 707 | ||
| 703 | struct brcmf_chanspec_list { | 708 | struct brcmf_chanspec_list { |
| 704 | __le32 count; /* # of entries */ | 709 | __le32 count; /* # of entries */ |
| 705 | __le32 element[1]; /* variable length uint32 list */ | 710 | __le32 element[]; /* variable length uint32 list */ |
| 706 | }; | 711 | }; |
| 707 | 712 | ||
| 708 | /* | 713 | /* |
| @@ -310,9 +310,9 @@ struct iwl_fw_ini_fifo_hdr { · 309 unmodified lines | |||
| 310 | struct iwl_fw_ini_error_dump_range { | 310 | struct iwl_fw_ini_error_dump_range { |
| 311 | __le32 range_data_size; | 311 | __le32 range_data_size; |
| 312 | union { | 312 | union { |
| 313 | __le32 internal_base_addr; | 313 | __le32 internal_base_addr __packed; |
| 314 | __le64 dram_base_addr; | 314 | __le64 dram_base_addr __packed; |
| 315 | __le32 page_num; | 315 | __le32 page_num __packed; |
| 316 | struct iwl_fw_ini_fifo_hdr fifo_hdr; | 316 | struct iwl_fw_ini_fifo_hdr fifo_hdr; |
| 317 | struct iwl_cmd_header fw_pkt_hdr; | 317 | struct iwl_cmd_header fw_pkt_hdr; |
| 318 | }; | 318 | }; |
| @@ -802,7 +802,7 @@ out: · 801 unmodified lines | |||
| 802 | mvm->nvm_data->bands[0].n_channels = 1; | 802 | mvm->nvm_data->bands[0].n_channels = 1; |
| 803 | mvm->nvm_data->bands[0].n_bitrates = 1; | 803 | mvm->nvm_data->bands[0].n_bitrates = 1; |
| 804 | mvm->nvm_data->bands[0].bitrates = | 804 | mvm->nvm_data->bands[0].bitrates = |
| 805 | (void *)((u8 *)mvm->nvm_data->channels + 1); | 805 | (void *)(mvm->nvm_data->channels + 1); |
| 806 | mvm->nvm_data->bands[0].bitrates->hw_value = 10; | 806 | mvm->nvm_data->bands[0].bitrates->hw_value = 10; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| @@ -731,73 +731,78 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm, · 730 unmodified lines | |||
| 731 | 731 | ||
| 732 | mvmvif->associated = vif->cfg.assoc; | 732 | mvmvif->associated = vif->cfg.assoc; |
| 733 | 733 | ||
| 734 | if (!(changes & BSS_CHANGED_ASSOC)) | 734 | if (changes & BSS_CHANGED_ASSOC) { |
| 735 | return; | 735 | if (vif->cfg.assoc) { |
| 736 | 736 | /* clear statistics to get clean beacon counter */ | |
| 737 | if (vif->cfg.assoc) { | 737 | iwl_mvm_request_statistics(mvm, true); |
| 738 | /* clear statistics to get clean beacon counter */ | 738 | iwl_mvm_sf_update(mvm, vif, false); |
| 739 | iwl_mvm_request_statistics(mvm, true); | 739 | iwl_mvm_power_vif_assoc(mvm, vif); |
| 740 | iwl_mvm_sf_update(mvm, vif, false); | 740 | |
| 741 | iwl_mvm_power_vif_assoc(mvm, vif); | 741 | for_each_mvm_vif_valid_link(mvmvif, i) { |
| 742 | 742 | memset(&mvmvif->link[i]->beacon_stats, 0, | |
| 743 | for_each_mvm_vif_valid_link(mvmvif, i) { | 743 | sizeof(mvmvif->link[i]->beacon_stats)); |
| 744 | memset(&mvmvif->link[i]->beacon_stats, 0, | 744 | |
| 745 | sizeof(mvmvif->link[i]->beacon_stats)); | 745 | if (vif->p2p) { |
| 746 | iwl_mvm_update_smps(mvm, vif, | ||
| 747 | IWL_MVM_SMPS_REQ_PROT, | ||
| 748 | IEEE80211_SMPS_DYNAMIC, i); | ||
| 749 | } | ||
| 750 | |||
| 751 | rcu_read_lock(); | ||
| 752 | link_conf = rcu_dereference(vif->link_conf[i]); | ||
| 753 | if (link_conf && !link_conf->dtim_period) | ||
| 754 | protect = true; | ||
| 755 | rcu_read_unlock(); | ||
| 756 | } | ||
| 746 | 757 | ||
| 747 | if (vif->p2p) { | 758 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && |
| 748 | iwl_mvm_update_smps(mvm, vif, | 759 | protect) { |
| 749 | IWL_MVM_SMPS_REQ_PROT, | 760 | /* If we're not restarting and still haven't |
| 750 | IEEE80211_SMPS_DYNAMIC, i); | 761 | * heard a beacon (dtim period unknown) then |
| 762 | * make sure we still have enough minimum time | ||
| 763 | * remaining in the time event, since the auth | ||
| 764 | * might actually have taken quite a while | ||
| 765 | * (especially for SAE) and so the remaining | ||
| 766 | * time could be small without us having heard | ||
| 767 | * a beacon yet. | ||
| 768 | */ | ||
| 769 | iwl_mvm_protect_assoc(mvm, vif, 0); | ||
| 751 | } | 770 | } |
| 752 | 771 | ||
| 753 | rcu_read_lock(); | 772 | iwl_mvm_sf_update(mvm, vif, false); |
| 754 | link_conf = rcu_dereference(vif->link_conf[i]); | 773 | |
| 755 | if (link_conf && !link_conf->dtim_period) | 774 | /* FIXME: need to decide about misbehaving AP handling */ |
| 756 | protect = true; | 775 | iwl_mvm_power_vif_assoc(mvm, vif); |
| 757 | rcu_read_unlock(); | 776 | } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { |
| 758 | } | 777 | iwl_mvm_mei_host_disassociated(mvm); |
| 759 | 778 | ||
| 760 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && | 779 | /* If update fails - SF might be running in associated |
| 761 | protect) { | 780 | * mode while disassociated - which is forbidden. |
| 762 | /* If we're not restarting and still haven't | ||
| 763 | * heard a beacon (dtim period unknown) then | ||
| 764 | * make sure we still have enough minimum time | ||
| 765 | * remaining in the time event, since the auth | ||
| 766 | * might actually have taken quite a while | ||
| 767 | * (especially for SAE) and so the remaining | ||
| 768 | * time could be small without us having heard | ||
| 769 | * a beacon yet. | ||
| 770 | */ | 781 | */ |
| 771 | iwl_mvm_protect_assoc(mvm, vif, 0); | 782 | ret = iwl_mvm_sf_update(mvm, vif, false); |
| 783 | WARN_ONCE(ret && | ||
| 784 | !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | ||
| 785 | &mvm->status), | ||
| 786 | "Failed to update SF upon disassociation\n"); | ||
| 787 | |||
| 788 | /* If we get an assert during the connection (after the | ||
| 789 | * station has been added, but before the vif is set | ||
| 790 | * to associated), mac80211 will re-add the station and | ||
| 791 | * then configure the vif. Since the vif is not | ||
| 792 | * associated, we would remove the station here and | ||
| 793 | * this would fail the recovery. | ||
| 794 | */ | ||
| 795 | iwl_mvm_mld_vif_delete_all_stas(mvm, vif); | ||
| 772 | } | 796 | } |
| 773 | 797 | ||
| 774 | iwl_mvm_sf_update(mvm, vif, false); | 798 | iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); |
| 775 | |||
| 776 | /* FIXME: need to decide about misbehaving AP handling */ | ||
| 777 | iwl_mvm_power_vif_assoc(mvm, vif); | ||
| 778 | } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { | ||
| 779 | iwl_mvm_mei_host_disassociated(mvm); | ||
| 780 | |||
| 781 | /* If update fails - SF might be running in associated | ||
| 782 | * mode while disassociated - which is forbidden. | ||
| 783 | */ | ||
| 784 | ret = iwl_mvm_sf_update(mvm, vif, false); | ||
| 785 | WARN_ONCE(ret && | ||
| 786 | !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | ||
| 787 | &mvm->status), | ||
| 788 | "Failed to update SF upon disassociation\n"); | ||
| 789 | |||
| 790 | /* If we get an assert during the connection (after the | ||
| 791 | * station has been added, but before the vif is set | ||
| 792 | * to associated), mac80211 will re-add the station and | ||
| 793 | * then configure the vif. Since the vif is not | ||
| 794 | * associated, we would remove the station here and | ||
| 795 | * this would fail the recovery. | ||
| 796 | */ | ||
| 797 | iwl_mvm_mld_vif_delete_all_stas(mvm, vif); | ||
| 798 | } | 799 | } |
| 799 | 800 | ||
| 800 | iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); | 801 | if (changes & BSS_CHANGED_PS) { |
| 802 | ret = iwl_mvm_power_update_mac(mvm); | ||
| 803 | if (ret) | ||
| 804 | IWL_ERR(mvm, "failed to update power mode\n"); | ||
| 805 | } | ||
| 801 | } | 806 | } |
| 802 | 807 | ||
| 803 | static void | 808 | static void |
| @@ -2342,7 +2342,7 @@ iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm, · 2341 unmodified lines | |||
| 2342 | if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) | 2342 | if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) |
| 2343 | gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; | 2343 | gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; |
| 2344 | 2344 | ||
| 2345 | if (version < 12) { | 2345 | if (version < 16) { |
| 2346 | gp->scan_start_mac_or_link_id = scan_vif->id; | 2346 | gp->scan_start_mac_or_link_id = scan_vif->id; |
| 2347 | } else { | 2347 | } else { |
| 2348 | struct iwl_mvm_vif_link_info *link_info; | 2348 | struct iwl_mvm_vif_link_info *link_info; |
| @@ -1612,6 +1612,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, · 1611 unmodified lines | |||
| 1612 | iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); | 1612 | iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); |
| 1613 | 1613 | ||
| 1614 | memset(&info->status, 0, sizeof(info->status)); | 1614 | memset(&info->status, 0, sizeof(info->status)); |
| 1615 | info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED); | ||
| 1615 | 1616 | ||
| 1616 | /* inform mac80211 about what happened with the frame */ | 1617 | /* inform mac80211 about what happened with the frame */ |
| 1617 | switch (status & TX_STATUS_MSK) { | 1618 | switch (status & TX_STATUS_MSK) { |
| @@ -1964,6 +1965,8 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid, · 346 unmodified lines | |||
| 1964 | */ | 1965 | */ |
| 1965 | if (!is_flush) | 1966 | if (!is_flush) |
| 1966 | info->flags |= IEEE80211_TX_STAT_ACK; | 1967 | info->flags |= IEEE80211_TX_STAT_ACK; |
| 1968 | else | ||
| 1969 | info->flags &= ~IEEE80211_TX_STAT_ACK; | ||
| 1967 | } | 1970 | } |
| 1968 | 1971 | ||
| 1969 | /* | 1972 | /* |
| @@ -918,9 +918,17 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, · 917 unmodified lines | |||
| 918 | 918 | ||
| 919 | mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:", | 919 | mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:", |
| 920 | event_buf, len); | 920 | event_buf, len); |
| 921 | while (tlv_buf_left >= sizeof(*tlv_rxba)) { | 921 | while (tlv_buf_left > sizeof(*tlv_rxba)) { |
| 922 | tlv_type = le16_to_cpu(tlv_rxba->header.type); | 922 | tlv_type = le16_to_cpu(tlv_rxba->header.type); |
| 923 | tlv_len = le16_to_cpu(tlv_rxba->header.len); | 923 | tlv_len = le16_to_cpu(tlv_rxba->header.len); |
| 924 | if (size_add(sizeof(tlv_rxba->header), tlv_len) > tlv_buf_left) { | ||
| 925 | mwifiex_dbg(priv->adapter, WARN, | ||
| 926 | "TLV size (%zu) overflows event_buf buf_left=%d\n", | ||
| 927 | size_add(sizeof(tlv_rxba->header), tlv_len), | ||
| 928 | tlv_buf_left); | ||
| 929 | return; | ||
| 930 | } | ||
| 931 | |||
| 924 | if (tlv_type != TLV_TYPE_RXBA_SYNC) { | 932 | if (tlv_type != TLV_TYPE_RXBA_SYNC) { |
| 925 | mwifiex_dbg(priv->adapter, ERROR, | 933 | mwifiex_dbg(priv->adapter, ERROR, |
| 926 | "Wrong TLV id=0x%x\n", tlv_type); | 934 | "Wrong TLV id=0x%x\n", tlv_type); |
| @@ -929,6 +937,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, · 2 unmodified lines | |||
| 929 | 937 | ||
| 930 | tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num); | 938 | tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num); |
| 931 | tlv_bitmap_len = le16_to_cpu(tlv_rxba->bitmap_len); | 939 | tlv_bitmap_len = le16_to_cpu(tlv_rxba->bitmap_len); |
| 940 | if (size_add(sizeof(*tlv_rxba), tlv_bitmap_len) > tlv_buf_left) { | ||
| 941 | mwifiex_dbg(priv->adapter, WARN, | ||
| 942 | "TLV size (%zu) overflows event_buf buf_left=%d\n", | ||
| 943 | size_add(sizeof(*tlv_rxba), tlv_bitmap_len), | ||
| 944 | tlv_buf_left); | ||
| 945 | return; | ||
| 946 | } | ||
| 947 | |||
| 932 | mwifiex_dbg(priv->adapter, INFO, | 948 | mwifiex_dbg(priv->adapter, INFO, |
| 933 | "%pM tid=%d seq_num=%d bitmap_len=%d\n", | 949 | "%pM tid=%d seq_num=%d bitmap_len=%d\n", |
| 934 | tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num, | 950 | tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num, |
| @@ -965,8 +981,8 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, · 30 unmodified lines | |||
| 965 | } | 981 | } |
| 966 | } | 982 | } |
| 967 | 983 | ||
| 968 | tlv_buf_left -= (sizeof(*tlv_rxba) + tlv_len); | 984 | tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len); |
| 969 | tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba); | 985 | tmp = (u8 *)tlv_rxba + sizeof(tlv_rxba->header) + tlv_len; |
| 970 | tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp; | 986 | tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp; |
| 971 | } | 987 | } |
| 972 | } | 988 | } |
| @@ -779,7 +779,7 @@ struct mwifiex_ie_types_rxba_sync { · 778 unmodified lines | |||
| 779 | u8 reserved; | 779 | u8 reserved; |
| 780 | __le16 seq_num; | 780 | __le16 seq_num; |
| 781 | __le16 bitmap_len; | 781 | __le16 bitmap_len; |
| 782 | u8 bitmap[1]; | 782 | u8 bitmap[]; |
| 783 | } __packed; | 783 | } __packed; |
| 784 | 784 | ||
| 785 | struct chan_band_param_set { | 785 | struct chan_band_param_set { |
| @@ -86,7 +86,8 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, · 85 unmodified lines | |||
| 86 | rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); | 86 | rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); |
| 87 | rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; | 87 | rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; |
| 88 | 88 | ||
| 89 | if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) { | 89 | if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) + |
| 90 | rx_pkt_off > skb->len) { | ||
| 90 | mwifiex_dbg(priv->adapter, ERROR, | 91 | mwifiex_dbg(priv->adapter, ERROR, |
| 91 | "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", | 92 | "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", |
| 92 | skb->len, rx_pkt_off); | 93 | skb->len, rx_pkt_off); |
| @@ -95,12 +96,13 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, · 2 unmodified lines | |||
| 95 | return -1; | 96 | return -1; |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, | 99 | if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len && |
| 99 | sizeof(bridge_tunnel_header))) || | 100 | ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, |
| 100 | (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, | 101 | sizeof(bridge_tunnel_header))) || |
| 101 | sizeof(rfc1042_header)) && | 102 | (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, |
| 102 | ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && | 103 | sizeof(rfc1042_header)) && |
| 103 | ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { | 104 | ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && |
| 105 | ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX))) { | ||
| 104 | /* | 106 | /* |
| 105 | * Replace the 803 header and rfc1042 header (llc/snap) with an | 107 | * Replace the 803 header and rfc1042 header (llc/snap) with an |
| 106 | * EthernetII header, keep the src/dst and snap_type | 108 | * EthernetII header, keep the src/dst and snap_type |
| @@ -93,13 +93,13 @@ __mt76_get_rxwi(struct mt76_dev *dev) · 92 unmodified lines | |||
| 93 | { | 93 | { |
| 94 | struct mt76_txwi_cache *t = NULL; | 94 | struct mt76_txwi_cache *t = NULL; |
| 95 | 95 | ||
| 96 | spin_lock(&dev->wed_lock); | 96 | spin_lock_bh(&dev->wed_lock); |
| 97 | if (!list_empty(&dev->rxwi_cache)) { | 97 | if (!list_empty(&dev->rxwi_cache)) { |
| 98 | t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache, | 98 | t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache, |
| 99 | list); | 99 | list); |
| 100 | list_del(&t->list); | 100 | list_del(&t->list); |
| 101 | } | 101 | } |
| 102 | spin_unlock(&dev->wed_lock); | 102 | spin_unlock_bh(&dev->wed_lock); |
| 103 | 103 | ||
| 104 | return t; | 104 | return t; |
| 105 | } | 105 | } |
| @@ -145,9 +145,9 @@ mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t) · 39 unmodified lines | |||
| 145 | if (!t) | 145 | if (!t) |
| 146 | return; | 146 | return; |
| 147 | 147 | ||
| 148 | spin_lock(&dev->wed_lock); | 148 | spin_lock_bh(&dev->wed_lock); |
| 149 | list_add(&t->list, &dev->rxwi_cache); | 149 | list_add(&t->list, &dev->rxwi_cache); |
| 150 | spin_unlock(&dev->wed_lock); | 150 | spin_unlock_bh(&dev->wed_lock); |
| 151 | } | 151 | } |
| 152 | EXPORT_SYMBOL_GPL(mt76_put_rxwi); | 152 | EXPORT_SYMBOL_GPL(mt76_put_rxwi); |
| 153 | 153 | ||
| @@ -131,15 +131,8 @@ u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev, · 130 unmodified lines | |||
| 131 | s8 *lna_2g, s8 *lna_5g, | 131 | s8 *lna_2g, s8 *lna_5g, |
| 132 | struct ieee80211_channel *chan) | 132 | struct ieee80211_channel *chan) |
| 133 | { | 133 | { |
| 134 | u16 val; | ||
| 135 | u8 lna; | 134 | u8 lna; |
| 136 | 135 | ||
| 137 | val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); | ||
| 138 | if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G) | ||
| 139 | *lna_2g = 0; | ||
| 140 | if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G) | ||
| 141 | memset(lna_5g, 0, sizeof(s8) * 3); | ||
| 142 | |||
| 143 | if (chan->band == NL80211_BAND_2GHZ) | 136 | if (chan->band == NL80211_BAND_2GHZ) |
| 144 | lna = *lna_2g; | 137 | lna = *lna_2g; |
| 145 | else if (chan->hw_value <= 64) | 138 | else if (chan->hw_value <= 64) |
| @@ -256,7 +256,8 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) · 255 unmodified lines | |||
| 256 | struct ieee80211_channel *chan = dev->mphy.chandef.chan; | 256 | struct ieee80211_channel *chan = dev->mphy.chandef.chan; |
| 257 | int channel = chan->hw_value; | 257 | int channel = chan->hw_value; |
| 258 | s8 lna_5g[3], lna_2g; | 258 | s8 lna_5g[3], lna_2g; |
| 259 | u8 lna; | 259 | bool use_lna; |
| 260 | u8 lna = 0; | ||
| 260 | u16 val; | 261 | u16 val; |
| 261 | 262 | ||
| 262 | if (chan->band == NL80211_BAND_2GHZ) | 263 | if (chan->band == NL80211_BAND_2GHZ) |
| @@ -275,7 +276,15 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) · 12 unmodified lines | |||
| 275 | dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; | 276 | dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; |
| 276 | dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24; | 277 | dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24; |
| 277 | 278 | ||
| 278 | lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); | 279 | val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); |
| 280 | if (chan->band == NL80211_BAND_2GHZ) | ||
| 281 | use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_2G); | ||
| 282 | else | ||
| 283 | use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_5G); | ||
| 284 | |||
| 285 | if (use_lna) | ||
| 286 | lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); | ||
| 287 | |||
| 279 | dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); | 288 | dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); |
| 280 | } | 289 | } |
| 281 | EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); | 290 | EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); |
| @@ -46,6 +46,7 @@ struct rtw8723du_efuse { · 45 unmodified lines | |||
| 46 | u8 vender_id[2]; /* 0x100 */ | 46 | u8 vender_id[2]; /* 0x100 */ |
| 47 | u8 product_id[2]; /* 0x102 */ | 47 | u8 product_id[2]; /* 0x102 */ |
| 48 | u8 usb_option; /* 0x104 */ | 48 | u8 usb_option; /* 0x104 */ |
| 49 | u8 res5[2]; /* 0x105 */ | ||
| 49 | u8 mac_addr[ETH_ALEN]; /* 0x107 */ | 50 | u8 mac_addr[ETH_ALEN]; /* 0x107 */ |
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| @@ -3998,7 +3998,6 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev) · 3997 unmodified lines | |||
| 3998 | return 0; | 3998 | return 0; |
| 3999 | 3999 | ||
| 4000 | out: | 4000 | out: |
| 4001 | ptp_ocp_dev_release(&bp->dev); | ||
| 4002 | put_device(&bp->dev); | 4001 | put_device(&bp->dev); |
| 4003 | return err; | 4002 | return err; |
| 4004 | } | 4003 | } |
| @@ -123,8 +123,18 @@ static inline ssize_t vringh_iov_xfer(struct vringh *vrh, · 122 unmodified lines | |||
| 123 | done += partlen; | 123 | done += partlen; |
| 124 | len -= partlen; | 124 | len -= partlen; |
| 125 | ptr += partlen; | 125 | ptr += partlen; |
| 126 | iov->consumed += partlen; | ||
| 127 | iov->iov[iov->i].iov_len -= partlen; | ||
| 128 | iov->iov[iov->i].iov_base += partlen; | ||
| 126 | 129 | ||
| 127 | vringh_kiov_advance(iov, partlen); | 130 | if (!iov->iov[iov->i].iov_len) { |
| 131 | /* Fix up old iov element then increment. */ | ||
| 132 | iov->iov[iov->i].iov_len = iov->consumed; | ||
| 133 | iov->iov[iov->i].iov_base -= iov->consumed; | ||
| 134 | |||
| 135 | iov->consumed = 0; | ||
| 136 | iov->i++; | ||
| 137 | } | ||
| 128 | } | 138 | } |
| 129 | return done; | 139 | return done; |
| 130 | } | 140 | } |
| @@ -1307,7 +1307,7 @@ static inline int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, · 1306 unmodified lines | |||
| 1307 | static inline struct bpf_trampoline *bpf_trampoline_get(u64 key, | 1307 | static inline struct bpf_trampoline *bpf_trampoline_get(u64 key, |
| 1308 | struct bpf_attach_target_info *tgt_info) | 1308 | struct bpf_attach_target_info *tgt_info) |
| 1309 | { | 1309 | { |
| 1310 | return ERR_PTR(-EOPNOTSUPP); | 1310 | return NULL; |
| 1311 | } | 1311 | } |
| 1312 | static inline void bpf_trampoline_put(struct bpf_trampoline *tr) {} | 1312 | static inline void bpf_trampoline_put(struct bpf_trampoline *tr) {} |
| 1313 | #define DEFINE_BPF_DISPATCHER(name) | 1313 | #define DEFINE_BPF_DISPATCHER(name) |
| @@ -9,6 +9,7 @@ struct ip_ct_sctp { · 8 unmodified lines | |||
| 9 | enum sctp_conntrack state; | 9 | enum sctp_conntrack state; |
| 10 | 10 | ||
| 11 | __be32 vtag[IP_CT_DIR_MAX]; | 11 | __be32 vtag[IP_CT_DIR_MAX]; |
| 12 | u8 init[IP_CT_DIR_MAX]; | ||
| 12 | u8 last_dir; | 13 | u8 last_dir; |
| 13 | u8 flags; | 14 | u8 flags; |
| 14 | }; | 15 | }; |
| @@ -350,7 +350,7 @@ struct hci_dev { · 349 unmodified lines | |||
| 350 | struct list_head list; | 350 | struct list_head list; |
| 351 | struct mutex lock; | 351 | struct mutex lock; |
| 352 | 352 | ||
| 353 | char name[8]; | 353 | const char *name; |
| 354 | unsigned long flags; | 354 | unsigned long flags; |
| 355 | __u16 id; | 355 | __u16 id; |
| 356 | __u8 bus; | 356 | __u8 bus; |
| @@ -5941,6 +5941,7 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy, · 5940 unmodified lines | |||
| 5941 | * @event_lock: (private) lock for event list | 5941 | * @event_lock: (private) lock for event list |
| 5942 | * @owner_nlportid: (private) owner socket port ID | 5942 | * @owner_nlportid: (private) owner socket port ID |
| 5943 | * @nl_owner_dead: (private) owner socket went away | 5943 | * @nl_owner_dead: (private) owner socket went away |
| 5944 | * @cqm_rssi_work: (private) CQM RSSI reporting work | ||
| 5944 | * @cqm_config: (private) nl80211 RSSI monitor state | 5945 | * @cqm_config: (private) nl80211 RSSI monitor state |
| 5945 | * @pmsr_list: (private) peer measurement requests | 5946 | * @pmsr_list: (private) peer measurement requests |
| 5946 | * @pmsr_lock: (private) peer measurements requests/results lock | 5947 | * @pmsr_lock: (private) peer measurements requests/results lock |
| @@ -6013,7 +6014,8 @@ struct wireless_dev { · 66 unmodified lines | |||
| 6013 | } wext; | 6014 | } wext; |
| 6014 | #endif | 6015 | #endif |
| 6015 | 6016 | ||
| 6016 | struct cfg80211_cqm_config *cqm_config; | 6017 | struct wiphy_work cqm_rssi_work; |
| 6018 | struct cfg80211_cqm_config __rcu *cqm_config; | ||
| 6017 | 6019 | ||
| 6018 | struct list_head pmsr_list; | 6020 | struct list_head pmsr_list; |
| 6019 | spinlock_t pmsr_lock; | 6021 | spinlock_t pmsr_lock; |
| @@ -7231,7 +7233,7 @@ struct cfg80211_rx_assoc_resp { · 1211 unmodified lines | |||
| 7231 | int uapsd_queues; | 7233 | int uapsd_queues; |
| 7232 | const u8 *ap_mld_addr; | 7234 | const u8 *ap_mld_addr; |
| 7233 | struct { | 7235 | struct { |
| 7234 | const u8 *addr; | 7236 | u8 addr[ETH_ALEN] __aligned(2); |
| 7235 | struct cfg80211_bss *bss; | 7237 | struct cfg80211_bss *bss; |
| 7236 | u16 status; | 7238 | u16 status; |
| 7237 | } links[IEEE80211_MLD_MAX_NUM_LINKS]; | 7239 | } links[IEEE80211_MLD_MAX_NUM_LINKS]; |
| @@ -154,6 +154,7 @@ struct fib_info { · 153 unmodified lines | |||
| 154 | int fib_nhs; | 154 | int fib_nhs; |
| 155 | bool fib_nh_is_v6; | 155 | bool fib_nh_is_v6; |
| 156 | bool nh_updated; | 156 | bool nh_updated; |
| 157 | bool pfsrc_removed; | ||
| 157 | struct nexthop *nh; | 158 | struct nexthop *nh; |
| 158 | struct rcu_head rcu; | 159 | struct rcu_head rcu; |
| 159 | struct fib_nh fib_nh[]; | 160 | struct fib_nh fib_nh[]; |
| @@ -103,9 +103,10 @@ struct mana_txq { · 102 unmodified lines | |||
| 103 | 103 | ||
| 104 | /* skb data and frags dma mappings */ | 104 | /* skb data and frags dma mappings */ |
| 105 | struct mana_skb_head { | 105 | struct mana_skb_head { |
| 106 | dma_addr_t dma_handle[MAX_SKB_FRAGS + 1]; | 106 | /* GSO pkts may have 2 SGEs for the linear part*/ |
| 107 | dma_addr_t dma_handle[MAX_SKB_FRAGS + 2]; | ||
| 107 | 108 | ||
| 108 | u32 size[MAX_SKB_FRAGS + 1]; | 109 | u32 size[MAX_SKB_FRAGS + 2]; |
| 109 | }; | 110 | }; |
| 110 | 111 | ||
| 111 | #define MANA_HEADROOM sizeof(struct mana_skb_head) | 112 | #define MANA_HEADROOM sizeof(struct mana_skb_head) |
| @@ -539,7 +539,7 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb, · 538 unmodified lines | |||
| 539 | READ_ONCE(hh->hh_len)) | 539 | READ_ONCE(hh->hh_len)) |
| 540 | return neigh_hh_output(hh, skb); | 540 | return neigh_hh_output(hh, skb); |
| 541 | 541 | ||
| 542 | return n->output(n, skb); | 542 | return READ_ONCE(n->output)(n, skb); |
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | static inline struct neighbour * | 545 | static inline struct neighbour * |
| @@ -16,13 +16,13 @@ · 15 unmodified lines | |||
| 16 | * page_pool_alloc_pages() call. Drivers should use | 16 | * page_pool_alloc_pages() call. Drivers should use |
| 17 | * page_pool_dev_alloc_pages() replacing dev_alloc_pages(). | 17 | * page_pool_dev_alloc_pages() replacing dev_alloc_pages(). |
| 18 | * | 18 | * |
| 19 | * API keeps track of in-flight pages, in order to let API user know | 19 | * The API keeps track of in-flight pages, in order to let API users know |
| 20 | * when it is safe to free a page_pool object. Thus, API users | 20 | * when it is safe to free a page_pool object. Thus, API users |
| 21 | * must call page_pool_put_page() to free the page, or attach | 21 | * must call page_pool_put_page() to free the page, or attach |
| 22 | * the page to a page_pool-aware objects like skbs marked with | 22 | * the page to a page_pool-aware object like skbs marked with |
| 23 | * skb_mark_for_recycle(). | 23 | * skb_mark_for_recycle(). |
| 24 | * | 24 | * |
| 25 | * API user must call page_pool_put_page() once on a page, as it | 25 | * API users must call page_pool_put_page() once on a page, as it |
| 26 | * will either recycle the page, or in case of refcnt > 1, it will | 26 | * will either recycle the page, or in case of refcnt > 1, it will |
| 27 | * release the DMA mapping and in-flight state accounting. | 27 | * release the DMA mapping and in-flight state accounting. |
| 28 | */ | 28 | */ |
| @@ -348,12 +348,14 @@ ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos, · 347 unmodified lines | |||
| 348 | struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, gfp_t gfp, | 348 | struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, gfp_t gfp, |
| 349 | bool force_schedule); | 349 | bool force_schedule); |
| 350 | 350 | ||
| 351 | static inline void tcp_dec_quickack_mode(struct sock *sk, | 351 | static inline void tcp_dec_quickack_mode(struct sock *sk) |
| 352 | const unsigned int pkts) | ||
| 353 | { | 352 | { |
| 354 | struct inet_connection_sock *icsk = inet_csk(sk); | 353 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 355 | 354 | ||
| 356 | if (icsk->icsk_ack.quick) { | 355 | if (icsk->icsk_ack.quick) { |
| 356 | /* How many ACKs S/ACKing new data have we sent? */ | ||
| 357 | const unsigned int pkts = inet_csk_ack_scheduled(sk) ? 1 : 0; | ||
| 358 | |||
| 357 | if (pkts >= icsk->icsk_ack.quick) { | 359 | if (pkts >= icsk->icsk_ack.quick) { |
| 358 | icsk->icsk_ack.quick = 0; | 360 | icsk->icsk_ack.quick = 0; |
| 359 | /* Leaving quickack mode we deflate ATO. */ | 361 | /* Leaving quickack mode we deflate ATO. */ |
| @@ -965,37 +965,31 @@ void notrace *bpf_mem_cache_alloc_flags(struct bpf_mem_alloc *ma, gfp_t flags) · 964 unmodified lines | |||
| 965 | return !ret ? NULL : ret + LLIST_NODE_SZ; | 965 | return !ret ? NULL : ret + LLIST_NODE_SZ; |
| 966 | } | 966 | } |
| 967 | 967 | ||
| 968 | /* Most of the logic is taken from setup_kmalloc_cache_index_table() */ | ||
| 969 | static __init int bpf_mem_cache_adjust_size(void) | 968 | static __init int bpf_mem_cache_adjust_size(void) |
| 970 | { | 969 | { |
| 971 | unsigned int size, index; | 970 | unsigned int size; |
| 972 | 971 | ||
| 973 | /* Normally KMALLOC_MIN_SIZE is 8-bytes, but it can be | 972 | /* Adjusting the indexes in size_index() according to the object_size |
| 974 | * up-to 256-bytes. | 973 | * of underlying slab cache, so bpf_mem_alloc() will select a |
| 974 | * bpf_mem_cache with unit_size equal to the object_size of | ||
| 975 | * the underlying slab cache. | ||
| 976 | * | ||
| 977 | * The maximal value of KMALLOC_MIN_SIZE and __kmalloc_minalign() is | ||
| 978 | * 256-bytes, so only do adjustment for [8-bytes, 192-bytes]. | ||
| 975 | */ | 979 | */ |
| 976 | size = KMALLOC_MIN_SIZE; | 980 | for (size = 192; size >= 8; size -= 8) { |
| 977 | if (size <= 192) | 981 | unsigned int kmalloc_size, index; |
| 978 | index = size_index[(size - 1) / 8]; | ||
| 979 | else | ||
| 980 | index = fls(size - 1) - 1; | ||
| 981 | for (size = 8; size < KMALLOC_MIN_SIZE && size <= 192; size += 8) | ||
| 982 | size_index[(size - 1) / 8] = index; | ||
| 983 | 982 | ||
| 984 | /* The minimal alignment is 64-bytes, so disable 96-bytes cache and | 983 | kmalloc_size = kmalloc_size_roundup(size); |
| 985 | * use 128-bytes cache instead. | 984 | if (kmalloc_size == size) |
| 986 | */ | 985 | continue; |
| 987 | if (KMALLOC_MIN_SIZE >= 64) { | ||
| 988 | index = size_index[(128 - 1) / 8]; | ||
| 989 | for (size = 64 + 8; size <= 96; size += 8) | ||
| 990 | size_index[(size - 1) / 8] = index; | ||
| 991 | } | ||
| 992 | 986 | ||
| 993 | /* The minimal alignment is 128-bytes, so disable 192-bytes cache and | 987 | if (kmalloc_size <= 192) |
| 994 | * use 256-bytes cache instead. | 988 | index = size_index[(kmalloc_size - 1) / 8]; |
| 995 | */ | 989 | else |
| 996 | if (KMALLOC_MIN_SIZE >= 128) { | 990 | index = fls(kmalloc_size - 1) - 1; |
| 997 | index = fls(256 - 1) - 1; | 991 | /* Only overwrite if necessary */ |
| 998 | for (size = 128 + 8; size <= 192; size += 8) | 992 | if (size_index[(size - 1) / 8] != index) |
| 999 | size_index[(size - 1) / 8] = index; | 993 | size_index[(size - 1) / 8] = index; |
| 1000 | } | 994 | } |
| 1001 | 995 | ||
| @@ -253,6 +253,9 @@ int bpf_mprog_attach(struct bpf_mprog_entry *entry, · 252 unmodified lines | |||
| 253 | goto out; | 253 | goto out; |
| 254 | } | 254 | } |
| 255 | idx = tidx; | 255 | idx = tidx; |
| 256 | } else if (bpf_mprog_total(entry) == bpf_mprog_max()) { | ||
| 257 | ret = -ERANGE; | ||
| 258 | goto out; | ||
| 256 | } | 259 | } |
| 257 | if (flags & BPF_F_BEFORE) { | 260 | if (flags & BPF_F_BEFORE) { |
| 258 | tidx = bpf_mprog_pos_before(entry, &rtuple); | 261 | tidx = bpf_mprog_pos_before(entry, &rtuple); |
| @@ -4047,11 +4047,9 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno) · 4046 unmodified lines | |||
| 4047 | bitmap_from_u64(mask, bt_reg_mask(bt)); | 4047 | bitmap_from_u64(mask, bt_reg_mask(bt)); |
| 4048 | for_each_set_bit(i, mask, 32) { | 4048 | for_each_set_bit(i, mask, 32) { |
| 4049 | reg = &st->frame[0]->regs[i]; | 4049 | reg = &st->frame[0]->regs[i]; |
| 4050 | if (reg->type != SCALAR_VALUE) { | 4050 | bt_clear_reg(bt, i); |
| 4051 | bt_clear_reg(bt, i); | 4051 | if (reg->type == SCALAR_VALUE) |
| 4052 | continue; | 4052 | reg->precise = true; |
| 4053 | } | ||
| 4054 | reg->precise = true; | ||
| 4055 | } | 4053 | } |
| 4056 | return 0; | 4054 | return 0; |
| 4057 | } | 4055 | } |
| @@ -2413,34 +2413,41 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type, · 2412 unmodified lines | |||
| 2413 | if (!test_bit(HCI_CONN_AUTH, &conn->flags)) | 2413 | if (!test_bit(HCI_CONN_AUTH, &conn->flags)) |
| 2414 | goto auth; | 2414 | goto auth; |
| 2415 | 2415 | ||
| 2416 | /* An authenticated FIPS approved combination key has sufficient | 2416 | switch (conn->key_type) { |
| 2417 | * security for security level 4. */ | 2417 | case HCI_LK_AUTH_COMBINATION_P256: |
| 2418 | if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256 && | 2418 | /* An authenticated FIPS approved combination key has |
| 2419 | sec_level == BT_SECURITY_FIPS) | 2419 | * sufficient security for security level 4 or lower. |
| 2420 | goto encrypt; | 2420 | */ |
| 2421 | 2421 | if (sec_level <= BT_SECURITY_FIPS) | |
| 2422 | /* An authenticated combination key has sufficient security for | 2422 | goto encrypt; |
| 2423 | security level 3. */ | 2423 | break; |
| 2424 | if ((conn->key_type == HCI_LK_AUTH_COMBINATION_P192 || | 2424 | case HCI_LK_AUTH_COMBINATION_P192: |
| 2425 | conn->key_type == HCI_LK_AUTH_COMBINATION_P256) && | 2425 | /* An authenticated combination key has sufficient security for |
| 2426 | sec_level == BT_SECURITY_HIGH) | 2426 | * security level 3 or lower. |
| 2427 | goto encrypt; | 2427 | */ |
| 2428 | 2428 | if (sec_level <= BT_SECURITY_HIGH) | |
| 2429 | /* An unauthenticated combination key has sufficient security for | 2429 | goto encrypt; |
| 2430 | security level 1 and 2. */ | 2430 | break; |
| 2431 | if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 || | 2431 | case HCI_LK_UNAUTH_COMBINATION_P192: |
| 2432 | conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) && | 2432 | case HCI_LK_UNAUTH_COMBINATION_P256: |
| 2433 | (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) | 2433 | /* An unauthenticated combination key has sufficient security |
| 2434 | goto encrypt; | 2434 | * for security level 2 or lower. |
| 2435 | 2435 | */ | |
| 2436 | /* A combination key has always sufficient security for the security | 2436 | if (sec_level <= BT_SECURITY_MEDIUM) |
| 2437 | levels 1 or 2. High security level requires the combination key | 2437 | goto encrypt; |
| 2438 | is generated using maximum PIN code length (16). | 2438 | break; |
| 2439 | For pre 2.1 units. */ | 2439 | case HCI_LK_COMBINATION: |
| 2440 | if (conn->key_type == HCI_LK_COMBINATION && | 2440 | /* A combination key has always sufficient security for the |
| 2441 | (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW || | 2441 | * security levels 2 or lower. High security level requires the |
| 2442 | conn->pin_length == 16)) | 2442 | * combination key is generated using maximum PIN code length |
| 2443 | goto encrypt; | 2443 | * (16). For pre 2.1 units. |
| 2444 | */ | ||
| 2445 | if (sec_level <= BT_SECURITY_MEDIUM || conn->pin_length == 16) | ||
| 2446 | goto encrypt; | ||
| 2447 | break; | ||
| 2448 | default: | ||
| 2449 | break; | ||
| 2450 | } | ||
| 2444 | 2451 | ||
| 2445 | auth: | 2452 | auth: |
| 2446 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) | 2453 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) |
| @@ -2617,7 +2617,11 @@ int hci_register_dev(struct hci_dev *hdev) · 2616 unmodified lines | |||
| 2617 | if (id < 0) | 2617 | if (id < 0) |
| 2618 | return id; | 2618 | return id; |
| 2619 | 2619 | ||
| 2620 | snprintf(hdev->name, sizeof(hdev->name), "hci%d", id); | 2620 | error = dev_set_name(&hdev->dev, "hci%u", id); |
| 2621 | if (error) | ||
| 2622 | return error; | ||
| 2623 | |||
| 2624 | hdev->name = dev_name(&hdev->dev); | ||
| 2621 | hdev->id = id; | 2625 | hdev->id = id; |
| 2622 | 2626 | ||
| 2623 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); | 2627 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); |
| @@ -2639,8 +2643,6 @@ int hci_register_dev(struct hci_dev *hdev) · 15 unmodified lines | |||
| 2639 | if (!IS_ERR_OR_NULL(bt_debugfs)) | 2643 | if (!IS_ERR_OR_NULL(bt_debugfs)) |
| 2640 | hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); | 2644 | hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); |
| 2641 | 2645 | ||
| 2642 | dev_set_name(&hdev->dev, "%s", hdev->name); | ||
| 2643 | |||
| 2644 | error = device_add(&hdev->dev); | 2646 | error = device_add(&hdev->dev); |
| 2645 | if (error < 0) | 2647 | if (error < 0) |
| 2646 | goto err_wqueue; | 2648 | goto err_wqueue; |
| @@ -2784,6 +2786,7 @@ void hci_release_dev(struct hci_dev *hdev) · 137 unmodified lines | |||
| 2784 | hci_conn_params_clear_all(hdev); | 2786 | hci_conn_params_clear_all(hdev); |
| 2785 | hci_discovery_filter_clear(hdev); | 2787 | hci_discovery_filter_clear(hdev); |
| 2786 | hci_blocked_keys_clear(hdev); | 2788 | hci_blocked_keys_clear(hdev); |
| 2789 | hci_codec_list_clear(&hdev->local_codecs); | ||
| 2787 | hci_dev_unlock(hdev); | 2790 | hci_dev_unlock(hdev); |
| 2788 | 2791 | ||
| 2789 | ida_simple_remove(&hci_index_ida, hdev->id); | 2792 | ida_simple_remove(&hci_index_ida, hdev->id); |
| @@ -3418,7 +3421,12 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) · 628 unmodified lines | |||
| 3418 | if (c->type == type && c->sent) { | 3421 | if (c->type == type && c->sent) { |
| 3419 | bt_dev_err(hdev, "killing stalled connection %pMR", | 3422 | bt_dev_err(hdev, "killing stalled connection %pMR", |
| 3420 | &c->dst); | 3423 | &c->dst); |
| 3424 | /* hci_disconnect might sleep, so, we have to release | ||
| 3425 | * the RCU read lock before calling it. | ||
| 3426 | */ | ||
| 3427 | rcu_read_unlock(); | ||
| 3421 | hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); | 3428 | hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); |
| 3429 | rcu_read_lock(); | ||
| 3422 | } | 3430 | } |
| 3423 | } | 3431 | } |
| 3424 | 3432 | ||
| @@ -33,6 +33,7 @@ · 32 unmodified lines | |||
| 33 | 33 | ||
| 34 | #include "hci_request.h" | 34 | #include "hci_request.h" |
| 35 | #include "hci_debugfs.h" | 35 | #include "hci_debugfs.h" |
| 36 | #include "hci_codec.h" | ||
| 36 | #include "a2mp.h" | 37 | #include "a2mp.h" |
| 37 | #include "amp.h" | 38 | #include "amp.h" |
| 38 | #include "smp.h" | 39 | #include "smp.h" |
| @@ -71,7 +71,5 @@ struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, · 70 unmodified lines | |||
| 71 | void hci_req_add_le_scan_disable(struct hci_request *req, bool rpa_le_conn); | 71 | void hci_req_add_le_scan_disable(struct hci_request *req, bool rpa_le_conn); |
| 72 | void hci_req_add_le_passive_scan(struct hci_request *req); | 72 | void hci_req_add_le_passive_scan(struct hci_request *req); |
| 73 | 73 | ||
| 74 | void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next); | ||
| 75 | |||
| 76 | void hci_request_setup(struct hci_dev *hdev); | 74 | void hci_request_setup(struct hci_dev *hdev); |
| 77 | void hci_request_cancel_all(struct hci_dev *hdev); | 75 | void hci_request_cancel_all(struct hci_dev *hdev); |
| @@ -413,11 +413,6 @@ static int hci_le_scan_restart_sync(struct hci_dev *hdev) · 412 unmodified lines | |||
| 413 | LE_SCAN_FILTER_DUP_ENABLE); | 413 | LE_SCAN_FILTER_DUP_ENABLE); |
| 414 | } | 414 | } |
| 415 | 415 | ||
| 416 | static int le_scan_restart_sync(struct hci_dev *hdev, void *data) | ||
| 417 | { | ||
| 418 | return hci_le_scan_restart_sync(hdev); | ||
| 419 | } | ||
| 420 | |||
| 421 | static void le_scan_restart(struct work_struct *work) | 416 | static void le_scan_restart(struct work_struct *work) |
| 422 | { | 417 | { |
| 423 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 418 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
| @@ -427,15 +422,15 @@ static void le_scan_restart(struct work_struct *work) · 3 unmodified lines | |||
| 427 | 422 | ||
| 428 | bt_dev_dbg(hdev, ""); | 423 | bt_dev_dbg(hdev, ""); |
| 429 | 424 | ||
| 430 | hci_dev_lock(hdev); | 425 | status = hci_le_scan_restart_sync(hdev); |
| 431 | |||
| 432 | status = hci_cmd_sync_queue(hdev, le_scan_restart_sync, NULL, NULL); | ||
| 433 | if (status) { | 426 | if (status) { |
| 434 | bt_dev_err(hdev, "failed to restart LE scan: status %d", | 427 | bt_dev_err(hdev, "failed to restart LE scan: status %d", |
| 435 | status); | 428 | status); |
| 436 | goto unlock; | 429 | return; |
| 437 | } | 430 | } |
| 438 | 431 | ||
| 432 | hci_dev_lock(hdev); | ||
| 433 | |||
| 439 | if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) || | 434 | if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) || |
| 440 | !hdev->discovery.scan_start) | 435 | !hdev->discovery.scan_start) |
| 441 | goto unlock; | 436 | goto unlock; |
| @@ -5079,6 +5074,7 @@ int hci_dev_close_sync(struct hci_dev *hdev) · 4637 unmodified lines | |||
| 5079 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 5074 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
| 5080 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); | 5075 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); |
| 5081 | bacpy(&hdev->random_addr, BDADDR_ANY); | 5076 | bacpy(&hdev->random_addr, BDADDR_ANY); |
| 5077 | hci_codec_list_clear(&hdev->local_codecs); | ||
| 5082 | 5078 | ||
| 5083 | hci_dev_put(hdev); | 5079 | hci_dev_put(hdev); |
| 5084 | return err; | 5080 | return err; |
| @@ -502,7 +502,7 @@ drop: · 501 unmodified lines | |||
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | /* -------- Socket interface ---------- */ | 504 | /* -------- Socket interface ---------- */ |
| 505 | static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba) | 505 | static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *src, bdaddr_t *dst) |
| 506 | { | 506 | { |
| 507 | struct sock *sk; | 507 | struct sock *sk; |
| 508 | 508 | ||
| @@ -510,7 +510,10 @@ static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba) · 1 unmodified line | |||
| 510 | if (sk->sk_state != BT_LISTEN) | 510 | if (sk->sk_state != BT_LISTEN) |
| 511 | continue; | 511 | continue; |
| 512 | 512 | ||
| 513 | if (!bacmp(&iso_pi(sk)->src, ba)) | 513 | if (bacmp(&iso_pi(sk)->dst, dst)) |
| 514 | continue; | ||
| 515 | |||
| 516 | if (!bacmp(&iso_pi(sk)->src, src)) | ||
| 514 | return sk; | 517 | return sk; |
| 515 | } | 518 | } |
| 516 | 519 | ||
| @@ -952,7 +955,7 @@ static int iso_listen_cis(struct sock *sk) · 435 unmodified lines | |||
| 952 | 955 | ||
| 953 | write_lock(&iso_sk_list.lock); | 956 | write_lock(&iso_sk_list.lock); |
| 954 | 957 | ||
| 955 | if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src)) | 958 | if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src, &iso_pi(sk)->dst)) |
| 956 | err = -EADDRINUSE; | 959 | err = -EADDRINUSE; |
| 957 | 960 | ||
| 958 | write_unlock(&iso_sk_list.lock); | 961 | write_unlock(&iso_sk_list.lock); |
| @@ -294,7 +294,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_ · 293 unmodified lines | |||
| 294 | /* tell br_dev_xmit to continue with forwarding */ | 294 | /* tell br_dev_xmit to continue with forwarding */ |
| 295 | nf_bridge->bridged_dnat = 1; | 295 | nf_bridge->bridged_dnat = 1; |
| 296 | /* FIXME Need to refragment */ | 296 | /* FIXME Need to refragment */ |
| 297 | ret = neigh->output(neigh, skb); | 297 | ret = READ_ONCE(neigh->output)(neigh, skb); |
| 298 | } | 298 | } |
| 299 | neigh_release(neigh); | 299 | neigh_release(neigh); |
| 300 | return ret; | 300 | return ret; |
| @@ -410,7 +410,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev, · 409 unmodified lines | |||
| 410 | */ | 410 | */ |
| 411 | __skb_queue_purge(&n->arp_queue); | 411 | __skb_queue_purge(&n->arp_queue); |
| 412 | n->arp_queue_len_bytes = 0; | 412 | n->arp_queue_len_bytes = 0; |
| 413 | n->output = neigh_blackhole; | 413 | WRITE_ONCE(n->output, neigh_blackhole); |
| 414 | if (n->nud_state & NUD_VALID) | 414 | if (n->nud_state & NUD_VALID) |
| 415 | n->nud_state = NUD_NOARP; | 415 | n->nud_state = NUD_NOARP; |
| 416 | else | 416 | else |
| @@ -920,7 +920,7 @@ static void neigh_suspect(struct neighbour *neigh) · 503 unmodified lines | |||
| 920 | { | 920 | { |
| 921 | neigh_dbg(2, "neigh %p is suspected\n", neigh); | 921 | neigh_dbg(2, "neigh %p is suspected\n", neigh); |
| 922 | 922 | ||
| 923 | neigh->output = neigh->ops->output; | 923 | WRITE_ONCE(neigh->output, neigh->ops->output); |
| 924 | } | 924 | } |
| 925 | 925 | ||
| 926 | /* Neighbour state is OK; | 926 | /* Neighbour state is OK; |
| @@ -932,7 +932,7 @@ static void neigh_connect(struct neighbour *neigh) · 5 unmodified lines | |||
| 932 | { | 932 | { |
| 933 | neigh_dbg(2, "neigh %p is connected\n", neigh); | 933 | neigh_dbg(2, "neigh %p is connected\n", neigh); |
| 934 | 934 | ||
| 935 | neigh->output = neigh->ops->connected_output; | 935 | WRITE_ONCE(neigh->output, neigh->ops->connected_output); |
| 936 | } | 936 | } |
| 937 | 937 | ||
| 938 | static void neigh_periodic_work(struct work_struct *work) | 938 | static void neigh_periodic_work(struct work_struct *work) |
| @@ -988,7 +988,9 @@ static void neigh_periodic_work(struct work_struct *work) · 49 unmodified lines | |||
| 988 | (state == NUD_FAILED || | 988 | (state == NUD_FAILED || |
| 989 | !time_in_range_open(jiffies, n->used, | 989 | !time_in_range_open(jiffies, n->used, |
| 990 | n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) { | 990 | n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) { |
| 991 | *np = n->next; | 991 | rcu_assign_pointer(*np, |
| 992 | rcu_dereference_protected(n->next, | ||
| 993 | lockdep_is_held(&tbl->lock))); | ||
| 992 | neigh_mark_dead(n); | 994 | neigh_mark_dead(n); |
| 993 | write_unlock(&n->lock); | 995 | write_unlock(&n->lock); |
| 994 | neigh_cleanup_and_release(n); | 996 | neigh_cleanup_and_release(n); |
| @@ -1447,7 +1449,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, · 452 unmodified lines | |||
| 1447 | if (n2) | 1449 | if (n2) |
| 1448 | n1 = n2; | 1450 | n1 = n2; |
| 1449 | } | 1451 | } |
| 1450 | n1->output(n1, skb); | 1452 | READ_ONCE(n1->output)(n1, skb); |
| 1451 | if (n2) | 1453 | if (n2) |
| 1452 | neigh_release(n2); | 1454 | neigh_release(n2); |
| 1453 | rcu_read_unlock(); | 1455 | rcu_read_unlock(); |
| @@ -3153,7 +3155,7 @@ int neigh_xmit(int index, struct net_device *dev, · 1699 unmodified lines | |||
| 3153 | rcu_read_unlock(); | 3155 | rcu_read_unlock(); |
| 3154 | goto out_kfree_skb; | 3156 | goto out_kfree_skb; |
| 3155 | } | 3157 | } |
| 3156 | err = neigh->output(neigh, skb); | 3158 | err = READ_ONCE(neigh->output)(neigh, skb); |
| 3157 | rcu_read_unlock(); | 3159 | rcu_read_unlock(); |
| 3158 | } | 3160 | } |
| 3159 | else if (index == NEIGH_LINK_TABLE) { | 3161 | else if (index == NEIGH_LINK_TABLE) { |
| @@ -668,6 +668,8 @@ BPF_CALL_4(bpf_msg_redirect_map, struct sk_msg *, msg, · 667 unmodified lines | |||
| 668 | sk = __sock_map_lookup_elem(map, key); | 668 | sk = __sock_map_lookup_elem(map, key); |
| 669 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) | 669 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) |
| 670 | return SK_DROP; | 670 | return SK_DROP; |
| 671 | if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) | ||
| 672 | return SK_DROP; | ||
| 671 | 673 | ||
| 672 | msg->flags = flags; | 674 | msg->flags = flags; |
| 673 | msg->sk_redir = sk; | 675 | msg->sk_redir = sk; |
| @@ -1267,6 +1269,8 @@ BPF_CALL_4(bpf_msg_redirect_hash, struct sk_msg *, msg, · 593 unmodified lines | |||
| 1267 | sk = __sock_hash_lookup_elem(map, key); | 1269 | sk = __sock_hash_lookup_elem(map, key); |
| 1268 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) | 1270 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) |
| 1269 | return SK_DROP; | 1271 | return SK_DROP; |
| 1272 | if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) | ||
| 1273 | return SK_DROP; | ||
| 1270 | 1274 | ||
| 1271 | msg->flags = flags; | 1275 | msg->flags = flags; |
| 1272 | msg->sk_redir = sk; | 1276 | msg->sk_redir = sk; |
| @@ -21,16 +21,6 @@ struct plca_reply_data { · 20 unmodified lines | |||
| 21 | #define PLCA_REPDATA(__reply_base) \ | 21 | #define PLCA_REPDATA(__reply_base) \ |
| 22 | container_of(__reply_base, struct plca_reply_data, base) | 22 | container_of(__reply_base, struct plca_reply_data, base) |
| 23 | 23 | ||
| 24 | static void plca_update_sint(int *dst, const struct nlattr *attr, | ||
| 25 | bool *mod) | ||
| 26 | { | ||
| 27 | if (!attr) | ||
| 28 | return; | ||
| 29 | |||
| 30 | *dst = nla_get_u32(attr); | ||
| 31 | *mod = true; | ||
| 32 | } | ||
| 33 | |||
| 34 | // PLCA get configuration message ------------------------------------------- // | 24 | // PLCA get configuration message ------------------------------------------- // |
| 35 | 25 | ||
| 36 | const struct nla_policy ethnl_plca_get_cfg_policy[] = { | 26 | const struct nla_policy ethnl_plca_get_cfg_policy[] = { |
| @@ -38,6 +28,29 @@ const struct nla_policy ethnl_plca_get_cfg_policy[] = { · 1 unmodified line | |||
| 38 | NLA_POLICY_NESTED(ethnl_header_policy), | 28 | NLA_POLICY_NESTED(ethnl_header_policy), |
| 39 | }; | 29 | }; |
| 40 | 30 | ||
| 31 | static void plca_update_sint(int *dst, struct nlattr **tb, u32 attrid, | ||
| 32 | bool *mod) | ||
| 33 | { | ||
| 34 | const struct nlattr *attr = tb[attrid]; | ||
| 35 | |||
| 36 | if (!attr || | ||
| 37 | WARN_ON_ONCE(attrid >= ARRAY_SIZE(ethnl_plca_set_cfg_policy))) | ||
| 38 | return; | ||
| 39 | |||
| 40 | switch (ethnl_plca_set_cfg_policy[attrid].type) { | ||
| 41 | case NLA_U8: | ||
| 42 | *dst = nla_get_u8(attr); | ||
| 43 | break; | ||
| 44 | case NLA_U32: | ||
| 45 | *dst = nla_get_u32(attr); | ||
| 46 | break; | ||
| 47 | default: | ||
| 48 | WARN_ON_ONCE(1); | ||
| 49 | } | ||
| 50 | |||
| 51 | *mod = true; | ||
| 52 | } | ||
| 53 | |||
| 41 | static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, | 54 | static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, |
| 42 | struct ethnl_reply_data *reply_base, | 55 | struct ethnl_reply_data *reply_base, |
| 43 | const struct genl_info *info) | 56 | const struct genl_info *info) |
| @@ -144,13 +157,13 @@ ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info) · 100 unmodified lines | |||
| 144 | return -EOPNOTSUPP; | 157 | return -EOPNOTSUPP; |
| 145 | 158 | ||
| 146 | memset(&plca_cfg, 0xff, sizeof(plca_cfg)); | 159 | memset(&plca_cfg, 0xff, sizeof(plca_cfg)); |
| 147 | plca_update_sint(&plca_cfg.enabled, tb[ETHTOOL_A_PLCA_ENABLED], &mod); | 160 | plca_update_sint(&plca_cfg.enabled, tb, ETHTOOL_A_PLCA_ENABLED, &mod); |
| 148 | plca_update_sint(&plca_cfg.node_id, tb[ETHTOOL_A_PLCA_NODE_ID], &mod); | 161 | plca_update_sint(&plca_cfg.node_id, tb, ETHTOOL_A_PLCA_NODE_ID, &mod); |
| 149 | plca_update_sint(&plca_cfg.node_cnt, tb[ETHTOOL_A_PLCA_NODE_CNT], &mod); | 162 | plca_update_sint(&plca_cfg.node_cnt, tb, ETHTOOL_A_PLCA_NODE_CNT, &mod); |
| 150 | plca_update_sint(&plca_cfg.to_tmr, tb[ETHTOOL_A_PLCA_TO_TMR], &mod); | 163 | plca_update_sint(&plca_cfg.to_tmr, tb, ETHTOOL_A_PLCA_TO_TMR, &mod); |
| 151 | plca_update_sint(&plca_cfg.burst_cnt, tb[ETHTOOL_A_PLCA_BURST_CNT], | 164 | plca_update_sint(&plca_cfg.burst_cnt, tb, ETHTOOL_A_PLCA_BURST_CNT, |
| 152 | &mod); | 165 | &mod); |
| 153 | plca_update_sint(&plca_cfg.burst_tmr, tb[ETHTOOL_A_PLCA_BURST_TMR], | 166 | plca_update_sint(&plca_cfg.burst_tmr, tb, ETHTOOL_A_PLCA_BURST_TMR, |
| 154 | &mod); | 167 | &mod); |
| 155 | if (!mod) | 168 | if (!mod) |
| 156 | return 0; | 169 | return 0; |
| @@ -1887,6 +1887,7 @@ int fib_sync_down_addr(struct net_device *dev, __be32 local) · 1886 unmodified lines | |||
| 1887 | continue; | 1887 | continue; |
| 1888 | if (fi->fib_prefsrc == local) { | 1888 | if (fi->fib_prefsrc == local) { |
| 1889 | fi->fib_flags |= RTNH_F_DEAD; | 1889 | fi->fib_flags |= RTNH_F_DEAD; |
| 1890 | fi->pfsrc_removed = true; | ||
| 1890 | ret++; | 1891 | ret++; |
| 1891 | } | 1892 | } |
| 1892 | } | 1893 | } |
| @@ -2027,6 +2027,7 @@ void fib_table_flush_external(struct fib_table *tb) · 2026 unmodified lines | |||
| 2027 | int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) | 2027 | int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) |
| 2028 | { | 2028 | { |
| 2029 | struct trie *t = (struct trie *)tb->tb_data; | 2029 | struct trie *t = (struct trie *)tb->tb_data; |
| 2030 | struct nl_info info = { .nl_net = net }; | ||
| 2030 | struct key_vector *pn = t->kv; | 2031 | struct key_vector *pn = t->kv; |
| 2031 | unsigned long cindex = 1; | 2032 | unsigned long cindex = 1; |
| 2032 | struct hlist_node *tmp; | 2033 | struct hlist_node *tmp; |
| @@ -2089,6 +2090,9 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) · 56 unmodified lines | |||
| 2089 | 2090 | ||
| 2090 | fib_notify_alias_delete(net, n->key, &n->leaf, fa, | 2091 | fib_notify_alias_delete(net, n->key, &n->leaf, fa, |
| 2091 | NULL); | 2092 | NULL); |
| 2093 | if (fi->pfsrc_removed) | ||
| 2094 | rtmsg_fib(RTM_DELROUTE, htonl(n->key), fa, | ||
| 2095 | KEYLENGTH - fa->fa_slen, tb->tb_id, &info, 0); | ||
| 2092 | hlist_del_rcu(&fa->fa_list); | 2096 | hlist_del_rcu(&fa->fa_list); |
| 2093 | fib_release_info(fa->fa_info); | 2097 | fib_release_info(fa->fa_info); |
| 2094 | alias_free_mem_rcu(fa); | 2098 | alias_free_mem_rcu(fa); |
| @@ -3417,6 +3417,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, · 3416 unmodified lines | |||
| 3417 | fa->fa_type == fri.type) { | 3417 | fa->fa_type == fri.type) { |
| 3418 | fri.offload = READ_ONCE(fa->offload); | 3418 | fri.offload = READ_ONCE(fa->offload); |
| 3419 | fri.trap = READ_ONCE(fa->trap); | 3419 | fri.trap = READ_ONCE(fa->trap); |
| 3420 | fri.offload_failed = | ||
| 3421 | READ_ONCE(fa->offload_failed); | ||
| 3420 | break; | 3422 | break; |
| 3421 | } | 3423 | } |
| 3422 | } | 3424 | } |
| @@ -1621,16 +1621,13 @@ EXPORT_SYMBOL(tcp_read_sock); · 1620 unmodified lines | |||
| 1621 | 1621 | ||
| 1622 | int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) | 1622 | int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) |
| 1623 | { | 1623 | { |
| 1624 | struct tcp_sock *tp = tcp_sk(sk); | ||
| 1625 | u32 seq = tp->copied_seq; | ||
| 1626 | struct sk_buff *skb; | 1624 | struct sk_buff *skb; |
| 1627 | int copied = 0; | 1625 | int copied = 0; |
| 1628 | u32 offset; | ||
| 1629 | 1626 | ||
| 1630 | if (sk->sk_state == TCP_LISTEN) | 1627 | if (sk->sk_state == TCP_LISTEN) |
| 1631 | return -ENOTCONN; | 1628 | return -ENOTCONN; |
| 1632 | 1629 | ||
| 1633 | while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { | 1630 | while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { |
| 1634 | u8 tcp_flags; | 1631 | u8 tcp_flags; |
| 1635 | int used; | 1632 | int used; |
| 1636 | 1633 | ||
| @@ -1643,13 +1640,10 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) · 6 unmodified lines | |||
| 1643 | copied = used; | 1640 | copied = used; |
| 1644 | break; | 1641 | break; |
| 1645 | } | 1642 | } |
| 1646 | seq += used; | ||
| 1647 | copied += used; | 1643 | copied += used; |
| 1648 | 1644 | ||
| 1649 | if (tcp_flags & TCPHDR_FIN) { | 1645 | if (tcp_flags & TCPHDR_FIN) |
| 1650 | ++seq; | ||
| 1651 | break; | 1646 | break; |
| 1652 | } | ||
| 1653 | } | 1647 | } |
| 1654 | return copied; | 1648 | return copied; |
| 1655 | } | 1649 | } |
| @@ -222,6 +222,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, · 221 unmodified lines | |||
| 222 | int *addr_len) | 222 | int *addr_len) |
| 223 | { | 223 | { |
| 224 | struct tcp_sock *tcp = tcp_sk(sk); | 224 | struct tcp_sock *tcp = tcp_sk(sk); |
| 225 | int peek = flags & MSG_PEEK; | ||
| 225 | u32 seq = tcp->copied_seq; | 226 | u32 seq = tcp->copied_seq; |
| 226 | struct sk_psock *psock; | 227 | struct sk_psock *psock; |
| 227 | int copied = 0; | 228 | int copied = 0; |
| @@ -311,7 +312,8 @@ msg_bytes_ready: · 83 unmodified lines | |||
| 311 | copied = -EAGAIN; | 312 | copied = -EAGAIN; |
| 312 | } | 313 | } |
| 313 | out: | 314 | out: |
| 314 | WRITE_ONCE(tcp->copied_seq, seq); | 315 | if (!peek) |
| 316 | WRITE_ONCE(tcp->copied_seq, seq); | ||
| 315 | tcp_rcv_space_adjust(sk); | 317 | tcp_rcv_space_adjust(sk); |
| 316 | if (copied > 0) | 318 | if (copied > 0) |
| 317 | __tcp_cleanup_rbuf(sk, copied); | 319 | __tcp_cleanup_rbuf(sk, copied); |
| @@ -253,6 +253,19 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) · 252 unmodified lines | |||
| 253 | if (unlikely(len > icsk->icsk_ack.rcv_mss + | 253 | if (unlikely(len > icsk->icsk_ack.rcv_mss + |
| 254 | MAX_TCP_OPTION_SPACE)) | 254 | MAX_TCP_OPTION_SPACE)) |
| 255 | tcp_gro_dev_warn(sk, skb, len); | 255 | tcp_gro_dev_warn(sk, skb, len); |
| 256 | /* If the skb has a len of exactly 1*MSS and has the PSH bit | ||
| 257 | * set then it is likely the end of an application write. So | ||
| 258 | * more data may not be arriving soon, and yet the data sender | ||
| 259 | * may be waiting for an ACK if cwnd-bound or using TX zero | ||
| 260 | * copy. So we set ICSK_ACK_PUSHED here so that | ||
| 261 | * tcp_cleanup_rbuf() will send an ACK immediately if the app | ||
| 262 | * reads all of the data and is not ping-pong. If len > MSS | ||
| 263 | * then this logic does not matter (and does not hurt) because | ||
| 264 | * tcp_cleanup_rbuf() will always ACK immediately if the app | ||
| 265 | * reads data and there is more than an MSS of unACKed data. | ||
| 266 | */ | ||
| 267 | if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_PSH) | ||
| 268 | icsk->icsk_ack.pending |= ICSK_ACK_PUSHED; | ||
| 256 | } else { | 269 | } else { |
| 257 | /* Otherwise, we make more careful check taking into account, | 270 | /* Otherwise, we make more careful check taking into account, |
| 258 | * that SACKs block is variable. | 271 | * that SACKs block is variable. |
| @@ -177,8 +177,7 @@ static void tcp_event_data_sent(struct tcp_sock *tp, · 176 unmodified lines | |||
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | /* Account for an ACK we sent. */ | 179 | /* Account for an ACK we sent. */ |
| 180 | static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, | 180 | static inline void tcp_event_ack_sent(struct sock *sk, u32 rcv_nxt) |
| 181 | u32 rcv_nxt) | ||
| 182 | { | 181 | { |
| 183 | struct tcp_sock *tp = tcp_sk(sk); | 182 | struct tcp_sock *tp = tcp_sk(sk); |
| 184 | 183 | ||
| @@ -192,7 +191,7 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, · 7 unmodified lines | |||
| 192 | 191 | ||
| 193 | if (unlikely(rcv_nxt != tp->rcv_nxt)) | 192 | if (unlikely(rcv_nxt != tp->rcv_nxt)) |
| 194 | return; /* Special ACK sent by DCTCP to reflect ECN */ | 193 | return; /* Special ACK sent by DCTCP to reflect ECN */ |
| 195 | tcp_dec_quickack_mode(sk, pkts); | 194 | tcp_dec_quickack_mode(sk); |
| 196 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); | 195 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); |
| 197 | } | 196 | } |
| 198 | 197 | ||
| @@ -1387,7 +1386,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, · 1188 unmodified lines | |||
| 1387 | sk, skb); | 1386 | sk, skb); |
| 1388 | 1387 | ||
| 1389 | if (likely(tcb->tcp_flags & TCPHDR_ACK)) | 1388 | if (likely(tcb->tcp_flags & TCPHDR_ACK)) |
| 1390 | tcp_event_ack_sent(sk, tcp_skb_pcount(skb), rcv_nxt); | 1389 | tcp_event_ack_sent(sk, rcv_nxt); |
| 1391 | 1390 | ||
| 1392 | if (skb->len != tcp_header_size) { | 1391 | if (skb->len != tcp_header_size) { |
| 1393 | tcp_event_data_sent(tp, sk); | 1392 | tcp_event_data_sent(tp, sk); |
| @@ -1640,9 +1640,12 @@ process: · 1639 unmodified lines | |||
| 1640 | struct sock *nsk; | 1640 | struct sock *nsk; |
| 1641 | 1641 | ||
| 1642 | sk = req->rsk_listener; | 1642 | sk = req->rsk_listener; |
| 1643 | drop_reason = tcp_inbound_md5_hash(sk, skb, | 1643 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
| 1644 | &hdr->saddr, &hdr->daddr, | 1644 | drop_reason = SKB_DROP_REASON_XFRM_POLICY; |
| 1645 | AF_INET6, dif, sdif); | 1645 | else |
| 1646 | drop_reason = tcp_inbound_md5_hash(sk, skb, | ||
| 1647 | &hdr->saddr, &hdr->daddr, | ||
| 1648 | AF_INET6, dif, sdif); | ||
| 1646 | if (drop_reason) { | 1649 | if (drop_reason) { |
| 1647 | sk_drops_add(sk, skb); | 1650 | sk_drops_add(sk, skb); |
| 1648 | reqsk_put(req); | 1651 | reqsk_put(req); |
| @@ -1689,6 +1692,7 @@ process: · 40 unmodified lines | |||
| 1689 | } | 1692 | } |
| 1690 | goto discard_and_relse; | 1693 | goto discard_and_relse; |
| 1691 | } | 1694 | } |
| 1695 | nf_reset_ct(skb); | ||
| 1692 | if (nsk == sk) { | 1696 | if (nsk == sk) { |
| 1693 | reqsk_put(req); | 1697 | reqsk_put(req); |
| 1694 | tcp_v6_restore_cb(skb); | 1698 | tcp_v6_restore_cb(skb); |
| @@ -507,7 +507,6 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 506 unmodified lines | |||
| 507 | */ | 507 | */ |
| 508 | if (len > INT_MAX - transhdrlen) | 508 | if (len > INT_MAX - transhdrlen) |
| 509 | return -EMSGSIZE; | 509 | return -EMSGSIZE; |
| 510 | ulen = len + transhdrlen; | ||
| 511 | 510 | ||
| 512 | /* Mirror BSD error message compatibility */ | 511 | /* Mirror BSD error message compatibility */ |
| 513 | if (msg->msg_flags & MSG_OOB) | 512 | if (msg->msg_flags & MSG_OOB) |
| @@ -628,6 +627,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 114 unmodified lines | |||
| 628 | 627 | ||
| 629 | back_from_confirm: | 628 | back_from_confirm: |
| 630 | lock_sock(sk); | 629 | lock_sock(sk); |
| 630 | ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0; | ||
| 631 | err = ip6_append_data(sk, ip_generic_getfrag, msg, | 631 | err = ip6_append_data(sk, ip_generic_getfrag, msg, |
| 632 | ulen, transhdrlen, &ipc6, | 632 | ulen, transhdrlen, &ipc6, |
| 633 | &fl6, (struct rt6_info *)dst, | 633 | &fl6, (struct rt6_info *)dst, |
| @@ -566,6 +566,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, · 565 unmodified lines | |||
| 566 | } | 566 | } |
| 567 | 567 | ||
| 568 | err = ieee80211_key_link(key, link, sta); | 568 | err = ieee80211_key_link(key, link, sta); |
| 569 | /* KRACK protection, shouldn't happen but just silently accept key */ | ||
| 570 | if (err == -EALREADY) | ||
| 571 | err = 0; | ||
| 569 | 572 | ||
| 570 | out_unlock: | 573 | out_unlock: |
| 571 | mutex_unlock(&local->sta_mtx); | 574 | mutex_unlock(&local->sta_mtx); |
| @@ -1857,7 +1860,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, · 1285 unmodified lines | |||
| 1857 | /* VHT can override some HT caps such as the A-MSDU max length */ | 1860 | /* VHT can override some HT caps such as the A-MSDU max length */ |
| 1858 | if (params->vht_capa) | 1861 | if (params->vht_capa) |
| 1859 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 1862 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 1860 | params->vht_capa, link_sta); | 1863 | params->vht_capa, NULL, |
| 1864 | link_sta); | ||
| 1861 | 1865 | ||
| 1862 | if (params->he_capa) | 1866 | if (params->he_capa) |
| 1863 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, | 1867 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, |
| @@ -1072,7 +1072,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, · 1071 unmodified lines | |||
| 1072 | &chandef); | 1072 | &chandef); |
| 1073 | memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); | 1073 | memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); |
| 1074 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 1074 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 1075 | &cap_ie, | 1075 | &cap_ie, NULL, |
| 1076 | &sta->deflink); | 1076 | &sta->deflink); |
| 1077 | if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap))) | 1077 | if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap))) |
| 1078 | rates_updated |= true; | 1078 | rates_updated |= true; |
| @@ -676,7 +676,7 @@ struct ieee80211_if_mesh { · 675 unmodified lines | |||
| 676 | struct timer_list mesh_path_root_timer; | 676 | struct timer_list mesh_path_root_timer; |
| 677 | 677 | ||
| 678 | unsigned long wrkq_flags; | 678 | unsigned long wrkq_flags; |
| 679 | unsigned long mbss_changed; | 679 | unsigned long mbss_changed[64 / BITS_PER_LONG]; |
| 680 | 680 | ||
| 681 | bool userspace_handles_dfs; | 681 | bool userspace_handles_dfs; |
| 682 | 682 | ||
| @@ -2141,6 +2141,7 @@ void · 1458 unmodified lines | |||
| 2141 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | 2141 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
| 2142 | struct ieee80211_supported_band *sband, | 2142 | struct ieee80211_supported_band *sband, |
| 2143 | const struct ieee80211_vht_cap *vht_cap_ie, | 2143 | const struct ieee80211_vht_cap *vht_cap_ie, |
| 2144 | const struct ieee80211_vht_cap *vht_cap_ie2, | ||
| 2144 | struct link_sta_info *link_sta); | 2145 | struct link_sta_info *link_sta); |
| 2145 | enum ieee80211_sta_rx_bandwidth | 2146 | enum ieee80211_sta_rx_bandwidth |
| 2146 | ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta); | 2147 | ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta); |
| @@ -802,6 +802,9 @@ static void ieee80211_key_destroy(struct ieee80211_key *key, · 801 unmodified lines | |||
| 802 | 802 | ||
| 803 | void ieee80211_key_free_unused(struct ieee80211_key *key) | 803 | void ieee80211_key_free_unused(struct ieee80211_key *key) |
| 804 | { | 804 | { |
| 805 | if (!key) | ||
| 806 | return; | ||
| 807 | |||
| 805 | WARN_ON(key->sdata || key->local); | 808 | WARN_ON(key->sdata || key->local); |
| 806 | ieee80211_key_free_common(key); | 809 | ieee80211_key_free_common(key); |
| 807 | } | 810 | } |
| @@ -854,7 +857,7 @@ int ieee80211_key_link(struct ieee80211_key *key, · 46 unmodified lines | |||
| 854 | * can cause warnings to appear. | 857 | * can cause warnings to appear. |
| 855 | */ | 858 | */ |
| 856 | bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION; | 859 | bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION; |
| 857 | int ret = -EOPNOTSUPP; | 860 | int ret; |
| 858 | 861 | ||
| 859 | mutex_lock(&sdata->local->key_mtx); | 862 | mutex_lock(&sdata->local->key_mtx); |
| 860 | 863 | ||
| @@ -868,8 +871,10 @@ int ieee80211_key_link(struct ieee80211_key *key, · 7 unmodified lines | |||
| 868 | * the same cipher. Enforce the assumption for pairwise keys. | 871 | * the same cipher. Enforce the assumption for pairwise keys. |
| 869 | */ | 872 | */ |
| 870 | if ((alt_key && alt_key->conf.cipher != key->conf.cipher) || | 873 | if ((alt_key && alt_key->conf.cipher != key->conf.cipher) || |
| 871 | (old_key && old_key->conf.cipher != key->conf.cipher)) | 874 | (old_key && old_key->conf.cipher != key->conf.cipher)) { |
| 875 | ret = -EOPNOTSUPP; | ||
| 872 | goto out; | 876 | goto out; |
| 877 | } | ||
| 873 | } else if (sta) { | 878 | } else if (sta) { |
| 874 | struct link_sta_info *link_sta = &sta->deflink; | 879 | struct link_sta_info *link_sta = &sta->deflink; |
| 875 | int link_id = key->conf.link_id; | 880 | int link_id = key->conf.link_id; |
| @@ -895,8 +900,10 @@ int ieee80211_key_link(struct ieee80211_key *key, · 19 unmodified lines | |||
| 895 | 900 | ||
| 896 | /* Non-pairwise keys must also not switch the cipher on rekey */ | 901 | /* Non-pairwise keys must also not switch the cipher on rekey */ |
| 897 | if (!pairwise) { | 902 | if (!pairwise) { |
| 898 | if (old_key && old_key->conf.cipher != key->conf.cipher) | 903 | if (old_key && old_key->conf.cipher != key->conf.cipher) { |
| 904 | ret = -EOPNOTSUPP; | ||
| 899 | goto out; | 905 | goto out; |
| 906 | } | ||
| 900 | } | 907 | } |
| 901 | 908 | ||
| 902 | /* | 909 | /* |
| @@ -904,9 +911,8 @@ int ieee80211_key_link(struct ieee80211_key *key, · 1 unmodified line | |||
| 904 | * new version of the key to avoid nonce reuse or replay issues. | 911 | * new version of the key to avoid nonce reuse or replay issues. |
| 905 | */ | 912 | */ |
| 906 | if (ieee80211_key_identical(sdata, old_key, key)) { | 913 | if (ieee80211_key_identical(sdata, old_key, key)) { |
| 907 | ieee80211_key_free_unused(key); | 914 | ret = -EALREADY; |
| 908 | ret = 0; | 915 | goto unlock; |
| 909 | goto out; | ||
| 910 | } | 916 | } |
| 911 | 917 | ||
| 912 | key->local = sdata->local; | 918 | key->local = sdata->local; |
| @@ -930,7 +936,11 @@ int ieee80211_key_link(struct ieee80211_key *key, · 17 unmodified lines | |||
| 930 | ieee80211_key_free(key, delay_tailroom); | 936 | ieee80211_key_free(key, delay_tailroom); |
| 931 | } | 937 | } |
| 932 | 938 | ||
| 939 | key = NULL; | ||
| 940 | |||
| 933 | out: | 941 | out: |
| 942 | ieee80211_key_free_unused(key); | ||
| 943 | unlock: | ||
| 934 | mutex_unlock(&sdata->local->key_mtx); | 944 | mutex_unlock(&sdata->local->key_mtx); |
| 935 | 945 | ||
| 936 | return ret; | 946 | return ret; |
| @@ -1175,7 +1175,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, · 1174 unmodified lines | |||
| 1175 | 1175 | ||
| 1176 | /* if we race with running work, worst case this work becomes a noop */ | 1176 | /* if we race with running work, worst case this work becomes a noop */ |
| 1177 | for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE) | 1177 | for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE) |
| 1178 | set_bit(bit, &ifmsh->mbss_changed); | 1178 | set_bit(bit, ifmsh->mbss_changed); |
| 1179 | set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags); | 1179 | set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags); |
| 1180 | wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work); | 1180 | wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work); |
| 1181 | } | 1181 | } |
| @@ -1257,7 +1257,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) · 75 unmodified lines | |||
| 1257 | 1257 | ||
| 1258 | /* clear any mesh work (for next join) we may have accrued */ | 1258 | /* clear any mesh work (for next join) we may have accrued */ |
| 1259 | ifmsh->wrkq_flags = 0; | 1259 | ifmsh->wrkq_flags = 0; |
| 1260 | ifmsh->mbss_changed = 0; | 1260 | memset(ifmsh->mbss_changed, 0, sizeof(ifmsh->mbss_changed)); |
| 1261 | 1261 | ||
| 1262 | local->fif_other_bss--; | 1262 | local->fif_other_bss--; |
| 1263 | atomic_dec(&local->iff_allmultis); | 1263 | atomic_dec(&local->iff_allmultis); |
| @@ -1724,9 +1724,9 @@ static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata) · 460 unmodified lines | |||
| 1724 | u32 bit; | 1724 | u32 bit; |
| 1725 | u64 changed = 0; | 1725 | u64 changed = 0; |
| 1726 | 1726 | ||
| 1727 | for_each_set_bit(bit, &ifmsh->mbss_changed, | 1727 | for_each_set_bit(bit, ifmsh->mbss_changed, |
| 1728 | sizeof(changed) * BITS_PER_BYTE) { | 1728 | sizeof(changed) * BITS_PER_BYTE) { |
| 1729 | clear_bit(bit, &ifmsh->mbss_changed); | 1729 | clear_bit(bit, ifmsh->mbss_changed); |
| 1730 | changed |= BIT(bit); | 1730 | changed |= BIT(bit); |
| 1731 | } | 1731 | } |
| 1732 | 1732 | ||
| @@ -451,7 +451,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, · 450 unmodified lines | |||
| 451 | changed |= IEEE80211_RC_BW_CHANGED; | 451 | changed |= IEEE80211_RC_BW_CHANGED; |
| 452 | 452 | ||
| 453 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 453 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 454 | elems->vht_cap_elem, | 454 | elems->vht_cap_elem, NULL, |
| 455 | &sta->deflink); | 455 | &sta->deflink); |
| 456 | 456 | ||
| 457 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap, | 457 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap, |
| @@ -4202,10 +4202,33 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, · 4201 unmodified lines | |||
| 4202 | elems->ht_cap_elem, | 4202 | elems->ht_cap_elem, |
| 4203 | link_sta); | 4203 | link_sta); |
| 4204 | 4204 | ||
| 4205 | if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) | 4205 | if (elems->vht_cap_elem && |
| 4206 | !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) { | ||
| 4207 | const struct ieee80211_vht_cap *bss_vht_cap = NULL; | ||
| 4208 | const struct cfg80211_bss_ies *ies; | ||
| 4209 | |||
| 4210 | /* | ||
| 4211 | * Cisco AP module 9115 with FW 17.3 has a bug and sends a | ||
| 4212 | * too large maximum MPDU length in the association response | ||
| 4213 | * (indicating 12k) that it cannot actually process ... | ||
| 4214 | * Work around that. | ||
| 4215 | */ | ||
| 4216 | rcu_read_lock(); | ||
| 4217 | ies = rcu_dereference(cbss->ies); | ||
| 4218 | if (ies) { | ||
| 4219 | const struct element *elem; | ||
| 4220 | |||
| 4221 | elem = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY, | ||
| 4222 | ies->data, ies->len); | ||
| 4223 | if (elem && elem->datalen >= sizeof(*bss_vht_cap)) | ||
| 4224 | bss_vht_cap = (const void *)elem->data; | ||
| 4225 | } | ||
| 4226 | |||
| 4206 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 4227 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 4207 | elems->vht_cap_elem, | 4228 | elems->vht_cap_elem, |
| 4208 | link_sta); | 4229 | bss_vht_cap, link_sta); |
| 4230 | rcu_read_unlock(); | ||
| 4231 | } | ||
| 4209 | 4232 | ||
| 4210 | if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && | 4233 | if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && |
| 4211 | elems->he_cap) { | 4234 | elems->he_cap) { |
| @@ -5107,9 +5130,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, · 895 unmodified lines | |||
| 5107 | continue; | 5130 | continue; |
| 5108 | 5131 | ||
| 5109 | valid_links |= BIT(link_id); | 5132 | valid_links |= BIT(link_id); |
| 5110 | if (assoc_data->link[link_id].disabled) { | 5133 | if (assoc_data->link[link_id].disabled) |
| 5111 | dormant_links |= BIT(link_id); | 5134 | dormant_links |= BIT(link_id); |
| 5112 | } else if (link_id != assoc_data->assoc_link_id) { | 5135 | |
| 5136 | if (link_id != assoc_data->assoc_link_id) { | ||
| 5113 | err = ieee80211_sta_allocate_link(sta, link_id); | 5137 | err = ieee80211_sta_allocate_link(sta, link_id); |
| 5114 | if (err) | 5138 | if (err) |
| 5115 | goto out_err; | 5139 | goto out_err; |
| @@ -5124,7 +5148,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, · 8 unmodified lines | |||
| 5124 | struct ieee80211_link_data *link; | 5148 | struct ieee80211_link_data *link; |
| 5125 | struct link_sta_info *link_sta; | 5149 | struct link_sta_info *link_sta; |
| 5126 | 5150 | ||
| 5127 | if (!cbss || assoc_data->link[link_id].disabled) | 5151 | if (!cbss) |
| 5128 | continue; | 5152 | continue; |
| 5129 | 5153 | ||
| 5130 | link = sdata_dereference(sdata->link[link_id], sdata); | 5154 | link = sdata_dereference(sdata->link[link_id], sdata); |
| @@ -5429,17 +5453,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, · 298 unmodified lines | |||
| 5429 | for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { | 5453 | for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { |
| 5430 | struct ieee80211_link_data *link; | 5454 | struct ieee80211_link_data *link; |
| 5431 | 5455 | ||
| 5432 | link = sdata_dereference(sdata->link[link_id], sdata); | ||
| 5433 | if (!link) | ||
| 5434 | continue; | ||
| 5435 | |||
| 5436 | if (!assoc_data->link[link_id].bss) | 5456 | if (!assoc_data->link[link_id].bss) |
| 5437 | continue; | 5457 | continue; |
| 5438 | 5458 | ||
| 5439 | resp.links[link_id].bss = assoc_data->link[link_id].bss; | 5459 | resp.links[link_id].bss = assoc_data->link[link_id].bss; |
| 5440 | resp.links[link_id].addr = link->conf->addr; | 5460 | ether_addr_copy(resp.links[link_id].addr, |
| 5461 | assoc_data->link[link_id].addr); | ||
| 5441 | resp.links[link_id].status = assoc_data->link[link_id].status; | 5462 | resp.links[link_id].status = assoc_data->link[link_id].status; |
| 5442 | 5463 | ||
| 5464 | link = sdata_dereference(sdata->link[link_id], sdata); | ||
| 5465 | if (!link) | ||
| 5466 | continue; | ||
| 5467 | |||
| 5443 | /* get uapsd queues configuration - same for all links */ | 5468 | /* get uapsd queues configuration - same for all links */ |
| 5444 | resp.uapsd_queues = 0; | 5469 | resp.uapsd_queues = 0; |
| 5445 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 5470 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
| @@ -665,7 +665,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) · 664 unmodified lines | |||
| 665 | } | 665 | } |
| 666 | 666 | ||
| 667 | if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED && | 667 | if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED && |
| 668 | !ieee80211_is_deauth(hdr->frame_control))) | 668 | !ieee80211_is_deauth(hdr->frame_control)) && |
| 669 | tx->skb->protocol != tx->sdata->control_port_protocol) | ||
| 669 | return TX_DROP; | 670 | return TX_DROP; |
| 670 | 671 | ||
| 671 | if (!skip_hw && tx->key && | 672 | if (!skip_hw && tx->key && |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | * | 4 | * |
| 5 | * Portions of this file | 5 | * Portions of this file |
| 6 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH | 6 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
| 7 | * Copyright (C) 2018 - 2022 Intel Corporation | 7 | * Copyright (C) 2018 - 2023 Intel Corporation |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/ieee80211.h> | 10 | #include <linux/ieee80211.h> |
| @@ -116,12 +116,14 @@ void · 105 unmodified lines | |||
| 116 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | 116 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
| 117 | struct ieee80211_supported_band *sband, | 117 | struct ieee80211_supported_band *sband, |
| 118 | const struct ieee80211_vht_cap *vht_cap_ie, | 118 | const struct ieee80211_vht_cap *vht_cap_ie, |
| 119 | const struct ieee80211_vht_cap *vht_cap_ie2, | ||
| 119 | struct link_sta_info *link_sta) | 120 | struct link_sta_info *link_sta) |
| 120 | { | 121 | { |
| 121 | struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap; | 122 | struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap; |
| 122 | struct ieee80211_sta_vht_cap own_cap; | 123 | struct ieee80211_sta_vht_cap own_cap; |
| 123 | u32 cap_info, i; | 124 | u32 cap_info, i; |
| 124 | bool have_80mhz; | 125 | bool have_80mhz; |
| 126 | u32 mpdu_len; | ||
| 125 | 127 | ||
| 126 | memset(vht_cap, 0, sizeof(*vht_cap)); | 128 | memset(vht_cap, 0, sizeof(*vht_cap)); |
| 127 | 129 | ||
| @@ -317,11 +319,21 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, · 189 unmodified lines | |||
| 317 | 319 | ||
| 318 | link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); | 320 | link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); |
| 319 | 321 | ||
| 322 | /* | ||
| 323 | * Work around the Cisco 9115 FW 17.3 bug by taking the min of | ||
| 324 | * both reported MPDU lengths. | ||
| 325 | */ | ||
| 326 | mpdu_len = vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK; | ||
| 327 | if (vht_cap_ie2) | ||
| 328 | mpdu_len = min_t(u32, mpdu_len, | ||
| 329 | le32_get_bits(vht_cap_ie2->vht_cap_info, | ||
| 330 | IEEE80211_VHT_CAP_MAX_MPDU_MASK)); | ||
| 331 | |||
| 320 | /* | 332 | /* |
| 321 | * FIXME - should the amsdu len be per link? store per link | 333 | * FIXME - should the amsdu len be per link? store per link |
| 322 | * and maintain a minimum? | 334 | * and maintain a minimum? |
| 323 | */ | 335 | */ |
| 324 | switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) { | 336 | switch (mpdu_len) { |
| 325 | case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: | 337 | case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: |
| 326 | link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454; | 338 | link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454; |
| 327 | break; | 339 | break; |
| @@ -307,12 +307,6 @@ int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info) · 306 unmodified lines | |||
| 307 | goto create_err; | 307 | goto create_err; |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | if (addr_l.id == 0) { | ||
| 311 | NL_SET_ERR_MSG_ATTR(info->extack, laddr, "missing local addr id"); | ||
| 312 | err = -EINVAL; | ||
| 313 | goto create_err; | ||
| 314 | } | ||
| 315 | |||
| 316 | err = mptcp_pm_parse_addr(raddr, info, &addr_r); | 310 | err = mptcp_pm_parse_addr(raddr, info, &addr_r); |
| 317 | if (err < 0) { | 311 | if (err < 0) { |
| 318 | NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr"); | 312 | NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr"); |
| @@ -3425,24 +3425,21 @@ static void schedule_3rdack_retransmission(struct sock *ssk) · 3424 unmodified lines | |||
| 3425 | sk_reset_timer(ssk, &icsk->icsk_delack_timer, timeout); | 3425 | sk_reset_timer(ssk, &icsk->icsk_delack_timer, timeout); |
| 3426 | } | 3426 | } |
| 3427 | 3427 | ||
| 3428 | void mptcp_subflow_process_delegated(struct sock *ssk) | 3428 | void mptcp_subflow_process_delegated(struct sock *ssk, long status) |
| 3429 | { | 3429 | { |
| 3430 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); | 3430 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 3431 | struct sock *sk = subflow->conn; | 3431 | struct sock *sk = subflow->conn; |
| 3432 | 3432 | ||
| 3433 | if (test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) { | 3433 | if (status & BIT(MPTCP_DELEGATE_SEND)) { |
| 3434 | mptcp_data_lock(sk); | 3434 | mptcp_data_lock(sk); |
| 3435 | if (!sock_owned_by_user(sk)) | 3435 | if (!sock_owned_by_user(sk)) |
| 3436 | __mptcp_subflow_push_pending(sk, ssk, true); | 3436 | __mptcp_subflow_push_pending(sk, ssk, true); |
| 3437 | else | 3437 | else |
| 3438 | __set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags); | 3438 | __set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags); |
| 3439 | mptcp_data_unlock(sk); | 3439 | mptcp_data_unlock(sk); |
| 3440 | mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_SEND); | ||
| 3441 | } | 3440 | } |
| 3442 | if (test_bit(MPTCP_DELEGATE_ACK, &subflow->delegated_status)) { | 3441 | if (status & BIT(MPTCP_DELEGATE_ACK)) |
| 3443 | schedule_3rdack_retransmission(ssk); | 3442 | schedule_3rdack_retransmission(ssk); |
| 3444 | mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_ACK); | ||
| 3445 | } | ||
| 3446 | } | 3443 | } |
| 3447 | 3444 | ||
| 3448 | static int mptcp_hash(struct sock *sk) | 3445 | static int mptcp_hash(struct sock *sk) |
| @@ -3968,14 +3965,17 @@ static int mptcp_napi_poll(struct napi_struct *napi, int budget) · 519 unmodified lines | |||
| 3968 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | 3965 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 3969 | 3966 | ||
| 3970 | bh_lock_sock_nested(ssk); | 3967 | bh_lock_sock_nested(ssk); |
| 3971 | if (!sock_owned_by_user(ssk) && | 3968 | if (!sock_owned_by_user(ssk)) { |
| 3972 | mptcp_subflow_has_delegated_action(subflow)) | 3969 | mptcp_subflow_process_delegated(ssk, xchg(&subflow->delegated_status, 0)); |
| 3973 | mptcp_subflow_process_delegated(ssk); | 3970 | } else { |
| 3974 | /* ... elsewhere tcp_release_cb_override already processed | 3971 | /* tcp_release_cb_override already processed |
| 3975 | * the action or will do at next release_sock(). | 3972 | * the action or will do at next release_sock(). |
| 3976 | * In both case must dequeue the subflow here - on the same | 3973 | * In both case must dequeue the subflow here - on the same |
| 3977 | * CPU that scheduled it. | 3974 | * CPU that scheduled it. |
| 3978 | */ | 3975 | */ |
| 3976 | smp_wmb(); | ||
| 3977 | clear_bit(MPTCP_DELEGATE_SCHEDULED, &subflow->delegated_status); | ||
| 3978 | } | ||
| 3979 | bh_unlock_sock(ssk); | 3979 | bh_unlock_sock(ssk); |
| 3980 | sock_put(ssk); | 3980 | sock_put(ssk); |
| 3981 | 3981 | ||
| @@ -444,9 +444,11 @@ struct mptcp_delegated_action { · 443 unmodified lines | |||
| 444 | 444 | ||
| 445 | DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); | 445 | DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); |
| 446 | 446 | ||
| 447 | #define MPTCP_DELEGATE_SEND 0 | 447 | #define MPTCP_DELEGATE_SCHEDULED 0 |
| 448 | #define MPTCP_DELEGATE_ACK 1 | 448 | #define MPTCP_DELEGATE_SEND 1 |
| 449 | #define MPTCP_DELEGATE_ACK 2 | ||
| 449 | 450 | ||
| 451 | #define MPTCP_DELEGATE_ACTIONS_MASK (~BIT(MPTCP_DELEGATE_SCHEDULED)) | ||
| 450 | /* MPTCP subflow context */ | 452 | /* MPTCP subflow context */ |
| 451 | struct mptcp_subflow_context { | 453 | struct mptcp_subflow_context { |
| 452 | struct list_head node;/* conn_list of subflows */ | 454 | struct list_head node;/* conn_list of subflows */ |
| @@ -564,23 +566,24 @@ mptcp_subflow_get_mapped_dsn(const struct mptcp_subflow_context *subflow) · 111 unmodified lines | |||
| 564 | return subflow->map_seq + mptcp_subflow_get_map_offset(subflow); | 566 | return subflow->map_seq + mptcp_subflow_get_map_offset(subflow); |
| 565 | } | 567 | } |
| 566 | 568 | ||
| 567 | void mptcp_subflow_process_delegated(struct sock *ssk); | 569 | void mptcp_subflow_process_delegated(struct sock *ssk, long actions); |
| 568 | 570 | ||
| 569 | static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow, int action) | 571 | static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow, int action) |
| 570 | { | 572 | { |
| 573 | long old, set_bits = BIT(MPTCP_DELEGATE_SCHEDULED) | BIT(action); | ||
| 571 | struct mptcp_delegated_action *delegated; | 574 | struct mptcp_delegated_action *delegated; |
| 572 | bool schedule; | 575 | bool schedule; |
| 573 | 576 | ||
| 574 | /* the caller held the subflow bh socket lock */ | 577 | /* the caller held the subflow bh socket lock */ |
| 575 | lockdep_assert_in_softirq(); | 578 | lockdep_assert_in_softirq(); |
| 576 | 579 | ||
| 577 | /* The implied barrier pairs with mptcp_subflow_delegated_done(), and | 580 | /* The implied barrier pairs with tcp_release_cb_override() |
| 578 | * ensures the below list check sees list updates done prior to status | 581 | * mptcp_napi_poll(), and ensures the below list check sees list |
| 579 | * bit changes | 582 | * updates done prior to delegated status bits changes |
| 580 | */ | 583 | */ |
| 581 | if (!test_and_set_bit(action, &subflow->delegated_status)) { | 584 | old = set_mask_bits(&subflow->delegated_status, 0, set_bits); |
| 582 | /* still on delegated list from previous scheduling */ | 585 | if (!(old & BIT(MPTCP_DELEGATE_SCHEDULED))) { |
| 583 | if (!list_empty(&subflow->delegated_node)) | 586 | if (WARN_ON_ONCE(!list_empty(&subflow->delegated_node))) |
| 584 | return; | 587 | return; |
| 585 | 588 | ||
| 586 | delegated = this_cpu_ptr(&mptcp_delegated_actions); | 589 | delegated = this_cpu_ptr(&mptcp_delegated_actions); |
| @@ -605,20 +608,6 @@ mptcp_subflow_delegated_next(struct mptcp_delegated_action *delegated) · 18 unmodified lines | |||
| 605 | return ret; | 608 | return ret; |
| 606 | } | 609 | } |
| 607 | 610 | ||
| 608 | static inline bool mptcp_subflow_has_delegated_action(const struct mptcp_subflow_context *subflow) | ||
| 609 | { | ||
| 610 | return !!READ_ONCE(subflow->delegated_status); | ||
| 611 | } | ||
| 612 | |||
| 613 | static inline void mptcp_subflow_delegated_done(struct mptcp_subflow_context *subflow, int action) | ||
| 614 | { | ||
| 615 | /* pairs with mptcp_subflow_delegate, ensures delegate_node is updated before | ||
| 616 | * touching the status bit | ||
| 617 | */ | ||
| 618 | smp_wmb(); | ||
| 619 | clear_bit(action, &subflow->delegated_status); | ||
| 620 | } | ||
| 621 | |||
| 622 | int mptcp_is_enabled(const struct net *net); | 611 | int mptcp_is_enabled(const struct net *net); |
| 623 | unsigned int mptcp_get_add_addr_timeout(const struct net *net); | 612 | unsigned int mptcp_get_add_addr_timeout(const struct net *net); |
| 624 | int mptcp_is_checksum_enabled(const struct net *net); | 613 | int mptcp_is_checksum_enabled(const struct net *net); |
| @@ -1956,9 +1956,15 @@ static void subflow_ulp_clone(const struct request_sock *req, · 1955 unmodified lines | |||
| 1956 | static void tcp_release_cb_override(struct sock *ssk) | 1956 | static void tcp_release_cb_override(struct sock *ssk) |
| 1957 | { | 1957 | { |
| 1958 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); | 1958 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 1959 | long status; | ||
| 1959 | 1960 | ||
| 1960 | if (mptcp_subflow_has_delegated_action(subflow)) | 1961 | /* process and clear all the pending actions, but leave the subflow into |
| 1961 | mptcp_subflow_process_delegated(ssk); | 1962 | * the napi queue. To respect locking, only the same CPU that originated |
| 1963 | * the action can touch the list. mptcp_napi_poll will take care of it. | ||
| 1964 | */ | ||
| 1965 | status = set_mask_bits(&subflow->delegated_status, MPTCP_DELEGATE_ACTIONS_MASK, 0); | ||
| 1966 | if (status) | ||
| 1967 | mptcp_subflow_process_delegated(ssk, status); | ||
| 1962 | 1968 | ||
| 1963 | tcp_release_cb(ssk); | 1969 | tcp_release_cb(ssk); |
| 1964 | } | 1970 | } |
| @@ -1439,7 +1439,7 @@ static int bind_mcastif_addr(struct socket *sock, struct net_device *dev) · 1438 unmodified lines | |||
| 1439 | sin.sin_addr.s_addr = addr; | 1439 | sin.sin_addr.s_addr = addr; |
| 1440 | sin.sin_port = 0; | 1440 | sin.sin_port = 0; |
| 1441 | 1441 | ||
| 1442 | return sock->ops->bind(sock, (struct sockaddr*)&sin, sizeof(sin)); | 1442 | return kernel_bind(sock, (struct sockaddr *)&sin, sizeof(sin)); |
| 1443 | } | 1443 | } |
| 1444 | 1444 | ||
| 1445 | static void get_mcast_sockaddr(union ipvs_sockaddr *sa, int *salen, | 1445 | static void get_mcast_sockaddr(union ipvs_sockaddr *sa, int *salen, |
| @@ -1505,8 +1505,8 @@ static int make_send_sock(struct netns_ipvs *ipvs, int id, · 59 unmodified lines | |||
| 1505 | } | 1505 | } |
| 1506 | 1506 | ||
| 1507 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->mcfg, id); | 1507 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->mcfg, id); |
| 1508 | result = sock->ops->connect(sock, (struct sockaddr *) &mcast_addr, | 1508 | result = kernel_connect(sock, (struct sockaddr *)&mcast_addr, |
| 1509 | salen, 0); | 1509 | salen, 0); |
| 1510 | if (result < 0) { | 1510 | if (result < 0) { |
| 1511 | pr_err("Error connecting to the multicast addr\n"); | 1511 | pr_err("Error connecting to the multicast addr\n"); |
| 1512 | goto error; | 1512 | goto error; |
| @@ -1546,7 +1546,7 @@ static int make_receive_sock(struct netns_ipvs *ipvs, int id, · 33 unmodified lines | |||
| 1546 | 1546 | ||
| 1547 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id); | 1547 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id); |
| 1548 | sock->sk->sk_bound_dev_if = dev->ifindex; | 1548 | sock->sk->sk_bound_dev_if = dev->ifindex; |
| 1549 | result = sock->ops->bind(sock, (struct sockaddr *)&mcast_addr, salen); | 1549 | result = kernel_bind(sock, (struct sockaddr *)&mcast_addr, salen); |
| 1550 | if (result < 0) { | 1550 | if (result < 0) { |
| 1551 | pr_err("Error binding to the multicast addr\n"); | 1551 | pr_err("Error binding to the multicast addr\n"); |
| 1552 | goto error; | 1552 | goto error; |
| @@ -112,7 +112,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 111 unmodified lines | |||
| 112 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA}, | 112 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA}, |
| 113 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/ | 113 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/ |
| 114 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */ | 114 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */ |
| 115 | /* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ | 115 | /* cookie_ack */ {sCL, sCL, sCW, sES, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ |
| 116 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL}, | 116 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL}, |
| 117 | /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, | 117 | /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| 118 | /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, | 118 | /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| @@ -126,7 +126,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 7 unmodified lines | |||
| 126 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV}, | 126 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV}, |
| 127 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV}, | 127 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV}, |
| 128 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV}, | 128 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV}, |
| 129 | /* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ | 129 | /* cookie_echo */ {sIV, sCL, sCE, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ |
| 130 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV}, | 130 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV}, |
| 131 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV}, | 131 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV}, |
| 132 | /* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, | 132 | /* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| @@ -412,6 +412,9 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 279 unmodified lines | |||
| 412 | /* (D) vtag must be same as init_vtag as found in INIT_ACK */ | 412 | /* (D) vtag must be same as init_vtag as found in INIT_ACK */ |
| 413 | if (sh->vtag != ct->proto.sctp.vtag[dir]) | 413 | if (sh->vtag != ct->proto.sctp.vtag[dir]) |
| 414 | goto out_unlock; | 414 | goto out_unlock; |
| 415 | } else if (sch->type == SCTP_CID_COOKIE_ACK) { | ||
| 416 | ct->proto.sctp.init[dir] = 0; | ||
| 417 | ct->proto.sctp.init[!dir] = 0; | ||
| 415 | } else if (sch->type == SCTP_CID_HEARTBEAT) { | 418 | } else if (sch->type == SCTP_CID_HEARTBEAT) { |
| 416 | if (ct->proto.sctp.vtag[dir] == 0) { | 419 | if (ct->proto.sctp.vtag[dir] == 0) { |
| 417 | pr_debug("Setting %d vtag %x for dir %d\n", sch->type, sh->vtag, dir); | 420 | pr_debug("Setting %d vtag %x for dir %d\n", sch->type, sh->vtag, dir); |
| @@ -461,16 +464,18 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 43 unmodified lines | |||
| 461 | } | 464 | } |
| 462 | 465 | ||
| 463 | /* If it is an INIT or an INIT ACK note down the vtag */ | 466 | /* If it is an INIT or an INIT ACK note down the vtag */ |
| 464 | if (sch->type == SCTP_CID_INIT || | 467 | if (sch->type == SCTP_CID_INIT) { |
| 465 | sch->type == SCTP_CID_INIT_ACK) { | 468 | struct sctp_inithdr _ih, *ih; |
| 466 | struct sctp_inithdr _inithdr, *ih; | ||
| 467 | 469 | ||
| 468 | ih = skb_header_pointer(skb, offset + sizeof(_sch), | 470 | ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih); |
| 469 | sizeof(_inithdr), &_inithdr); | 471 | if (!ih) |
| 470 | if (ih == NULL) | ||
| 471 | goto out_unlock; | 472 | goto out_unlock; |
| 472 | pr_debug("Setting vtag %x for dir %d\n", | 473 | |
| 473 | ih->init_tag, !dir); | 474 | if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir]) |
| 475 | ct->proto.sctp.init[!dir] = 0; | ||
| 476 | ct->proto.sctp.init[dir] = 1; | ||
| 477 | |||
| 478 | pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir); | ||
| 474 | ct->proto.sctp.vtag[!dir] = ih->init_tag; | 479 | ct->proto.sctp.vtag[!dir] = ih->init_tag; |
| 475 | 480 | ||
| 476 | /* don't renew timeout on init retransmit so | 481 | /* don't renew timeout on init retransmit so |
| @@ -481,6 +486,24 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 4 unmodified lines | |||
| 481 | old_state == SCTP_CONNTRACK_CLOSED && | 486 | old_state == SCTP_CONNTRACK_CLOSED && |
| 482 | nf_ct_is_confirmed(ct)) | 487 | nf_ct_is_confirmed(ct)) |
| 483 | ignore = true; | 488 | ignore = true; |
| 489 | } else if (sch->type == SCTP_CID_INIT_ACK) { | ||
| 490 | struct sctp_inithdr _ih, *ih; | ||
| 491 | __be32 vtag; | ||
| 492 | |||
| 493 | ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih); | ||
| 494 | if (!ih) | ||
| 495 | goto out_unlock; | ||
| 496 | |||
| 497 | vtag = ct->proto.sctp.vtag[!dir]; | ||
| 498 | if (!ct->proto.sctp.init[!dir] && vtag && vtag != ih->init_tag) | ||
| 499 | goto out_unlock; | ||
| 500 | /* collision */ | ||
| 501 | if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir] && | ||
| 502 | vtag != ih->init_tag) | ||
| 503 | goto out_unlock; | ||
| 504 | |||
| 505 | pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir); | ||
| 506 | ct->proto.sctp.vtag[!dir] = ih->init_tag; | ||
| 484 | } | 507 | } |
| 485 | 508 | ||
| 486 | ct->proto.sctp.state = new_state; | 509 | ct->proto.sctp.state = new_state; |
| @@ -7871,24 +7871,14 @@ static int nf_tables_delobj(struct sk_buff *skb, const struct nfnl_info *info, · 7870 unmodified lines | |||
| 7871 | return nft_delobj(&ctx, obj); | 7871 | return nft_delobj(&ctx, obj); |
| 7872 | } | 7872 | } |
| 7873 | 7873 | ||
| 7874 | void nft_obj_notify(struct net *net, const struct nft_table *table, | 7874 | static void |
| 7875 | struct nft_object *obj, u32 portid, u32 seq, int event, | 7875 | __nft_obj_notify(struct net *net, const struct nft_table *table, |
| 7876 | u16 flags, int family, int report, gfp_t gfp) | 7876 | struct nft_object *obj, u32 portid, u32 seq, int event, |
| 7877 | u16 flags, int family, int report, gfp_t gfp) | ||
| 7877 | { | 7878 | { |
| 7878 | struct nftables_pernet *nft_net = nft_pernet(net); | 7879 | struct nftables_pernet *nft_net = nft_pernet(net); |
| 7879 | struct sk_buff *skb; | 7880 | struct sk_buff *skb; |
| 7880 | int err; | 7881 | int err; |
| 7881 | char *buf = kasprintf(gfp, "%s:%u", | ||
| 7882 | table->name, nft_net->base_seq); | ||
| 7883 | |||
| 7884 | audit_log_nfcfg(buf, | ||
| 7885 | family, | ||
| 7886 | obj->handle, | ||
| 7887 | event == NFT_MSG_NEWOBJ ? | ||
| 7888 | AUDIT_NFT_OP_OBJ_REGISTER : | ||
| 7889 | AUDIT_NFT_OP_OBJ_UNREGISTER, | ||
| 7890 | gfp); | ||
| 7891 | kfree(buf); | ||
| 7892 | 7882 | ||
| 7893 | if (!report && | 7883 | if (!report && |
| 7894 | !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) | 7884 | !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) |
| @@ -7911,13 +7901,35 @@ void nft_obj_notify(struct net *net, const struct nft_table *table, · 16 unmodified lines | |||
| 7911 | err: | 7901 | err: |
| 7912 | nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS); | 7902 | nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS); |
| 7913 | } | 7903 | } |
| 7904 | |||
| 7905 | void nft_obj_notify(struct net *net, const struct nft_table *table, | ||
| 7906 | struct nft_object *obj, u32 portid, u32 seq, int event, | ||
| 7907 | u16 flags, int family, int report, gfp_t gfp) | ||
| 7908 | { | ||
| 7909 | struct nftables_pernet *nft_net = nft_pernet(net); | ||
| 7910 | char *buf = kasprintf(gfp, "%s:%u", | ||
| 7911 | table->name, nft_net->base_seq); | ||
| 7912 | |||
| 7913 | audit_log_nfcfg(buf, | ||
| 7914 | family, | ||
| 7915 | obj->handle, | ||
| 7916 | event == NFT_MSG_NEWOBJ ? | ||
| 7917 | AUDIT_NFT_OP_OBJ_REGISTER : | ||
| 7918 | AUDIT_NFT_OP_OBJ_UNREGISTER, | ||
| 7919 | gfp); | ||
| 7920 | kfree(buf); | ||
| 7921 | |||
| 7922 | __nft_obj_notify(net, table, obj, portid, seq, event, | ||
| 7923 | flags, family, report, gfp); | ||
| 7924 | } | ||
| 7914 | EXPORT_SYMBOL_GPL(nft_obj_notify); | 7925 | EXPORT_SYMBOL_GPL(nft_obj_notify); |
| 7915 | 7926 | ||
| 7916 | static void nf_tables_obj_notify(const struct nft_ctx *ctx, | 7927 | static void nf_tables_obj_notify(const struct nft_ctx *ctx, |
| 7917 | struct nft_object *obj, int event) | 7928 | struct nft_object *obj, int event) |
| 7918 | { | 7929 | { |
| 7919 | nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event, | 7930 | __nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, |
| 7920 | ctx->flags, ctx->family, ctx->report, GFP_KERNEL); | 7931 | ctx->seq, event, ctx->flags, ctx->family, |
| 7932 | ctx->report, GFP_KERNEL); | ||
| 7921 | } | 7933 | } |
| 7922 | 7934 | ||
| 7923 | /* | 7935 | /* |
| @@ -154,6 +154,17 @@ int nft_payload_inner_offset(const struct nft_pktinfo *pkt) · 153 unmodified lines | |||
| 154 | return pkt->inneroff; | 154 | return pkt->inneroff; |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | static bool nft_payload_need_vlan_copy(const struct nft_payload *priv) | ||
| 158 | { | ||
| 159 | unsigned int len = priv->offset + priv->len; | ||
| 160 | |||
| 161 | /* data past ether src/dst requested, copy needed */ | ||
| 162 | if (len > offsetof(struct ethhdr, h_proto)) | ||
| 163 | return true; | ||
| 164 | |||
| 165 | return false; | ||
| 166 | } | ||
| 167 | |||
| 157 | void nft_payload_eval(const struct nft_expr *expr, | 168 | void nft_payload_eval(const struct nft_expr *expr, |
| 158 | struct nft_regs *regs, | 169 | struct nft_regs *regs, |
| 159 | const struct nft_pktinfo *pkt) | 170 | const struct nft_pktinfo *pkt) |
| @@ -172,7 +183,7 @@ void nft_payload_eval(const struct nft_expr *expr, · 12 unmodified lines | |||
| 172 | goto err; | 183 | goto err; |
| 173 | 184 | ||
| 174 | if (skb_vlan_tag_present(skb) && | 185 | if (skb_vlan_tag_present(skb) && |
| 175 | priv->offset >= offsetof(struct ethhdr, h_proto)) { | 186 | nft_payload_need_vlan_copy(priv)) { |
| 176 | if (!nft_payload_copy_vlan(dest, skb, | 187 | if (!nft_payload_copy_vlan(dest, skb, |
| 177 | priv->offset, priv->len)) | 188 | priv->offset, priv->len)) |
| 178 | goto err; | 189 | goto err; |
| @@ -233,10 +233,9 @@ static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set, · 232 unmodified lines | |||
| 233 | rb_erase(&rbe->node, &priv->root); | 233 | rb_erase(&rbe->node, &priv->root); |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static int nft_rbtree_gc_elem(const struct nft_set *__set, | 236 | static const struct nft_rbtree_elem * |
| 237 | struct nft_rbtree *priv, | 237 | nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv, |
| 238 | struct nft_rbtree_elem *rbe, | 238 | struct nft_rbtree_elem *rbe, u8 genmask) |
| 239 | u8 genmask) | ||
| 240 | { | 239 | { |
| 241 | struct nft_set *set = (struct nft_set *)__set; | 240 | struct nft_set *set = (struct nft_set *)__set; |
| 242 | struct rb_node *prev = rb_prev(&rbe->node); | 241 | struct rb_node *prev = rb_prev(&rbe->node); |
| @@ -246,7 +245,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 3 unmodified lines | |||
| 246 | 245 | ||
| 247 | gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); | 246 | gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); |
| 248 | if (!gc) | 247 | if (!gc) |
| 249 | return -ENOMEM; | 248 | return ERR_PTR(-ENOMEM); |
| 250 | 249 | ||
| 251 | /* search for end interval coming before this element. | 250 | /* search for end interval coming before this element. |
| 252 | * end intervals don't carry a timeout extension, they | 251 | * end intervals don't carry a timeout extension, they |
| @@ -261,6 +260,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 8 unmodified lines | |||
| 261 | prev = rb_prev(prev); | 260 | prev = rb_prev(prev); |
| 262 | } | 261 | } |
| 263 | 262 | ||
| 263 | rbe_prev = NULL; | ||
| 264 | if (prev) { | 264 | if (prev) { |
| 265 | rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); | 265 | rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); |
| 266 | nft_rbtree_gc_remove(net, set, priv, rbe_prev); | 266 | nft_rbtree_gc_remove(net, set, priv, rbe_prev); |
| @@ -272,7 +272,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 5 unmodified lines | |||
| 272 | */ | 272 | */ |
| 273 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); | 273 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); |
| 274 | if (WARN_ON_ONCE(!gc)) | 274 | if (WARN_ON_ONCE(!gc)) |
| 275 | return -ENOMEM; | 275 | return ERR_PTR(-ENOMEM); |
| 276 | 276 | ||
| 277 | nft_trans_gc_elem_add(gc, rbe_prev); | 277 | nft_trans_gc_elem_add(gc, rbe_prev); |
| 278 | } | 278 | } |
| @@ -280,13 +280,13 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 1 unmodified line | |||
| 280 | nft_rbtree_gc_remove(net, set, priv, rbe); | 280 | nft_rbtree_gc_remove(net, set, priv, rbe); |
| 281 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); | 281 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); |
| 282 | if (WARN_ON_ONCE(!gc)) | 282 | if (WARN_ON_ONCE(!gc)) |
| 283 | return -ENOMEM; | 283 | return ERR_PTR(-ENOMEM); |
| 284 | 284 | ||
| 285 | nft_trans_gc_elem_add(gc, rbe); | 285 | nft_trans_gc_elem_add(gc, rbe); |
| 286 | 286 | ||
| 287 | nft_trans_gc_queue_sync_done(gc); | 287 | nft_trans_gc_queue_sync_done(gc); |
| 288 | 288 | ||
| 289 | return 0; | 289 | return rbe_prev; |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | static bool nft_rbtree_update_first(const struct nft_set *set, | 292 | static bool nft_rbtree_update_first(const struct nft_set *set, |
| @@ -314,7 +314,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 21 unmodified lines | |||
| 314 | struct nft_rbtree *priv = nft_set_priv(set); | 314 | struct nft_rbtree *priv = nft_set_priv(set); |
| 315 | u8 cur_genmask = nft_genmask_cur(net); | 315 | u8 cur_genmask = nft_genmask_cur(net); |
| 316 | u8 genmask = nft_genmask_next(net); | 316 | u8 genmask = nft_genmask_next(net); |
| 317 | int d, err; | 317 | int d; |
| 318 | 318 | ||
| 319 | /* Descend the tree to search for an existing element greater than the | 319 | /* Descend the tree to search for an existing element greater than the |
| 320 | * key value to insert that is greater than the new element. This is the | 320 | * key value to insert that is greater than the new element. This is the |
| @@ -363,9 +363,14 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 42 unmodified lines | |||
| 363 | */ | 363 | */ |
| 364 | if (nft_set_elem_expired(&rbe->ext) && | 364 | if (nft_set_elem_expired(&rbe->ext) && |
| 365 | nft_set_elem_active(&rbe->ext, cur_genmask)) { | 365 | nft_set_elem_active(&rbe->ext, cur_genmask)) { |
| 366 | err = nft_rbtree_gc_elem(set, priv, rbe, genmask); | 366 | const struct nft_rbtree_elem *removed_end; |
| 367 | if (err < 0) | 367 | |
| 368 | return err; | 368 | removed_end = nft_rbtree_gc_elem(set, priv, rbe, genmask); |
| 369 | if (IS_ERR(removed_end)) | ||
| 370 | return PTR_ERR(removed_end); | ||
| 371 | |||
| 372 | if (removed_end == rbe_le || removed_end == rbe_ge) | ||
| 373 | return -EAGAIN; | ||
| 369 | 374 | ||
| 370 | continue; | 375 | continue; |
| 371 | } | 376 | } |
| @@ -486,11 +491,18 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 114 unmodified lines | |||
| 486 | struct nft_rbtree_elem *rbe = elem->priv; | 491 | struct nft_rbtree_elem *rbe = elem->priv; |
| 487 | int err; | 492 | int err; |
| 488 | 493 | ||
| 489 | write_lock_bh(&priv->lock); | 494 | do { |
| 490 | write_seqcount_begin(&priv->count); | 495 | if (fatal_signal_pending(current)) |
| 491 | err = __nft_rbtree_insert(net, set, rbe, ext); | 496 | return -EINTR; |
| 492 | write_seqcount_end(&priv->count); | 497 | |
| 493 | write_unlock_bh(&priv->lock); | 498 | cond_resched(); |
| 499 | |||
| 500 | write_lock_bh(&priv->lock); | ||
| 501 | write_seqcount_begin(&priv->count); | ||
| 502 | err = __nft_rbtree_insert(net, set, rbe, ext); | ||
| 503 | write_seqcount_end(&priv->count); | ||
| 504 | write_unlock_bh(&priv->lock); | ||
| 505 | } while (err == -EAGAIN); | ||
| 494 | 506 | ||
| 495 | return err; | 507 | return err; |
| 496 | } | 508 | } |
| @@ -352,7 +352,7 @@ static void netlink_overrun(struct sock *sk) · 351 unmodified lines | |||
| 352 | if (!nlk_test_bit(RECV_NO_ENOBUFS, sk)) { | 352 | if (!nlk_test_bit(RECV_NO_ENOBUFS, sk)) { |
| 353 | if (!test_and_set_bit(NETLINK_S_CONGESTED, | 353 | if (!test_and_set_bit(NETLINK_S_CONGESTED, |
| 354 | &nlk_sk(sk)->state)) { | 354 | &nlk_sk(sk)->state)) { |
| 355 | sk->sk_err = ENOBUFS; | 355 | WRITE_ONCE(sk->sk_err, ENOBUFS); |
| 356 | sk_error_report(sk); | 356 | sk_error_report(sk); |
| 357 | } | 357 | } |
| 358 | } | 358 | } |
| @@ -1605,7 +1605,7 @@ static int do_one_set_err(struct sock *sk, struct netlink_set_err_data *p) · 1246 unmodified lines | |||
| 1605 | goto out; | 1605 | goto out; |
| 1606 | } | 1606 | } |
| 1607 | 1607 | ||
| 1608 | sk->sk_err = p->code; | 1608 | WRITE_ONCE(sk->sk_err, p->code); |
| 1609 | sk_error_report(sk); | 1609 | sk_error_report(sk); |
| 1610 | out: | 1610 | out: |
| 1611 | return ret; | 1611 | return ret; |
| @@ -1991,7 +1991,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, · 379 unmodified lines | |||
| 1991 | atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) { | 1991 | atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) { |
| 1992 | ret = netlink_dump(sk); | 1992 | ret = netlink_dump(sk); |
| 1993 | if (ret) { | 1993 | if (ret) { |
| 1994 | sk->sk_err = -ret; | 1994 | WRITE_ONCE(sk->sk_err, -ret); |
| 1995 | sk_error_report(sk); | 1995 | sk_error_report(sk); |
| 1996 | } | 1996 | } |
| 1997 | } | 1997 | } |
| @@ -2511,7 +2511,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, · 513 unmodified lines | |||
| 2511 | err_bad_put: | 2511 | err_bad_put: |
| 2512 | nlmsg_free(skb); | 2512 | nlmsg_free(skb); |
| 2513 | err_skb: | 2513 | err_skb: |
| 2514 | NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; | 2514 | WRITE_ONCE(NETLINK_CB(in_skb).sk->sk_err, ENOBUFS); |
| 2515 | sk_error_report(NETLINK_CB(in_skb).sk); | 2515 | sk_error_report(NETLINK_CB(in_skb).sk); |
| 2516 | } | 2516 | } |
| 2517 | EXPORT_SYMBOL(netlink_ack); | 2517 | EXPORT_SYMBOL(netlink_ack); |
| @@ -1636,7 +1636,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) · 1635 unmodified lines | |||
| 1636 | timer_setup(&local->sdreq_timer, nfc_llcp_sdreq_timer, 0); | 1636 | timer_setup(&local->sdreq_timer, nfc_llcp_sdreq_timer, 0); |
| 1637 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); | 1637 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); |
| 1638 | 1638 | ||
| 1639 | spin_lock(&llcp_devices_lock); | ||
| 1639 | list_add(&local->list, &llcp_devices); | 1640 | list_add(&local->list, &llcp_devices); |
| 1641 | spin_unlock(&llcp_devices_lock); | ||
| 1640 | 1642 | ||
| 1641 | return 0; | 1643 | return 0; |
| 1642 | } | 1644 | } |
| @@ -145,7 +145,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp) · 144 unmodified lines | |||
| 145 | addrlen = sizeof(sin); | 145 | addrlen = sizeof(sin); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | ret = sock->ops->bind(sock, addr, addrlen); | 148 | ret = kernel_bind(sock, addr, addrlen); |
| 149 | if (ret) { | 149 | if (ret) { |
| 150 | rdsdebug("bind failed with %d at address %pI6c\n", | 150 | rdsdebug("bind failed with %d at address %pI6c\n", |
| 151 | ret, &conn->c_laddr); | 151 | ret, &conn->c_laddr); |
| @@ -173,7 +173,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp) · 21 unmodified lines | |||
| 173 | * own the socket | 173 | * own the socket |
| 174 | */ | 174 | */ |
| 175 | rds_tcp_set_callbacks(sock, cp); | 175 | rds_tcp_set_callbacks(sock, cp); |
| 176 | ret = sock->ops->connect(sock, addr, addrlen, O_NONBLOCK); | 176 | ret = kernel_connect(sock, addr, addrlen, O_NONBLOCK); |
| 177 | 177 | ||
| 178 | rdsdebug("connect to address %pI6c returned %d\n", &conn->c_faddr, ret); | 178 | rdsdebug("connect to address %pI6c returned %d\n", &conn->c_faddr, ret); |
| 179 | if (ret == -EINPROGRESS) | 179 | if (ret == -EINPROGRESS) |
| @@ -306,7 +306,7 @@ struct socket *rds_tcp_listen_init(struct net *net, bool isv6) · 305 unmodified lines | |||
| 306 | addr_len = sizeof(*sin); | 306 | addr_len = sizeof(*sin); |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | ret = sock->ops->bind(sock, (struct sockaddr *)&ss, addr_len); | 309 | ret = kernel_bind(sock, (struct sockaddr *)&ss, addr_len); |
| 310 | if (ret < 0) { | 310 | if (ret < 0) { |
| 311 | rdsdebug("could not bind %s listener socket: %d\n", | 311 | rdsdebug("could not bind %s listener socket: %d\n", |
| 312 | isv6 ? "IPv6" : "IPv4", ret); | 312 | isv6 ? "IPv6" : "IPv4", ret); |
| @@ -48,6 +48,7 @@ struct rfkill { · 47 unmodified lines | |||
| 48 | bool persistent; | 48 | bool persistent; |
| 49 | bool polling_paused; | 49 | bool polling_paused; |
| 50 | bool suspended; | 50 | bool suspended; |
| 51 | bool need_sync; | ||
| 51 | 52 | ||
| 52 | const struct rfkill_ops *ops; | 53 | const struct rfkill_ops *ops; |
| 53 | void *data; | 54 | void *data; |
| @@ -368,6 +369,17 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) · 314 unmodified lines | |||
| 368 | rfkill_event(rfkill); | 369 | rfkill_event(rfkill); |
| 369 | } | 370 | } |
| 370 | 371 | ||
| 372 | static void rfkill_sync(struct rfkill *rfkill) | ||
| 373 | { | ||
| 374 | lockdep_assert_held(&rfkill_global_mutex); | ||
| 375 | |||
| 376 | if (!rfkill->need_sync) | ||
| 377 | return; | ||
| 378 | |||
| 379 | rfkill_set_block(rfkill, rfkill_global_states[rfkill->type].cur); | ||
| 380 | rfkill->need_sync = false; | ||
| 381 | } | ||
| 382 | |||
| 371 | static void rfkill_update_global_state(enum rfkill_type type, bool blocked) | 383 | static void rfkill_update_global_state(enum rfkill_type type, bool blocked) |
| 372 | { | 384 | { |
| 373 | int i; | 385 | int i; |
| @@ -730,6 +742,10 @@ static ssize_t soft_show(struct device *dev, struct device_attribute *attr, · 356 unmodified lines | |||
| 730 | { | 742 | { |
| 731 | struct rfkill *rfkill = to_rfkill(dev); | 743 | struct rfkill *rfkill = to_rfkill(dev); |
| 732 | 744 | ||
| 745 | mutex_lock(&rfkill_global_mutex); | ||
| 746 | rfkill_sync(rfkill); | ||
| 747 | mutex_unlock(&rfkill_global_mutex); | ||
| 748 | |||
| 733 | return sysfs_emit(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0); | 749 | return sysfs_emit(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0); |
| 734 | } | 750 | } |
| 735 | 751 | ||
| @@ -751,6 +767,7 @@ static ssize_t soft_store(struct device *dev, struct device_attribute *attr, · 15 unmodified lines | |||
| 751 | return -EINVAL; | 767 | return -EINVAL; |
| 752 | 768 | ||
| 753 | mutex_lock(&rfkill_global_mutex); | 769 | mutex_lock(&rfkill_global_mutex); |
| 770 | rfkill_sync(rfkill); | ||
| 754 | rfkill_set_block(rfkill, state); | 771 | rfkill_set_block(rfkill, state); |
| 755 | mutex_unlock(&rfkill_global_mutex); | 772 | mutex_unlock(&rfkill_global_mutex); |
| 756 | 773 | ||
| @@ -783,6 +800,10 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, · 26 unmodified lines | |||
| 783 | { | 800 | { |
| 784 | struct rfkill *rfkill = to_rfkill(dev); | 801 | struct rfkill *rfkill = to_rfkill(dev); |
| 785 | 802 | ||
| 803 | mutex_lock(&rfkill_global_mutex); | ||
| 804 | rfkill_sync(rfkill); | ||
| 805 | mutex_unlock(&rfkill_global_mutex); | ||
| 806 | |||
| 786 | return sysfs_emit(buf, "%d\n", user_state_from_blocked(rfkill->state)); | 807 | return sysfs_emit(buf, "%d\n", user_state_from_blocked(rfkill->state)); |
| 787 | } | 808 | } |
| 788 | 809 | ||
| @@ -805,6 +826,7 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, · 16 unmodified lines | |||
| 805 | return -EINVAL; | 826 | return -EINVAL; |
| 806 | 827 | ||
| 807 | mutex_lock(&rfkill_global_mutex); | 828 | mutex_lock(&rfkill_global_mutex); |
| 829 | rfkill_sync(rfkill); | ||
| 808 | rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED); | 830 | rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED); |
| 809 | mutex_unlock(&rfkill_global_mutex); | 831 | mutex_unlock(&rfkill_global_mutex); |
| 810 | 832 | ||
| @@ -1032,14 +1054,10 @@ static void rfkill_uevent_work(struct work_struct *work) · 221 unmodified lines | |||
| 1032 | 1054 | ||
| 1033 | static void rfkill_sync_work(struct work_struct *work) | 1055 | static void rfkill_sync_work(struct work_struct *work) |
| 1034 | { | 1056 | { |
| 1035 | struct rfkill *rfkill; | 1057 | struct rfkill *rfkill = container_of(work, struct rfkill, sync_work); |
| 1036 | bool cur; | ||
| 1037 | |||
| 1038 | rfkill = container_of(work, struct rfkill, sync_work); | ||
| 1039 | 1058 | ||
| 1040 | mutex_lock(&rfkill_global_mutex); | 1059 | mutex_lock(&rfkill_global_mutex); |
| 1041 | cur = rfkill_global_states[rfkill->type].cur; | 1060 | rfkill_sync(rfkill); |
| 1042 | rfkill_set_block(rfkill, cur); | ||
| 1043 | mutex_unlock(&rfkill_global_mutex); | 1061 | mutex_unlock(&rfkill_global_mutex); |
| 1044 | } | 1062 | } |
| 1045 | 1063 | ||
| @@ -1087,6 +1105,7 @@ int __must_check rfkill_register(struct rfkill *rfkill) · 41 unmodified lines | |||
| 1087 | round_jiffies_relative(POLL_INTERVAL)); | 1105 | round_jiffies_relative(POLL_INTERVAL)); |
| 1088 | 1106 | ||
| 1089 | if (!rfkill->persistent || rfkill_epo_lock_active) { | 1107 | if (!rfkill->persistent || rfkill_epo_lock_active) { |
| 1108 | rfkill->need_sync = true; | ||
| 1090 | schedule_work(&rfkill->sync_work); | 1109 | schedule_work(&rfkill->sync_work); |
| 1091 | } else { | 1110 | } else { |
| 1092 | #ifdef CONFIG_RFKILL_INPUT | 1111 | #ifdef CONFIG_RFKILL_INPUT |
| @@ -1171,6 +1190,7 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) · 78 unmodified lines | |||
| 1171 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); | 1190 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); |
| 1172 | if (!ev) | 1191 | if (!ev) |
| 1173 | goto free; | 1192 | goto free; |
| 1193 | rfkill_sync(rfkill); | ||
| 1174 | rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); | 1194 | rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); |
| 1175 | list_add_tail(&ev->list, &data->events); | 1195 | list_add_tail(&ev->list, &data->events); |
| 1176 | } | 1196 | } |
| @@ -1159,8 +1159,7 @@ int sctp_assoc_update(struct sctp_association *asoc, · 1158 unmodified lines | |||
| 1159 | /* Add any peer addresses from the new association. */ | 1159 | /* Add any peer addresses from the new association. */ |
| 1160 | list_for_each_entry(trans, &new->peer.transport_addr_list, | 1160 | list_for_each_entry(trans, &new->peer.transport_addr_list, |
| 1161 | transports) | 1161 | transports) |
| 1162 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr) && | 1162 | if (!sctp_assoc_add_peer(asoc, &trans->ipaddr, |
| 1163 | !sctp_assoc_add_peer(asoc, &trans->ipaddr, | ||
| 1164 | GFP_ATOMIC, trans->state)) | 1163 | GFP_ATOMIC, trans->state)) |
| 1165 | return -ENOMEM; | 1164 | return -ENOMEM; |
| 1166 | 1165 | ||
| @@ -2450,6 +2450,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, · 2449 unmodified lines | |||
| 2450 | if (trans) { | 2450 | if (trans) { |
| 2451 | trans->hbinterval = | 2451 | trans->hbinterval = |
| 2452 | msecs_to_jiffies(params->spp_hbinterval); | 2452 | msecs_to_jiffies(params->spp_hbinterval); |
| 2453 | sctp_transport_reset_hb_timer(trans); | ||
| 2453 | } else if (asoc) { | 2454 | } else if (asoc) { |
| 2454 | asoc->hbinterval = | 2455 | asoc->hbinterval = |
| 2455 | msecs_to_jiffies(params->spp_hbinterval); | 2456 | msecs_to_jiffies(params->spp_hbinterval); |
| @@ -737,6 +737,14 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) · 736 unmodified lines | |||
| 737 | return ret; | 737 | return ret; |
| 738 | } | 738 | } |
| 739 | 739 | ||
| 740 | static int __sock_sendmsg(struct socket *sock, struct msghdr *msg) | ||
| 741 | { | ||
| 742 | int err = security_socket_sendmsg(sock, msg, | ||
| 743 | msg_data_left(msg)); | ||
| 744 | |||
| 745 | return err ?: sock_sendmsg_nosec(sock, msg); | ||
| 746 | } | ||
| 747 | |||
| 740 | /** | 748 | /** |
| 741 | * sock_sendmsg - send a message through @sock | 749 | * sock_sendmsg - send a message through @sock |
| 742 | * @sock: socket | 750 | * @sock: socket |
| @@ -747,10 +755,19 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) · 4 unmodified lines | |||
| 747 | */ | 755 | */ |
| 748 | int sock_sendmsg(struct socket *sock, struct msghdr *msg) | 756 | int sock_sendmsg(struct socket *sock, struct msghdr *msg) |
| 749 | { | 757 | { |
| 750 | int err = security_socket_sendmsg(sock, msg, | 758 | struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name; |
| 751 | msg_data_left(msg)); | 759 | struct sockaddr_storage address; |
| 760 | int ret; | ||
| 752 | 761 | ||
| 753 | return err ?: sock_sendmsg_nosec(sock, msg); | 762 | if (msg->msg_name) { |
| 763 | memcpy(&address, msg->msg_name, msg->msg_namelen); | ||
| 764 | msg->msg_name = &address; | ||
| 765 | } | ||
| 766 | |||
| 767 | ret = __sock_sendmsg(sock, msg); | ||
| 768 | msg->msg_name = save_addr; | ||
| 769 | |||
| 770 | return ret; | ||
| 754 | } | 771 | } |
| 755 | EXPORT_SYMBOL(sock_sendmsg); | 772 | EXPORT_SYMBOL(sock_sendmsg); |
| 756 | 773 | ||
| @@ -1138,7 +1155,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) · 381 unmodified lines | |||
| 1138 | if (sock->type == SOCK_SEQPACKET) | 1155 | if (sock->type == SOCK_SEQPACKET) |
| 1139 | msg.msg_flags |= MSG_EOR; | 1156 | msg.msg_flags |= MSG_EOR; |
| 1140 | 1157 | ||
| 1141 | res = sock_sendmsg(sock, &msg); | 1158 | res = __sock_sendmsg(sock, &msg); |
| 1142 | *from = msg.msg_iter; | 1159 | *from = msg.msg_iter; |
| 1143 | return res; | 1160 | return res; |
| 1144 | } | 1161 | } |
| @@ -2174,7 +2191,7 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, · 1029 unmodified lines | |||
| 2174 | if (sock->file->f_flags & O_NONBLOCK) | 2191 | if (sock->file->f_flags & O_NONBLOCK) |
| 2175 | flags |= MSG_DONTWAIT; | 2192 | flags |= MSG_DONTWAIT; |
| 2176 | msg.msg_flags = flags; | 2193 | msg.msg_flags = flags; |
| 2177 | err = sock_sendmsg(sock, &msg); | 2194 | err = __sock_sendmsg(sock, &msg); |
| 2178 | 2195 | ||
| 2179 | out_put: | 2196 | out_put: |
| 2180 | fput_light(sock->file, fput_needed); | 2197 | fput_light(sock->file, fput_needed); |
| @@ -2538,7 +2555,7 @@ static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys, · 357 unmodified lines | |||
| 2538 | err = sock_sendmsg_nosec(sock, msg_sys); | 2555 | err = sock_sendmsg_nosec(sock, msg_sys); |
| 2539 | goto out_freectl; | 2556 | goto out_freectl; |
| 2540 | } | 2557 | } |
| 2541 | err = sock_sendmsg(sock, msg_sys); | 2558 | err = __sock_sendmsg(sock, msg_sys); |
| 2542 | /* | 2559 | /* |
| 2543 | * If this is sendmmsg() and sending to current destination address was | 2560 | * If this is sendmmsg() and sending to current destination address was |
| 2544 | * successful, remember it. | 2561 | * successful, remember it. |
| @@ -3499,7 +3516,12 @@ static long compat_sock_ioctl(struct file *file, unsigned int cmd, · 954 unmodified lines | |||
| 3499 | 3516 | ||
| 3500 | int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) | 3517 | int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) |
| 3501 | { | 3518 | { |
| 3502 | return READ_ONCE(sock->ops)->bind(sock, addr, addrlen); | 3519 | struct sockaddr_storage address; |
| 3520 | |||
| 3521 | memcpy(&address, addr, addrlen); | ||
| 3522 | |||
| 3523 | return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr *)&address, | ||
| 3524 | addrlen); | ||
| 3503 | } | 3525 | } |
| 3504 | EXPORT_SYMBOL(kernel_bind); | 3526 | EXPORT_SYMBOL(kernel_bind); |
| 3505 | 3527 | ||
| @@ -1441,14 +1441,14 @@ static int tipc_crypto_key_revoke(struct net *net, u8 tx_key) · 1440 unmodified lines | |||
| 1441 | struct tipc_crypto *tx = tipc_net(net)->crypto_tx; | 1441 | struct tipc_crypto *tx = tipc_net(net)->crypto_tx; |
| 1442 | struct tipc_key key; | 1442 | struct tipc_key key; |
| 1443 | 1443 | ||
| 1444 | spin_lock(&tx->lock); | 1444 | spin_lock_bh(&tx->lock); |
| 1445 | key = tx->key; | 1445 | key = tx->key; |
| 1446 | WARN_ON(!key.active || tx_key != key.active); | 1446 | WARN_ON(!key.active || tx_key != key.active); |
| 1447 | 1447 | ||
| 1448 | /* Free the active key */ | 1448 | /* Free the active key */ |
| 1449 | tipc_crypto_key_set_state(tx, key.passive, 0, key.pending); | 1449 | tipc_crypto_key_set_state(tx, key.passive, 0, key.pending); |
| 1450 | tipc_crypto_key_detach(tx->aead[key.active], &tx->lock); | 1450 | tipc_crypto_key_detach(tx->aead[key.active], &tx->lock); |
| 1451 | spin_unlock(&tx->lock); | 1451 | spin_unlock_bh(&tx->lock); |
| 1452 | 1452 | ||
| 1453 | pr_warn("%s: key is revoked\n", tx->name); | 1453 | pr_warn("%s: key is revoked\n", tx->name); |
| 1454 | return -EKEYREVOKED; | 1454 | return -EKEYREVOKED; |
| @@ -1181,16 +1181,11 @@ void wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked, · 1180 unmodified lines | |||
| 1181 | } | 1181 | } |
| 1182 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason); | 1182 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason); |
| 1183 | 1183 | ||
| 1184 | void cfg80211_cqm_config_free(struct wireless_dev *wdev) | ||
| 1185 | { | ||
| 1186 | kfree(wdev->cqm_config); | ||
| 1187 | wdev->cqm_config = NULL; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, | 1184 | static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, |
| 1191 | bool unregister_netdev) | 1185 | bool unregister_netdev) |
| 1192 | { | 1186 | { |
| 1193 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 1187 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
| 1188 | struct cfg80211_cqm_config *cqm_config; | ||
| 1194 | unsigned int link_id; | 1189 | unsigned int link_id; |
| 1195 | 1190 | ||
| 1196 | ASSERT_RTNL(); | 1191 | ASSERT_RTNL(); |
| @@ -1227,7 +1222,10 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, · 30 unmodified lines | |||
| 1227 | kfree_sensitive(wdev->wext.keys); | 1222 | kfree_sensitive(wdev->wext.keys); |
| 1228 | wdev->wext.keys = NULL; | 1223 | wdev->wext.keys = NULL; |
| 1229 | #endif | 1224 | #endif |
| 1230 | cfg80211_cqm_config_free(wdev); | 1225 | wiphy_work_cancel(wdev->wiphy, &wdev->cqm_rssi_work); |
| 1226 | /* deleted from the list, so can't be found from nl80211 any more */ | ||
| 1227 | cqm_config = rcu_access_pointer(wdev->cqm_config); | ||
| 1228 | kfree_rcu(cqm_config, rcu_head); | ||
| 1231 | 1229 | ||
| 1232 | /* | 1230 | /* |
| 1233 | * Ensure that all events have been processed and | 1231 | * Ensure that all events have been processed and |
| @@ -1379,6 +1377,8 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) · 145 unmodified lines | |||
| 1379 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 1377 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
| 1380 | #endif | 1378 | #endif |
| 1381 | 1379 | ||
| 1380 | wiphy_work_init(&wdev->cqm_rssi_work, cfg80211_cqm_rssi_notify_work); | ||
| 1381 | |||
| 1382 | if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) | 1382 | if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) |
| 1383 | wdev->ps = true; | 1383 | wdev->ps = true; |
| 1384 | else | 1384 | else |
| @@ -295,12 +295,17 @@ struct cfg80211_beacon_registration { · 294 unmodified lines | |||
| 295 | }; | 295 | }; |
| 296 | 296 | ||
| 297 | struct cfg80211_cqm_config { | 297 | struct cfg80211_cqm_config { |
| 298 | struct rcu_head rcu_head; | ||
| 298 | u32 rssi_hyst; | 299 | u32 rssi_hyst; |
| 299 | s32 last_rssi_event_value; | 300 | s32 last_rssi_event_value; |
| 301 | enum nl80211_cqm_rssi_threshold_event last_rssi_event_type; | ||
| 300 | int n_rssi_thresholds; | 302 | int n_rssi_thresholds; |
| 301 | s32 rssi_thresholds[] __counted_by(n_rssi_thresholds); | 303 | s32 rssi_thresholds[] __counted_by(n_rssi_thresholds); |
| 302 | }; | 304 | }; |
| 303 | 305 | ||
| 306 | void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, | ||
| 307 | struct wiphy_work *work); | ||
| 308 | |||
| 304 | void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev); | 309 | void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev); |
| 305 | 310 | ||
| 306 | /* free object */ | 311 | /* free object */ |
| @@ -566,8 +571,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, · 259 unmodified lines | |||
| 566 | #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) | 571 | #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) |
| 567 | #endif | 572 | #endif |
| 568 | 573 | ||
| 569 | void cfg80211_cqm_config_free(struct wireless_dev *wdev); | ||
| 570 | |||
| 571 | void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); | 574 | void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); |
| 572 | void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); | 575 | void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); |
| 573 | void cfg80211_pmsr_free_wk(struct work_struct *work); | 576 | void cfg80211_pmsr_free_wk(struct work_struct *work); |
| @@ -52,7 +52,8 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, · 51 unmodified lines | |||
| 52 | cr.links[link_id].bssid = data->links[link_id].bss->bssid; | 52 | cr.links[link_id].bssid = data->links[link_id].bss->bssid; |
| 53 | cr.links[link_id].addr = data->links[link_id].addr; | 53 | cr.links[link_id].addr = data->links[link_id].addr; |
| 54 | /* need to have local link addresses for MLO connections */ | 54 | /* need to have local link addresses for MLO connections */ |
| 55 | WARN_ON(cr.ap_mld_addr && !cr.links[link_id].addr); | 55 | WARN_ON(cr.ap_mld_addr && |
| 56 | !is_valid_ether_addr(cr.links[link_id].addr)); | ||
| 56 | 57 | ||
| 57 | BUG_ON(!cr.links[link_id].bss->channel); | 58 | BUG_ON(!cr.links[link_id].bss->channel); |
| 58 | 59 | ||
| @@ -5909,6 +5909,21 @@ out: · 5908 unmodified lines | |||
| 5909 | nlmsg_free(msg); | 5909 | nlmsg_free(msg); |
| 5910 | } | 5910 | } |
| 5911 | 5911 | ||
| 5912 | static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params) | ||
| 5913 | { | ||
| 5914 | struct ieee80211_channel *channel = params->chandef.chan; | ||
| 5915 | |||
| 5916 | if ((params->he_cap || params->he_oper) && | ||
| 5917 | (channel->flags & IEEE80211_CHAN_NO_HE)) | ||
| 5918 | return -EOPNOTSUPP; | ||
| 5919 | |||
| 5920 | if ((params->eht_cap || params->eht_oper) && | ||
| 5921 | (channel->flags & IEEE80211_CHAN_NO_EHT)) | ||
| 5922 | return -EOPNOTSUPP; | ||
| 5923 | |||
| 5924 | return 0; | ||
| 5925 | } | ||
| 5926 | |||
| 5912 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | 5927 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) |
| 5913 | { | 5928 | { |
| 5914 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5929 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| @@ -6178,6 +6193,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 263 unmodified lines | |||
| 6178 | if (err) | 6193 | if (err) |
| 6179 | goto out_unlock; | 6194 | goto out_unlock; |
| 6180 | 6195 | ||
| 6196 | err = nl80211_validate_ap_phy_operation(params); | ||
| 6197 | if (err) | ||
| 6198 | goto out_unlock; | ||
| 6199 | |||
| 6181 | if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]) | 6200 | if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]) |
| 6182 | params->flags = nla_get_u32( | 6201 | params->flags = nla_get_u32( |
| 6183 | info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]); | 6202 | info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]); |
| @@ -8482,7 +8501,7 @@ static int nl80211_update_mesh_config(struct sk_buff *skb, · 2298 unmodified lines | |||
| 8482 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 8501 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 8483 | struct net_device *dev = info->user_ptr[1]; | 8502 | struct net_device *dev = info->user_ptr[1]; |
| 8484 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 8503 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 8485 | struct mesh_config cfg; | 8504 | struct mesh_config cfg = {}; |
| 8486 | u32 mask; | 8505 | u32 mask; |
| 8487 | int err; | 8506 | int err; |
| 8488 | 8507 | ||
| @@ -12796,7 +12815,8 @@ static int nl80211_set_cqm_txe(struct genl_info *info, · 4307 unmodified lines | |||
| 12796 | } | 12815 | } |
| 12797 | 12816 | ||
| 12798 | static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, | 12817 | static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, |
| 12799 | struct net_device *dev) | 12818 | struct net_device *dev, |
| 12819 | struct cfg80211_cqm_config *cqm_config) | ||
| 12800 | { | 12820 | { |
| 12801 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 12821 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 12802 | s32 last, low, high; | 12822 | s32 last, low, high; |
| @@ -12805,7 +12825,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 2 unmodified lines | |||
| 12805 | int err; | 12825 | int err; |
| 12806 | 12826 | ||
| 12807 | /* RSSI reporting disabled? */ | 12827 | /* RSSI reporting disabled? */ |
| 12808 | if (!wdev->cqm_config) | 12828 | if (!cqm_config) |
| 12809 | return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0); | 12829 | return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0); |
| 12810 | 12830 | ||
| 12811 | /* | 12831 | /* |
| @@ -12814,7 +12834,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 2 unmodified lines | |||
| 12814 | * connection is established and enough beacons received to calculate | 12834 | * connection is established and enough beacons received to calculate |
| 12815 | * the average. | 12835 | * the average. |
| 12816 | */ | 12836 | */ |
| 12817 | if (!wdev->cqm_config->last_rssi_event_value && | 12837 | if (!cqm_config->last_rssi_event_value && |
| 12818 | wdev->links[0].client.current_bss && | 12838 | wdev->links[0].client.current_bss && |
| 12819 | rdev->ops->get_station) { | 12839 | rdev->ops->get_station) { |
| 12820 | struct station_info sinfo = {}; | 12840 | struct station_info sinfo = {}; |
| @@ -12828,30 +12848,30 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 7 unmodified lines | |||
| 12828 | 12848 | ||
| 12829 | cfg80211_sinfo_release_content(&sinfo); | 12849 | cfg80211_sinfo_release_content(&sinfo); |
| 12830 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) | 12850 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) |
| 12831 | wdev->cqm_config->last_rssi_event_value = | 12851 | cqm_config->last_rssi_event_value = |
| 12832 | (s8) sinfo.rx_beacon_signal_avg; | 12852 | (s8) sinfo.rx_beacon_signal_avg; |
| 12833 | } | 12853 | } |
| 12834 | 12854 | ||
| 12835 | last = wdev->cqm_config->last_rssi_event_value; | 12855 | last = cqm_config->last_rssi_event_value; |
| 12836 | hyst = wdev->cqm_config->rssi_hyst; | 12856 | hyst = cqm_config->rssi_hyst; |
| 12837 | n = wdev->cqm_config->n_rssi_thresholds; | 12857 | n = cqm_config->n_rssi_thresholds; |
| 12838 | 12858 | ||
| 12839 | for (i = 0; i < n; i++) { | 12859 | for (i = 0; i < n; i++) { |
| 12840 | i = array_index_nospec(i, n); | 12860 | i = array_index_nospec(i, n); |
| 12841 | if (last < wdev->cqm_config->rssi_thresholds[i]) | 12861 | if (last < cqm_config->rssi_thresholds[i]) |
| 12842 | break; | 12862 | break; |
| 12843 | } | 12863 | } |
| 12844 | 12864 | ||
| 12845 | low_index = i - 1; | 12865 | low_index = i - 1; |
| 12846 | if (low_index >= 0) { | 12866 | if (low_index >= 0) { |
| 12847 | low_index = array_index_nospec(low_index, n); | 12867 | low_index = array_index_nospec(low_index, n); |
| 12848 | low = wdev->cqm_config->rssi_thresholds[low_index] - hyst; | 12868 | low = cqm_config->rssi_thresholds[low_index] - hyst; |
| 12849 | } else { | 12869 | } else { |
| 12850 | low = S32_MIN; | 12870 | low = S32_MIN; |
| 12851 | } | 12871 | } |
| 12852 | if (i < n) { | 12872 | if (i < n) { |
| 12853 | i = array_index_nospec(i, n); | 12873 | i = array_index_nospec(i, n); |
| 12854 | high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1; | 12874 | high = cqm_config->rssi_thresholds[i] + hyst - 1; |
| 12855 | } else { | 12875 | } else { |
| 12856 | high = S32_MAX; | 12876 | high = S32_MAX; |
| 12857 | } | 12877 | } |
| @@ -12864,6 +12884,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 6 unmodified lines | |||
| 12864 | u32 hysteresis) | 12884 | u32 hysteresis) |
| 12865 | { | 12885 | { |
| 12866 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 12886 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 12887 | struct cfg80211_cqm_config *cqm_config = NULL, *old; | ||
| 12867 | struct net_device *dev = info->user_ptr[1]; | 12888 | struct net_device *dev = info->user_ptr[1]; |
| 12868 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 12889 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 12869 | int i, err; | 12890 | int i, err; |
| @@ -12881,10 +12902,6 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 11 unmodified lines | |||
| 12881 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) | 12902 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) |
| 12882 | return -EOPNOTSUPP; | 12903 | return -EOPNOTSUPP; |
| 12883 | 12904 | ||
| 12884 | wdev_lock(wdev); | ||
| 12885 | cfg80211_cqm_config_free(wdev); | ||
| 12886 | wdev_unlock(wdev); | ||
| 12887 | |||
| 12888 | if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) { | 12905 | if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) { |
| 12889 | if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */ | 12906 | if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */ |
| 12890 | return rdev_set_cqm_rssi_config(rdev, dev, 0, 0); | 12907 | return rdev_set_cqm_rssi_config(rdev, dev, 0, 0); |
| @@ -12901,9 +12918,10 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 10 unmodified lines | |||
| 12901 | n_thresholds = 0; | 12918 | n_thresholds = 0; |
| 12902 | 12919 | ||
| 12903 | wdev_lock(wdev); | 12920 | wdev_lock(wdev); |
| 12904 | if (n_thresholds) { | 12921 | old = rcu_dereference_protected(wdev->cqm_config, |
| 12905 | struct cfg80211_cqm_config *cqm_config; | 12922 | lockdep_is_held(&wdev->mtx)); |
| 12906 | 12923 | ||
| 12924 | if (n_thresholds) { | ||
| 12907 | cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds, | 12925 | cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds, |
| 12908 | n_thresholds), | 12926 | n_thresholds), |
| 12909 | GFP_KERNEL); | 12927 | GFP_KERNEL); |
| @@ -12918,11 +12936,18 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 8 unmodified lines | |||
| 12918 | flex_array_size(cqm_config, rssi_thresholds, | 12936 | flex_array_size(cqm_config, rssi_thresholds, |
| 12919 | n_thresholds)); | 12937 | n_thresholds)); |
| 12920 | 12938 | ||
| 12921 | wdev->cqm_config = cqm_config; | 12939 | rcu_assign_pointer(wdev->cqm_config, cqm_config); |
| 12940 | } else { | ||
| 12941 | RCU_INIT_POINTER(wdev->cqm_config, NULL); | ||
| 12922 | } | 12942 | } |
| 12923 | 12943 | ||
| 12924 | err = cfg80211_cqm_rssi_update(rdev, dev); | 12944 | err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config); |
| 12925 | 12945 | if (err) { | |
| 12946 | rcu_assign_pointer(wdev->cqm_config, old); | ||
| 12947 | kfree_rcu(cqm_config, rcu_head); | ||
| 12948 | } else { | ||
| 12949 | kfree_rcu(old, rcu_head); | ||
| 12950 | } | ||
| 12926 | unlock: | 12951 | unlock: |
| 12927 | wdev_unlock(wdev); | 12952 | wdev_unlock(wdev); |
| 12928 | 12953 | ||
| @@ -19073,9 +19098,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 6144 unmodified lines | |||
| 19073 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 19098 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
| 19074 | s32 rssi_level, gfp_t gfp) | 19099 | s32 rssi_level, gfp_t gfp) |
| 19075 | { | 19100 | { |
| 19076 | struct sk_buff *msg; | ||
| 19077 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 19101 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 19078 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 19102 | struct cfg80211_cqm_config *cqm_config; |
| 19079 | 19103 | ||
| 19080 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level); | 19104 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level); |
| 19081 | 19105 | ||
| @@ -19083,18 +19107,41 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 1 unmodified line | |||
| 19083 | rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) | 19107 | rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) |
| 19084 | return; | 19108 | return; |
| 19085 | 19109 | ||
| 19086 | if (wdev->cqm_config) { | 19110 | rcu_read_lock(); |
| 19087 | wdev->cqm_config->last_rssi_event_value = rssi_level; | 19111 | cqm_config = rcu_dereference(wdev->cqm_config); |
| 19112 | if (cqm_config) { | ||
| 19113 | cqm_config->last_rssi_event_value = rssi_level; | ||
| 19114 | cqm_config->last_rssi_event_type = rssi_event; | ||
| 19115 | wiphy_work_queue(wdev->wiphy, &wdev->cqm_rssi_work); | ||
| 19116 | } | ||
| 19117 | rcu_read_unlock(); | ||
| 19118 | } | ||
| 19119 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
| 19088 | 19120 | ||
| 19089 | cfg80211_cqm_rssi_update(rdev, dev); | 19121 | void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work) |
| 19122 | { | ||
| 19123 | struct wireless_dev *wdev = container_of(work, struct wireless_dev, | ||
| 19124 | cqm_rssi_work); | ||
| 19125 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | ||
| 19126 | enum nl80211_cqm_rssi_threshold_event rssi_event; | ||
| 19127 | struct cfg80211_cqm_config *cqm_config; | ||
| 19128 | struct sk_buff *msg; | ||
| 19129 | s32 rssi_level; | ||
| 19090 | 19130 | ||
| 19091 | if (rssi_level == 0) | 19131 | wdev_lock(wdev); |
| 19092 | rssi_level = wdev->cqm_config->last_rssi_event_value; | 19132 | cqm_config = rcu_dereference_protected(wdev->cqm_config, |
| 19093 | } | 19133 | lockdep_is_held(&wdev->mtx)); |
| 19134 | if (!wdev->cqm_config) | ||
| 19135 | goto unlock; | ||
| 19094 | 19136 | ||
| 19095 | msg = cfg80211_prepare_cqm(dev, NULL, gfp); | 19137 | cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config); |
| 19138 | |||
| 19139 | rssi_level = cqm_config->last_rssi_event_value; | ||
| 19140 | rssi_event = cqm_config->last_rssi_event_type; | ||
| 19141 | |||
| 19142 | msg = cfg80211_prepare_cqm(wdev->netdev, NULL, GFP_KERNEL); | ||
| 19096 | if (!msg) | 19143 | if (!msg) |
| 19097 | return; | 19144 | goto unlock; |
| 19098 | 19145 | ||
| 19099 | if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, | 19146 | if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, |
| 19100 | rssi_event)) | 19147 | rssi_event)) |
| @@ -19104,14 +19151,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 3 unmodified lines | |||
| 19104 | rssi_level)) | 19151 | rssi_level)) |
| 19105 | goto nla_put_failure; | 19152 | goto nla_put_failure; |
| 19106 | 19153 | ||
| 19107 | cfg80211_send_cqm(msg, gfp); | 19154 | cfg80211_send_cqm(msg, GFP_KERNEL); |
| 19108 | 19155 | ||
| 19109 | return; | 19156 | goto unlock; |
| 19110 | 19157 | ||
| 19111 | nla_put_failure: | 19158 | nla_put_failure: |
| 19112 | nlmsg_free(msg); | 19159 | nlmsg_free(msg); |
| 19160 | unlock: | ||
| 19161 | wdev_unlock(wdev); | ||
| 19113 | } | 19162 | } |
| 19114 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
| 19115 | 19163 | ||
| 19116 | void cfg80211_cqm_txe_notify(struct net_device *dev, | 19164 | void cfg80211_cqm_txe_notify(struct net_device *dev, |
| 19117 | const u8 *peer, u32 num_packets, | 19165 | const u8 *peer, u32 num_packets, |
| @@ -908,6 +908,10 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev) · 907 unmodified lines | |||
| 908 | !cfg80211_find_ssid_match(ap, request)) | 908 | !cfg80211_find_ssid_match(ap, request)) |
| 909 | continue; | 909 | continue; |
| 910 | 910 | ||
| 911 | if (!is_broadcast_ether_addr(request->bssid) && | ||
| 912 | !ether_addr_equal(request->bssid, ap->bssid)) | ||
| 913 | continue; | ||
| 914 | |||
| 911 | if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid) | 915 | if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid) |
| 912 | continue; | 916 | continue; |
| 913 | 917 | ||
| @@ -185,6 +185,8 @@ static void test_cubic(void) · 184 unmodified lines | |||
| 185 | 185 | ||
| 186 | do_test("bpf_cubic", NULL); | 186 | do_test("bpf_cubic", NULL); |
| 187 | 187 | ||
| 188 | ASSERT_EQ(cubic_skel->bss->bpf_cubic_acked_called, 1, "pkts_acked called"); | ||
| 189 | |||
| 188 | bpf_link__destroy(link); | 190 | bpf_link__destroy(link); |
| 189 | bpf_cubic__destroy(cubic_skel); | 191 | bpf_cubic__destroy(cubic_skel); |
| 190 | } | 192 | } |
| @@ -475,6 +475,55 @@ out: · 474 unmodified lines | |||
| 475 | test_sockmap_drop_prog__destroy(drop); | 475 | test_sockmap_drop_prog__destroy(drop); |
| 476 | } | 476 | } |
| 477 | 477 | ||
| 478 | static void test_sockmap_skb_verdict_peek(void) | ||
| 479 | { | ||
| 480 | int err, map, verdict, s, c1, p1, zero = 0, sent, recvd, avail; | ||
| 481 | struct test_sockmap_pass_prog *pass; | ||
| 482 | char snd[256] = "0123456789"; | ||
| 483 | char rcv[256] = "0"; | ||
| 484 | |||
| 485 | pass = test_sockmap_pass_prog__open_and_load(); | ||
| 486 | if (!ASSERT_OK_PTR(pass, "open_and_load")) | ||
| 487 | return; | ||
| 488 | verdict = bpf_program__fd(pass->progs.prog_skb_verdict); | ||
| 489 | map = bpf_map__fd(pass->maps.sock_map_rx); | ||
| 490 | |||
| 491 | err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0); | ||
| 492 | if (!ASSERT_OK(err, "bpf_prog_attach")) | ||
| 493 | goto out; | ||
| 494 | |||
| 495 | s = socket_loopback(AF_INET, SOCK_STREAM); | ||
| 496 | if (!ASSERT_GT(s, -1, "socket_loopback(s)")) | ||
| 497 | goto out; | ||
| 498 | |||
| 499 | err = create_pair(s, AF_INET, SOCK_STREAM, &c1, &p1); | ||
| 500 | if (!ASSERT_OK(err, "create_pairs(s)")) | ||
| 501 | goto out; | ||
| 502 | |||
| 503 | err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST); | ||
| 504 | if (!ASSERT_OK(err, "bpf_map_update_elem(c1)")) | ||
| 505 | goto out_close; | ||
| 506 | |||
| 507 | sent = xsend(p1, snd, sizeof(snd), 0); | ||
| 508 | ASSERT_EQ(sent, sizeof(snd), "xsend(p1)"); | ||
| 509 | recvd = recv(c1, rcv, sizeof(rcv), MSG_PEEK); | ||
| 510 | ASSERT_EQ(recvd, sizeof(rcv), "recv(c1)"); | ||
| 511 | err = ioctl(c1, FIONREAD, &avail); | ||
| 512 | ASSERT_OK(err, "ioctl(FIONREAD) error"); | ||
| 513 | ASSERT_EQ(avail, sizeof(snd), "after peek ioctl(FIONREAD)"); | ||
| 514 | recvd = recv(c1, rcv, sizeof(rcv), 0); | ||
| 515 | ASSERT_EQ(recvd, sizeof(rcv), "recv(p0)"); | ||
| 516 | err = ioctl(c1, FIONREAD, &avail); | ||
| 517 | ASSERT_OK(err, "ioctl(FIONREAD) error"); | ||
| 518 | ASSERT_EQ(avail, 0, "after read ioctl(FIONREAD)"); | ||
| 519 | |||
| 520 | out_close: | ||
| 521 | close(c1); | ||
| 522 | close(p1); | ||
| 523 | out: | ||
| 524 | test_sockmap_pass_prog__destroy(pass); | ||
| 525 | } | ||
| 526 | |||
| 478 | void test_sockmap_basic(void) | 527 | void test_sockmap_basic(void) |
| 479 | { | 528 | { |
| 480 | if (test__start_subtest("sockmap create_update_free")) | 529 | if (test__start_subtest("sockmap create_update_free")) |
| @@ -515,4 +564,6 @@ void test_sockmap_basic(void) · 34 unmodified lines | |||
| 515 | test_sockmap_skb_verdict_fionread(true); | 564 | test_sockmap_skb_verdict_fionread(true); |
| 516 | if (test__start_subtest("sockmap skb_verdict fionread on drop")) | 565 | if (test__start_subtest("sockmap skb_verdict fionread on drop")) |
| 517 | test_sockmap_skb_verdict_fionread(false); | 566 | test_sockmap_skb_verdict_fionread(false); |
| 567 | if (test__start_subtest("sockmap skb_verdict msg_f_peek")) | ||
| 568 | test_sockmap_skb_verdict_peek(); | ||
| 518 | } | 569 | } |
| @@ -2378,3 +2378,87 @@ void serial_test_tc_opts_chain_mixed(void) · 2377 unmodified lines | |||
| 2378 | test_tc_chain_mixed(BPF_TCX_INGRESS); | 2378 | test_tc_chain_mixed(BPF_TCX_INGRESS); |
| 2379 | test_tc_chain_mixed(BPF_TCX_EGRESS); | 2379 | test_tc_chain_mixed(BPF_TCX_EGRESS); |
| 2380 | } | 2380 | } |
| 2381 | |||
| 2382 | static int generate_dummy_prog(void) | ||
| 2383 | { | ||
| 2384 | const struct bpf_insn prog_insns[] = { | ||
| 2385 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
| 2386 | BPF_EXIT_INSN(), | ||
| 2387 | }; | ||
| 2388 | const size_t prog_insn_cnt = sizeof(prog_insns) / sizeof(struct bpf_insn); | ||
| 2389 | LIBBPF_OPTS(bpf_prog_load_opts, opts); | ||
| 2390 | const size_t log_buf_sz = 256; | ||
| 2391 | char *log_buf; | ||
| 2392 | int fd = -1; | ||
| 2393 | |||
| 2394 | log_buf = malloc(log_buf_sz); | ||
| 2395 | if (!ASSERT_OK_PTR(log_buf, "log_buf_alloc")) | ||
| 2396 | return fd; | ||
| 2397 | opts.log_buf = log_buf; | ||
| 2398 | opts.log_size = log_buf_sz; | ||
| 2399 | |||
| 2400 | log_buf[0] = '\0'; | ||
| 2401 | opts.log_level = 0; | ||
| 2402 | fd = bpf_prog_load(BPF_PROG_TYPE_SCHED_CLS, "tcx_prog", "GPL", | ||
| 2403 | prog_insns, prog_insn_cnt, &opts); | ||
| 2404 | ASSERT_STREQ(log_buf, "", "log_0"); | ||
| 2405 | ASSERT_GE(fd, 0, "prog_fd"); | ||
| 2406 | free(log_buf); | ||
| 2407 | return fd; | ||
| 2408 | } | ||
| 2409 | |||
| 2410 | static void test_tc_opts_max_target(int target, int flags, bool relative) | ||
| 2411 | { | ||
| 2412 | int err, ifindex, i, prog_fd, last_fd = -1; | ||
| 2413 | LIBBPF_OPTS(bpf_prog_attach_opts, opta); | ||
| 2414 | const int max_progs = 63; | ||
| 2415 | |||
| 2416 | ASSERT_OK(system("ip link add dev tcx_opts1 type veth peer name tcx_opts2"), "add veth"); | ||
| 2417 | ifindex = if_nametoindex("tcx_opts1"); | ||
| 2418 | ASSERT_NEQ(ifindex, 0, "non_zero_ifindex"); | ||
| 2419 | |||
| 2420 | assert_mprog_count_ifindex(ifindex, target, 0); | ||
| 2421 | |||
| 2422 | for (i = 0; i < max_progs; i++) { | ||
| 2423 | prog_fd = generate_dummy_prog(); | ||
| 2424 | if (!ASSERT_GE(prog_fd, 0, "dummy_prog")) | ||
| 2425 | goto cleanup; | ||
| 2426 | err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta); | ||
| 2427 | if (!ASSERT_EQ(err, 0, "prog_attach")) | ||
| 2428 | goto cleanup; | ||
| 2429 | assert_mprog_count_ifindex(ifindex, target, i + 1); | ||
| 2430 | if (i == max_progs - 1 && relative) | ||
| 2431 | last_fd = prog_fd; | ||
| 2432 | else | ||
| 2433 | close(prog_fd); | ||
| 2434 | } | ||
| 2435 | |||
| 2436 | prog_fd = generate_dummy_prog(); | ||
| 2437 | if (!ASSERT_GE(prog_fd, 0, "dummy_prog")) | ||
| 2438 | goto cleanup; | ||
| 2439 | opta.flags = flags; | ||
| 2440 | if (last_fd > 0) | ||
| 2441 | opta.relative_fd = last_fd; | ||
| 2442 | err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta); | ||
| 2443 | ASSERT_EQ(err, -ERANGE, "prog_64_attach"); | ||
| 2444 | assert_mprog_count_ifindex(ifindex, target, max_progs); | ||
| 2445 | close(prog_fd); | ||
| 2446 | cleanup: | ||
| 2447 | if (last_fd > 0) | ||
| 2448 | close(last_fd); | ||
| 2449 | ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth"); | ||
| 2450 | ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed"); | ||
| 2451 | ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); | ||
| 2452 | } | ||
| 2453 | |||
| 2454 | void serial_test_tc_opts_max(void) | ||
| 2455 | { | ||
| 2456 | test_tc_opts_max_target(BPF_TCX_INGRESS, 0, false); | ||
| 2457 | test_tc_opts_max_target(BPF_TCX_EGRESS, 0, false); | ||
| 2458 | |||
| 2459 | test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_BEFORE, false); | ||
| 2460 | test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_BEFORE, true); | ||
| 2461 | |||
| 2462 | test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_AFTER, true); | ||
| 2463 | test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_AFTER, false); | ||
| 2464 | } | ||
| @@ -490,6 +490,8 @@ static __always_inline void hystart_update(struct sock *sk, __u32 delay) · 489 unmodified lines | |||
| 490 | } | 490 | } |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | int bpf_cubic_acked_called = 0; | ||
| 494 | |||
| 493 | void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk, | 495 | void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk, |
| 494 | const struct ack_sample *sample) | 496 | const struct ack_sample *sample) |
| 495 | { | 497 | { |
| @@ -497,6 +499,7 @@ void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk, · 1 unmodified line | |||
| 497 | struct bictcp *ca = inet_csk_ca(sk); | 499 | struct bictcp *ca = inet_csk_ca(sk); |
| 498 | __u32 delay; | 500 | __u32 delay; |
| 499 | 501 | ||
| 502 | bpf_cubic_acked_called = 1; | ||
| 500 | /* Some calls are for duplicates without timetamps */ | 503 | /* Some calls are for duplicates without timetamps */ |
| 501 | if (sample->rtt_us < 0) | 504 | if (sample->rtt_us < 0) |
| 502 | return; | 505 | return; |
| @@ -6,13 +6,14 @@ TEST_PROGS := nft_trans_stress.sh nft_fib.sh nft_nat.sh bridge_brouter.sh \ · 5 unmodified lines | |||
| 6 | nft_concat_range.sh nft_conntrack_helper.sh \ | 6 | nft_concat_range.sh nft_conntrack_helper.sh \ |
| 7 | nft_queue.sh nft_meta.sh nf_nat_edemux.sh \ | 7 | nft_queue.sh nft_meta.sh nf_nat_edemux.sh \ |
| 8 | ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \ | 8 | ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \ |
| 9 | conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh | 9 | conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh \ |
| 10 | conntrack_sctp_collision.sh | ||
| 10 | 11 | ||
| 11 | HOSTPKG_CONFIG := pkg-config | 12 | HOSTPKG_CONFIG := pkg-config |
| 12 | 13 | ||
| 13 | CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null) | 14 | CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null) |
| 14 | LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl) | 15 | LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl) |
| 15 | 16 | ||
| 16 | TEST_GEN_FILES = nf-queue connect_close audit_logread | 17 | TEST_GEN_FILES = nf-queue connect_close audit_logread sctp_collision |
| 17 | 18 | ||
| 18 | include ../lib.mk | 19 | include ../lib.mk |
| @@ -0,0 +1,89 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | # SPDX-License-Identifier: GPL-2.0 | ||
| 3 | # | ||
| 4 | # Testing For SCTP COLLISION SCENARIO as Below: | ||
| 5 | # | ||
| 6 | # 14:35:47.655279 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT] [init tag: 2017837359] | ||
| 7 | # 14:35:48.353250 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT] [init tag: 1187206187] | ||
| 8 | # 14:35:48.353275 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT ACK] [init tag: 2017837359] | ||
| 9 | # 14:35:48.353283 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [COOKIE ECHO] | ||
| 10 | # 14:35:48.353977 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [COOKIE ACK] | ||
| 11 | # 14:35:48.855335 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT ACK] [init tag: 164579970] | ||
| 12 | # | ||
| 13 | # TOPO: SERVER_NS (link0)<--->(link1) ROUTER_NS (link2)<--->(link3) CLIENT_NS | ||
| 14 | |||
| 15 | CLIENT_NS=$(mktemp -u client-XXXXXXXX) | ||
| 16 | CLIENT_IP="198.51.200.1" | ||
| 17 | CLIENT_PORT=1234 | ||
| 18 | |||
| 19 | SERVER_NS=$(mktemp -u server-XXXXXXXX) | ||
| 20 | SERVER_IP="198.51.100.1" | ||
| 21 | SERVER_PORT=1234 | ||
| 22 | |||
| 23 | ROUTER_NS=$(mktemp -u router-XXXXXXXX) | ||
| 24 | CLIENT_GW="198.51.200.2" | ||
| 25 | SERVER_GW="198.51.100.2" | ||
| 26 | |||
| 27 | # setup the topo | ||
| 28 | setup() { | ||
| 29 | ip net add $CLIENT_NS | ||
| 30 | ip net add $SERVER_NS | ||
| 31 | ip net add $ROUTER_NS | ||
| 32 | ip -n $SERVER_NS link add link0 type veth peer name link1 netns $ROUTER_NS | ||
| 33 | ip -n $CLIENT_NS link add link3 type veth peer name link2 netns $ROUTER_NS | ||
| 34 | |||
| 35 | ip -n $SERVER_NS link set link0 up | ||
| 36 | ip -n $SERVER_NS addr add $SERVER_IP/24 dev link0 | ||
| 37 | ip -n $SERVER_NS route add $CLIENT_IP dev link0 via $SERVER_GW | ||
| 38 | |||
| 39 | ip -n $ROUTER_NS link set link1 up | ||
| 40 | ip -n $ROUTER_NS link set link2 up | ||
| 41 | ip -n $ROUTER_NS addr add $SERVER_GW/24 dev link1 | ||
| 42 | ip -n $ROUTER_NS addr add $CLIENT_GW/24 dev link2 | ||
| 43 | ip net exec $ROUTER_NS sysctl -wq net.ipv4.ip_forward=1 | ||
| 44 | |||
| 45 | ip -n $CLIENT_NS link set link3 up | ||
| 46 | ip -n $CLIENT_NS addr add $CLIENT_IP/24 dev link3 | ||
| 47 | ip -n $CLIENT_NS route add $SERVER_IP dev link3 via $CLIENT_GW | ||
| 48 | |||
| 49 | # simulate the delay on OVS upcall by setting up a delay for INIT_ACK with | ||
| 50 | # tc on $SERVER_NS side | ||
| 51 | tc -n $SERVER_NS qdisc add dev link0 root handle 1: htb | ||
| 52 | tc -n $SERVER_NS class add dev link0 parent 1: classid 1:1 htb rate 100mbit | ||
| 53 | tc -n $SERVER_NS filter add dev link0 parent 1: protocol ip u32 match ip protocol 132 \ | ||
| 54 | 0xff match u8 2 0xff at 32 flowid 1:1 | ||
| 55 | tc -n $SERVER_NS qdisc add dev link0 parent 1:1 handle 10: netem delay 1200ms | ||
| 56 | |||
| 57 | # simulate the ctstate check on OVS nf_conntrack | ||
| 58 | ip net exec $ROUTER_NS iptables -A FORWARD -m state --state INVALID,UNTRACKED -j DROP | ||
| 59 | ip net exec $ROUTER_NS iptables -A INPUT -p sctp -j DROP | ||
| 60 | |||
| 61 | # use a smaller number for assoc's max_retrans to reproduce the issue | ||
| 62 | modprobe sctp | ||
| 63 | ip net exec $CLIENT_NS sysctl -wq net.sctp.association_max_retrans=3 | ||
| 64 | } | ||
| 65 | |||
| 66 | cleanup() { | ||
| 67 | ip net exec $CLIENT_NS pkill sctp_collision 2>&1 >/dev/null | ||
| 68 | ip net exec $SERVER_NS pkill sctp_collision 2>&1 >/dev/null | ||
| 69 | ip net del "$CLIENT_NS" | ||
| 70 | ip net del "$SERVER_NS" | ||
| 71 | ip net del "$ROUTER_NS" | ||
| 72 | } | ||
| 73 | |||
| 74 | do_test() { | ||
| 75 | ip net exec $SERVER_NS ./sctp_collision server \ | ||
| 76 | $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT & | ||
| 77 | ip net exec $CLIENT_NS ./sctp_collision client \ | ||
| 78 | $CLIENT_IP $CLIENT_PORT $SERVER_IP $SERVER_PORT | ||
| 79 | } | ||
| 80 | |||
| 81 | # NOTE: one way to work around the issue is set a smaller hb_interval | ||
| 82 | # ip net exec $CLIENT_NS sysctl -wq net.sctp.hb_interval=3500 | ||
| 83 | |||
| 84 | # run the test case | ||
| 85 | trap cleanup EXIT | ||
| 86 | setup && \ | ||
| 87 | echo "Test for SCTP Collision in nf_conntrack:" && \ | ||
| 88 | do_test && echo "PASS!" | ||
| 89 | exit $? | ||
| @@ -12,10 +12,11 @@ nft --version >/dev/null 2>&1 || { · 11 unmodified lines | |||
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | logfile=$(mktemp) | 14 | logfile=$(mktemp) |
| 15 | rulefile=$(mktemp) | ||
| 15 | echo "logging into $logfile" | 16 | echo "logging into $logfile" |
| 16 | ./audit_logread >"$logfile" & | 17 | ./audit_logread >"$logfile" & |
| 17 | logread_pid=$! | 18 | logread_pid=$! |
| 18 | trap 'kill $logread_pid; rm -f $logfile' EXIT | 19 | trap 'kill $logread_pid; rm -f $logfile $rulefile' EXIT |
| 19 | exec 3<"$logfile" | 20 | exec 3<"$logfile" |
| 20 | 21 | ||
| 21 | do_test() { # (cmd, log) | 22 | do_test() { # (cmd, log) |
| @@ -26,12 +27,14 @@ do_test() { # (cmd, log) · 4 unmodified lines | |||
| 26 | res=$(diff -a -u <(echo "$2") - <&3) | 27 | res=$(diff -a -u <(echo "$2") - <&3) |
| 27 | [ $? -eq 0 ] && { echo "OK"; return; } | 28 | [ $? -eq 0 ] && { echo "OK"; return; } |
| 28 | echo "FAIL" | 29 | echo "FAIL" |
| 29 | echo "$res" | 30 | grep -v '^\(---\|+++\|@@\)' <<< "$res" |
| 30 | ((RC++)) | 31 | ((RC--)) |
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | nft flush ruleset | 34 | nft flush ruleset |
| 34 | 35 | ||
| 36 | # adding tables, chains and rules | ||
| 37 | |||
| 35 | for table in t1 t2; do | 38 | for table in t1 t2; do |
| 36 | do_test "nft add table $table" \ | 39 | do_test "nft add table $table" \ |
| 37 | "table=$table family=2 entries=1 op=nft_register_table" | 40 | "table=$table family=2 entries=1 op=nft_register_table" |
| @@ -62,6 +65,48 @@ for table in t1 t2; do · 24 unmodified lines | |||
| 62 | "table=$table family=2 entries=6 op=nft_register_rule" | 65 | "table=$table family=2 entries=6 op=nft_register_rule" |
| 63 | done | 66 | done |
| 64 | 67 | ||
| 68 | for ((i = 0; i < 500; i++)); do | ||
| 69 | echo "add rule t2 c3 counter accept comment \"rule $i\"" | ||
| 70 | done >$rulefile | ||
| 71 | do_test "nft -f $rulefile" \ | ||
| 72 | 'table=t2 family=2 entries=500 op=nft_register_rule' | ||
| 73 | |||
| 74 | # adding sets and elements | ||
| 75 | |||
| 76 | settype='type inet_service; counter' | ||
| 77 | setelem='{ 22, 80, 443 }' | ||
| 78 | setblock="{ $settype; elements = $setelem; }" | ||
| 79 | do_test "nft add set t1 s $setblock" \ | ||
| 80 | "table=t1 family=2 entries=4 op=nft_register_set" | ||
| 81 | |||
| 82 | do_test "nft add set t1 s2 $setblock; add set t1 s3 { $settype; }" \ | ||
| 83 | "table=t1 family=2 entries=5 op=nft_register_set" | ||
| 84 | |||
| 85 | do_test "nft add element t1 s3 $setelem" \ | ||
| 86 | "table=t1 family=2 entries=3 op=nft_register_setelem" | ||
| 87 | |||
| 88 | # adding counters | ||
| 89 | |||
| 90 | do_test 'nft add counter t1 c1' \ | ||
| 91 | 'table=t1 family=2 entries=1 op=nft_register_obj' | ||
| 92 | |||
| 93 | do_test 'nft add counter t2 c1; add counter t2 c2' \ | ||
| 94 | 'table=t2 family=2 entries=2 op=nft_register_obj' | ||
| 95 | |||
| 96 | # adding/updating quotas | ||
| 97 | |||
| 98 | do_test 'nft add quota t1 q1 { 10 bytes }' \ | ||
| 99 | 'table=t1 family=2 entries=1 op=nft_register_obj' | ||
| 100 | |||
| 101 | do_test 'nft add quota t2 q1 { 10 bytes }; add quota t2 q2 { 10 bytes }' \ | ||
| 102 | 'table=t2 family=2 entries=2 op=nft_register_obj' | ||
| 103 | |||
| 104 | # changing the quota value triggers obj update path | ||
| 105 | do_test 'nft add quota t1 q1 { 20 bytes }' \ | ||
| 106 | 'table=t1 family=2 entries=1 op=nft_register_obj' | ||
| 107 | |||
| 108 | # resetting rules | ||
| 109 | |||
| 65 | do_test 'nft reset rules t1 c2' \ | 110 | do_test 'nft reset rules t1 c2' \ |
| 66 | 'table=t1 family=2 entries=3 op=nft_reset_rule' | 111 | 'table=t1 family=2 entries=3 op=nft_reset_rule' |
| 67 | 112 | ||
| @@ -70,19 +115,6 @@ do_test 'nft reset rules table t1' \ · 2 unmodified lines | |||
| 70 | table=t1 family=2 entries=3 op=nft_reset_rule | 115 | table=t1 family=2 entries=3 op=nft_reset_rule |
| 71 | table=t1 family=2 entries=3 op=nft_reset_rule' | 116 | table=t1 family=2 entries=3 op=nft_reset_rule' |
| 72 | 117 | ||
| 73 | do_test 'nft reset rules' \ | ||
| 74 | 'table=t1 family=2 entries=3 op=nft_reset_rule | ||
| 75 | table=t1 family=2 entries=3 op=nft_reset_rule | ||
| 76 | table=t1 family=2 entries=3 op=nft_reset_rule | ||
| 77 | table=t2 family=2 entries=3 op=nft_reset_rule | ||
| 78 | table=t2 family=2 entries=3 op=nft_reset_rule | ||
| 79 | table=t2 family=2 entries=3 op=nft_reset_rule' | ||
| 80 | |||
| 81 | for ((i = 0; i < 500; i++)); do | ||
| 82 | echo "add rule t2 c3 counter accept comment \"rule $i\"" | ||
| 83 | done | do_test 'nft -f -' \ | ||
| 84 | 'table=t2 family=2 entries=500 op=nft_register_rule' | ||
| 85 | |||
| 86 | do_test 'nft reset rules t2 c3' \ | 118 | do_test 'nft reset rules t2 c3' \ |
| 87 | 'table=t2 family=2 entries=189 op=nft_reset_rule | 119 | 'table=t2 family=2 entries=189 op=nft_reset_rule |
| 88 | table=t2 family=2 entries=188 op=nft_reset_rule | 120 | table=t2 family=2 entries=188 op=nft_reset_rule |
| @@ -105,4 +137,57 @@ table=t2 family=2 entries=180 op=nft_reset_rule · 16 unmodified lines | |||
| 105 | table=t2 family=2 entries=188 op=nft_reset_rule | 137 | table=t2 family=2 entries=188 op=nft_reset_rule |
| 106 | table=t2 family=2 entries=135 op=nft_reset_rule' | 138 | table=t2 family=2 entries=135 op=nft_reset_rule' |
| 107 | 139 | ||
| 140 | # resetting sets and elements | ||
| 141 | |||
| 142 | elem=(22 ,80 ,443) | ||
| 143 | relem="" | ||
| 144 | for i in {1..3}; do | ||
| 145 | relem+="${elem[((i - 1))]}" | ||
| 146 | do_test "nft reset element t1 s { $relem }" \ | ||
| 147 | "table=t1 family=2 entries=$i op=nft_reset_setelem" | ||
| 148 | done | ||
| 149 | |||
| 150 | do_test 'nft reset set t1 s' \ | ||
| 151 | 'table=t1 family=2 entries=3 op=nft_reset_setelem' | ||
| 152 | |||
| 153 | # deleting rules | ||
| 154 | |||
| 155 | readarray -t handles < <(nft -a list chain t1 c1 | \ | ||
| 156 | sed -n 's/.*counter.* handle \(.*\)$/\1/p') | ||
| 157 | |||
| 158 | do_test "nft delete rule t1 c1 handle ${handles[0]}" \ | ||
| 159 | 'table=t1 family=2 entries=1 op=nft_unregister_rule' | ||
| 160 | |||
| 161 | cmd='delete rule t1 c1 handle' | ||
| 162 | do_test "nft $cmd ${handles[1]}; $cmd ${handles[2]}" \ | ||
| 163 | 'table=t1 family=2 entries=2 op=nft_unregister_rule' | ||
| 164 | |||
| 165 | do_test 'nft flush chain t1 c2' \ | ||
| 166 | 'table=t1 family=2 entries=3 op=nft_unregister_rule' | ||
| 167 | |||
| 168 | do_test 'nft flush table t2' \ | ||
| 169 | 'table=t2 family=2 entries=509 op=nft_unregister_rule' | ||
| 170 | |||
| 171 | # deleting chains | ||
| 172 | |||
| 173 | do_test 'nft delete chain t2 c2' \ | ||
| 174 | 'table=t2 family=2 entries=1 op=nft_unregister_chain' | ||
| 175 | |||
| 176 | # deleting sets and elements | ||
| 177 | |||
| 178 | do_test 'nft delete element t1 s { 22 }' \ | ||
| 179 | 'table=t1 family=2 entries=1 op=nft_unregister_setelem' | ||
| 180 | |||
| 181 | do_test 'nft delete element t1 s { 80, 443 }' \ | ||
| 182 | 'table=t1 family=2 entries=2 op=nft_unregister_setelem' | ||
| 183 | |||
| 184 | do_test 'nft flush set t1 s2' \ | ||
| 185 | 'table=t1 family=2 entries=3 op=nft_unregister_setelem' | ||
| 186 | |||
| 187 | do_test 'nft delete set t1 s2' \ | ||
| 188 | 'table=t1 family=2 entries=1 op=nft_unregister_set' | ||
| 189 | |||
| 190 | do_test 'nft delete set t1 s3' \ | ||
| 191 | 'table=t1 family=2 entries=1 op=nft_unregister_set' | ||
| 192 | |||
| 108 | exit $RC | 193 | exit $RC |
| @@ -0,0 +1,99 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | #include <stdio.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | #include <string.h> | ||
| 6 | #include <unistd.h> | ||
| 7 | #include <arpa/inet.h> | ||
| 8 | |||
| 9 | int main(int argc, char *argv[]) | ||
| 10 | { | ||
| 11 | struct sockaddr_in saddr = {}, daddr = {}; | ||
| 12 | int sd, ret, len = sizeof(daddr); | ||
| 13 | struct timeval tv = {25, 0}; | ||
| 14 | char buf[] = "hello"; | ||
| 15 | |||
| 16 | if (argc != 6 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) { | ||
| 17 | printf("%s <server|client> <LOCAL_IP> <LOCAL_PORT> <REMOTE_IP> <REMOTE_PORT>\n", | ||
| 18 | argv[0]); | ||
| 19 | return -1; | ||
| 20 | } | ||
| 21 | |||
| 22 | sd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); | ||
| 23 | if (sd < 0) { | ||
| 24 | printf("Failed to create sd\n"); | ||
| 25 | return -1; | ||
| 26 | } | ||
| 27 | |||
| 28 | saddr.sin_family = AF_INET; | ||
| 29 | saddr.sin_addr.s_addr = inet_addr(argv[2]); | ||
| 30 | saddr.sin_port = htons(atoi(argv[3])); | ||
| 31 | |||
| 32 | ret = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr)); | ||
| 33 | if (ret < 0) { | ||
| 34 | printf("Failed to bind to address\n"); | ||
| 35 | goto out; | ||
| 36 | } | ||
| 37 | |||
| 38 | ret = listen(sd, 5); | ||
| 39 | if (ret < 0) { | ||
| 40 | printf("Failed to listen on port\n"); | ||
| 41 | goto out; | ||
| 42 | } | ||
| 43 | |||
| 44 | daddr.sin_family = AF_INET; | ||
| 45 | daddr.sin_addr.s_addr = inet_addr(argv[4]); | ||
| 46 | daddr.sin_port = htons(atoi(argv[5])); | ||
| 47 | |||
| 48 | /* make test shorter than 25s */ | ||
| 49 | ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); | ||
| 50 | if (ret < 0) { | ||
| 51 | printf("Failed to setsockopt SO_RCVTIMEO\n"); | ||
| 52 | goto out; | ||
| 53 | } | ||
| 54 | |||
| 55 | if (!strcmp(argv[1], "server")) { | ||
| 56 | sleep(1); /* wait a bit for client's INIT */ | ||
| 57 | ret = connect(sd, (struct sockaddr *)&daddr, len); | ||
| 58 | if (ret < 0) { | ||
| 59 | printf("Failed to connect to peer\n"); | ||
| 60 | goto out; | ||
| 61 | } | ||
| 62 | ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len); | ||
| 63 | if (ret < 0) { | ||
| 64 | printf("Failed to recv msg %d\n", ret); | ||
| 65 | goto out; | ||
| 66 | } | ||
| 67 | ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len); | ||
| 68 | if (ret < 0) { | ||
| 69 | printf("Failed to send msg %d\n", ret); | ||
| 70 | goto out; | ||
| 71 | } | ||
| 72 | printf("Server: sent! %d\n", ret); | ||
| 73 | } | ||
| 74 | |||
| 75 | if (!strcmp(argv[1], "client")) { | ||
| 76 | usleep(300000); /* wait a bit for server's listening */ | ||
| 77 | ret = connect(sd, (struct sockaddr *)&daddr, len); | ||
| 78 | if (ret < 0) { | ||
| 79 | printf("Failed to connect to peer\n"); | ||
| 80 | goto out; | ||
| 81 | } | ||
| 82 | sleep(1); /* wait a bit for server's delayed INIT_ACK to reproduce the issue */ | ||
| 83 | ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len); | ||
| 84 | if (ret < 0) { | ||
| 85 | printf("Failed to send msg %d\n", ret); | ||
| 86 | goto out; | ||
| 87 | } | ||
| 88 | ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len); | ||
| 89 | if (ret < 0) { | ||
| 90 | printf("Failed to recv msg %d\n", ret); | ||
| 91 | goto out; | ||
| 92 | } | ||
| 93 | printf("Client: rcvd! %d\n", ret); | ||
| 94 | } | ||
| 95 | ret = 0; | ||
| 96 | out: | ||
| 97 | close(sd); | ||
| 98 | return ret; | ||
| 99 | } | ||