Pull networking fixes from Paolo Abeni: "Including fixes from Bluetooth, IPsec and CAN. No known regressions at this point. Current release - regressions: - xfrm: xfrm_alloc_spi shouldn't use 0 as SPI Previous releases - regressions: - xfrm: fix offloading of cross-family tunnels - bluetooth: fix several races leading to UaFs - dsa: lantiq_gswip: fix FDB entries creation for the CPU port - eth: - tun: update napi->skb after XDP process - mlx: fix UAF in flow counter release Previous releases - always broken: - core: forbid FDB status change while nexthop is in a group - smc: fix warning in smc_rx_splice() when calling get_page() - can: provide missing ndo_change_mtu(), to prevent buffer overflow. - eth: - i40e: fix VF config validation - broadcom: fix support for PTP_EXTTS_REQUEST2 ioctl" * tag 'net-6.17-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (40 commits) octeontx2-pf: Fix potential use after free in otx2_tc_add_flow() net: dsa: lantiq_gswip: suppress -EINVAL errors for bridge FDB entries added to the CPU port net: dsa: lantiq_gswip: move gswip_add_single_port_br() call to port_setup() libie: fix string names for AQ error codes net/mlx5e: Fix missing FEC RS stats for RS_544_514_INTERLEAVED_QUAD net/mlx5: HWS, ignore flow level for multi-dest table net/mlx5: fs, fix UAF in flow counter release selftests: fib_nexthops: Add test cases for FDB status change selftests: fib_nexthops: Fix creation of non-FDB nexthops nexthop: Forbid FDB status change while nexthop is in a group net: allow alloc_skb_with_frags() to use MAX_SKB_FRAGS bnxt_en: correct offset handling for IPv6 destination address ptp: document behavior of PTP_STRICT_FLAGS broadcom: fix support for PTP_EXTTS_REQUEST2 ioctl broadcom: fix support for PTP_PEROUT_DUTY_CYCLE Bluetooth: MGMT: Fix possible UAFs Bluetooth: hci_event: Fix UAF in hci_acl_create_conn_sync Bluetooth: hci_event: Fix UAF in hci_conn_tx_dequeue Bluetooth: hci_sync: Fix hci_resume_advertising_sync Bluetooth: Fix build after header cleanup ...
Unified · Split
| @@ -312,7 +312,9 @@ config BT_HCIBCM4377 · 311 unmodified lines | |||
| 312 | 312 | ||
| 313 | config BT_HCIBPA10X | 313 | config BT_HCIBPA10X |
| 314 | tristate "HCI BPA10x USB driver" | 314 | tristate "HCI BPA10x USB driver" |
| 315 | depends on BT_HCIUART | ||
| 315 | depends on USB | 316 | depends on USB |
| 317 | select BT_HCIUART_H4 | ||
| 316 | help | 318 | help |
| 317 | Bluetooth HCI BPA10x USB driver. | 319 | Bluetooth HCI BPA10x USB driver. |
| 318 | This driver provides support for the Digianswer BPA 100/105 Bluetooth | 320 | This driver provides support for the Digianswer BPA 100/105 Bluetooth |
| @@ -437,8 +439,10 @@ config BT_MTKSDIO · 118 unmodified lines | |||
| 437 | 439 | ||
| 438 | config BT_MTKUART | 440 | config BT_MTKUART |
| 439 | tristate "MediaTek HCI UART driver" | 441 | tristate "MediaTek HCI UART driver" |
| 442 | depends on BT_HCIUART | ||
| 440 | depends on SERIAL_DEV_BUS | 443 | depends on SERIAL_DEV_BUS |
| 441 | depends on USB || !BT_HCIBTUSB_MTK | 444 | depends on USB || !BT_HCIBTUSB_MTK |
| 445 | select BT_HCIUART_H4 | ||
| 442 | select BT_MTK | 446 | select BT_MTK |
| 443 | help | 447 | help |
| 444 | MediaTek Bluetooth HCI UART driver. | 448 | MediaTek Bluetooth HCI UART driver. |
| @@ -483,7 +487,9 @@ config BT_VIRTIO · 38 unmodified lines | |||
| 483 | 487 | ||
| 484 | config BT_NXPUART | 488 | config BT_NXPUART |
| 485 | tristate "NXP protocol support" | 489 | tristate "NXP protocol support" |
| 490 | depends on BT_HCIUART | ||
| 486 | depends on SERIAL_DEV_BUS | 491 | depends on SERIAL_DEV_BUS |
| 492 | select BT_HCIUART_H4 | ||
| 487 | select CRC32 | 493 | select CRC32 |
| 488 | select CRC8 | 494 | select CRC8 |
| 489 | help | 495 | help |
| @@ -121,10 +121,6 @@ void hci_uart_set_flow_control(struct hci_uart *hu, bool enable); · 120 unmodified lines | |||
| 121 | void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed, | 121 | void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed, |
| 122 | unsigned int oper_speed); | 122 | unsigned int oper_speed); |
| 123 | 123 | ||
| 124 | #ifdef CONFIG_BT_HCIUART_H4 | ||
| 125 | int h4_init(void); | ||
| 126 | int h4_deinit(void); | ||
| 127 | |||
| 128 | struct h4_recv_pkt { | 124 | struct h4_recv_pkt { |
| 129 | u8 type; /* Packet type */ | 125 | u8 type; /* Packet type */ |
| 130 | u8 hlen; /* Header length */ | 126 | u8 hlen; /* Header length */ |
| @@ -162,6 +158,10 @@ struct h4_recv_pkt { · 31 unmodified lines | |||
| 162 | .lsize = 2, \ | 158 | .lsize = 2, \ |
| 163 | .maxlen = HCI_MAX_FRAME_SIZE \ | 159 | .maxlen = HCI_MAX_FRAME_SIZE \ |
| 164 | 160 | ||
| 161 | #ifdef CONFIG_BT_HCIUART_H4 | ||
| 162 | int h4_init(void); | ||
| 163 | int h4_deinit(void); | ||
| 164 | |||
| 165 | struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb, | 165 | struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb, |
| 166 | const unsigned char *buffer, int count, | 166 | const unsigned char *buffer, int count, |
| 167 | const struct h4_recv_pkt *pkts, int pkts_count); | 167 | const struct h4_recv_pkt *pkts, int pkts_count); |
| @@ -823,9 +823,6 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) · 822 unmodified lines | |||
| 823 | /* Reset Global error flags */ | 823 | /* Reset Global error flags */ |
| 824 | rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0); | 824 | rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0); |
| 825 | 825 | ||
| 826 | /* Set the controller into appropriate mode */ | ||
| 827 | rcar_canfd_set_mode(gpriv); | ||
| 828 | |||
| 829 | /* Transition all Channels to reset mode */ | 826 | /* Transition all Channels to reset mode */ |
| 830 | for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) { | 827 | for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) { |
| 831 | rcar_canfd_clear_bit(gpriv->base, | 828 | rcar_canfd_clear_bit(gpriv->base, |
| @@ -844,6 +841,10 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) · 12 unmodified lines | |||
| 844 | return err; | 841 | return err; |
| 845 | } | 842 | } |
| 846 | } | 843 | } |
| 844 | |||
| 845 | /* Set the controller into appropriate mode */ | ||
| 846 | rcar_canfd_set_mode(gpriv); | ||
| 847 | |||
| 847 | return 0; | 848 | return 0; |
| 848 | } | 849 | } |
| 849 | 850 | ||
| @@ -545,8 +545,6 @@ static int hi3110_stop(struct net_device *net) · 544 unmodified lines | |||
| 545 | 545 | ||
| 546 | priv->force_quit = 1; | 546 | priv->force_quit = 1; |
| 547 | free_irq(spi->irq, priv); | 547 | free_irq(spi->irq, priv); |
| 548 | destroy_workqueue(priv->wq); | ||
| 549 | priv->wq = NULL; | ||
| 550 | 548 | ||
| 551 | mutex_lock(&priv->hi3110_lock); | 549 | mutex_lock(&priv->hi3110_lock); |
| 552 | 550 | ||
| @@ -770,34 +768,23 @@ static int hi3110_open(struct net_device *net) · 217 unmodified lines | |||
| 770 | goto out_close; | 768 | goto out_close; |
| 771 | } | 769 | } |
| 772 | 770 | ||
| 773 | priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, | ||
| 774 | 0); | ||
| 775 | if (!priv->wq) { | ||
| 776 | ret = -ENOMEM; | ||
| 777 | goto out_free_irq; | ||
| 778 | } | ||
| 779 | INIT_WORK(&priv->tx_work, hi3110_tx_work_handler); | ||
| 780 | INIT_WORK(&priv->restart_work, hi3110_restart_work_handler); | ||
| 781 | |||
| 782 | ret = hi3110_hw_reset(spi); | 771 | ret = hi3110_hw_reset(spi); |
| 783 | if (ret) | 772 | if (ret) |
| 784 | goto out_free_wq; | 773 | goto out_free_irq; |
| 785 | 774 | ||
| 786 | ret = hi3110_setup(net); | 775 | ret = hi3110_setup(net); |
| 787 | if (ret) | 776 | if (ret) |
| 788 | goto out_free_wq; | 777 | goto out_free_irq; |
| 789 | 778 | ||
| 790 | ret = hi3110_set_normal_mode(spi); | 779 | ret = hi3110_set_normal_mode(spi); |
| 791 | if (ret) | 780 | if (ret) |
| 792 | goto out_free_wq; | 781 | goto out_free_irq; |
| 793 | 782 | ||
| 794 | netif_wake_queue(net); | 783 | netif_wake_queue(net); |
| 795 | mutex_unlock(&priv->hi3110_lock); | 784 | mutex_unlock(&priv->hi3110_lock); |
| 796 | 785 | ||
| 797 | return 0; | 786 | return 0; |
| 798 | 787 | ||
| 799 | out_free_wq: | ||
| 800 | destroy_workqueue(priv->wq); | ||
| 801 | out_free_irq: | 788 | out_free_irq: |
| 802 | free_irq(spi->irq, priv); | 789 | free_irq(spi->irq, priv); |
| 803 | hi3110_hw_sleep(spi); | 790 | hi3110_hw_sleep(spi); |
| @@ -812,6 +799,7 @@ static const struct net_device_ops hi3110_netdev_ops = { · 8 unmodified lines | |||
| 812 | .ndo_open = hi3110_open, | 799 | .ndo_open = hi3110_open, |
| 813 | .ndo_stop = hi3110_stop, | 800 | .ndo_stop = hi3110_stop, |
| 814 | .ndo_start_xmit = hi3110_hard_start_xmit, | 801 | .ndo_start_xmit = hi3110_hard_start_xmit, |
| 802 | .ndo_change_mtu = can_change_mtu, | ||
| 815 | }; | 803 | }; |
| 816 | 804 | ||
| 817 | static const struct ethtool_ops hi3110_ethtool_ops = { | 805 | static const struct ethtool_ops hi3110_ethtool_ops = { |
| @@ -908,6 +896,15 @@ static int hi3110_can_probe(struct spi_device *spi) · 90 unmodified lines | |||
| 908 | if (ret) | 896 | if (ret) |
| 909 | goto out_clk; | 897 | goto out_clk; |
| 910 | 898 | ||
| 899 | priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, | ||
| 900 | 0); | ||
| 901 | if (!priv->wq) { | ||
| 902 | ret = -ENOMEM; | ||
| 903 | goto out_clk; | ||
| 904 | } | ||
| 905 | INIT_WORK(&priv->tx_work, hi3110_tx_work_handler); | ||
| 906 | INIT_WORK(&priv->restart_work, hi3110_restart_work_handler); | ||
| 907 | |||
| 911 | priv->spi = spi; | 908 | priv->spi = spi; |
| 912 | mutex_init(&priv->hi3110_lock); | 909 | mutex_init(&priv->hi3110_lock); |
| 913 | 910 | ||
| @@ -943,6 +940,8 @@ static int hi3110_can_probe(struct spi_device *spi) · 29 unmodified lines | |||
| 943 | return 0; | 940 | return 0; |
| 944 | 941 | ||
| 945 | error_probe: | 942 | error_probe: |
| 943 | destroy_workqueue(priv->wq); | ||
| 944 | priv->wq = NULL; | ||
| 946 | hi3110_power_enable(priv->power, 0); | 945 | hi3110_power_enable(priv->power, 0); |
| 947 | 946 | ||
| 948 | out_clk: | 947 | out_clk: |
| @@ -963,6 +962,9 @@ static void hi3110_can_remove(struct spi_device *spi) · 14 unmodified lines | |||
| 963 | 962 | ||
| 964 | hi3110_power_enable(priv->power, 0); | 963 | hi3110_power_enable(priv->power, 0); |
| 965 | 964 | ||
| 965 | destroy_workqueue(priv->wq); | ||
| 966 | priv->wq = NULL; | ||
| 967 | |||
| 966 | clk_disable_unprepare(priv->clk); | 968 | clk_disable_unprepare(priv->clk); |
| 967 | 969 | ||
| 968 | free_candev(net); | 970 | free_candev(net); |
| @@ -768,6 +768,7 @@ static const struct net_device_ops sun4ican_netdev_ops = { · 767 unmodified lines | |||
| 768 | .ndo_open = sun4ican_open, | 768 | .ndo_open = sun4ican_open, |
| 769 | .ndo_stop = sun4ican_close, | 769 | .ndo_stop = sun4ican_close, |
| 770 | .ndo_start_xmit = sun4ican_start_xmit, | 770 | .ndo_start_xmit = sun4ican_start_xmit, |
| 771 | .ndo_change_mtu = can_change_mtu, | ||
| 771 | }; | 772 | }; |
| 772 | 773 | ||
| 773 | static const struct ethtool_ops sun4ican_ethtool_ops = { | 774 | static const struct ethtool_ops sun4ican_ethtool_ops = { |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | |||
| 7 | * | 7 | * |
| 8 | * Copyright (c) 2019 Robert Bosch Engineering and Business Solutions. All rights reserved. | 8 | * Copyright (c) 2019 Robert Bosch Engineering and Business Solutions. All rights reserved. |
| 9 | * Copyright (c) 2020 ETAS K.K.. All rights reserved. | 9 | * Copyright (c) 2020 ETAS K.K.. All rights reserved. |
| 10 | * Copyright (c) 2020-2022 Vincent Mailhol <mailhol.vincent@wanadoo.fr> | 10 | * Copyright (c) 2020-2025 Vincent Mailhol <mailhol@kernel.org> |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/unaligned.h> | 13 | #include <linux/unaligned.h> |
| @@ -1977,6 +1977,7 @@ static const struct net_device_ops es58x_netdev_ops = { · 1963 unmodified lines | |||
| 1977 | .ndo_stop = es58x_stop, | 1977 | .ndo_stop = es58x_stop, |
| 1978 | .ndo_start_xmit = es58x_start_xmit, | 1978 | .ndo_start_xmit = es58x_start_xmit, |
| 1979 | .ndo_eth_ioctl = can_eth_ioctl_hwts, | 1979 | .ndo_eth_ioctl = can_eth_ioctl_hwts, |
| 1980 | .ndo_change_mtu = can_change_mtu, | ||
| 1980 | }; | 1981 | }; |
| 1981 | 1982 | ||
| 1982 | static const struct ethtool_ops es58x_ethtool_ops = { | 1983 | static const struct ethtool_ops es58x_ethtool_ops = { |
| @@ -761,6 +761,7 @@ static const struct net_device_ops mcba_netdev_ops = { · 760 unmodified lines | |||
| 761 | .ndo_open = mcba_usb_open, | 761 | .ndo_open = mcba_usb_open, |
| 762 | .ndo_stop = mcba_usb_close, | 762 | .ndo_stop = mcba_usb_close, |
| 763 | .ndo_start_xmit = mcba_usb_start_xmit, | 763 | .ndo_start_xmit = mcba_usb_start_xmit, |
| 764 | .ndo_change_mtu = can_change_mtu, | ||
| 764 | }; | 765 | }; |
| 765 | 766 | ||
| 766 | static const struct ethtool_ops mcba_ethtool_ops = { | 767 | static const struct ethtool_ops mcba_ethtool_ops = { |
| @@ -111,7 +111,7 @@ void peak_usb_update_ts_now(struct peak_time_ref *time_ref, u32 ts_now) · 110 unmodified lines | |||
| 111 | u32 delta_ts = time_ref->ts_dev_2 - time_ref->ts_dev_1; | 111 | u32 delta_ts = time_ref->ts_dev_2 - time_ref->ts_dev_1; |
| 112 | 112 | ||
| 113 | if (time_ref->ts_dev_2 < time_ref->ts_dev_1) | 113 | if (time_ref->ts_dev_2 < time_ref->ts_dev_1) |
| 114 | delta_ts &= (1 << time_ref->adapter->ts_used_bits) - 1; | 114 | delta_ts &= (1ULL << time_ref->adapter->ts_used_bits) - 1; |
| 115 | 115 | ||
| 116 | time_ref->ts_total += delta_ts; | 116 | time_ref->ts_total += delta_ts; |
| 117 | } | 117 | } |
| @@ -685,18 +685,27 @@ static int gswip_add_single_port_br(struct gswip_priv *priv, int port, bool add) · 684 unmodified lines | |||
| 685 | return 0; | 685 | return 0; |
| 686 | } | 686 | } |
| 687 | 687 | ||
| 688 | static int gswip_port_enable(struct dsa_switch *ds, int port, | 688 | static int gswip_port_setup(struct dsa_switch *ds, int port) |
| 689 | struct phy_device *phydev) | ||
| 690 | { | 689 | { |
| 691 | struct gswip_priv *priv = ds->priv; | 690 | struct gswip_priv *priv = ds->priv; |
| 692 | int err; | 691 | int err; |
| 693 | 692 | ||
| 694 | if (!dsa_is_cpu_port(ds, port)) { | 693 | if (!dsa_is_cpu_port(ds, port)) { |
| 695 | u32 mdio_phy = 0; | ||
| 696 | |||
| 697 | err = gswip_add_single_port_br(priv, port, true); | 694 | err = gswip_add_single_port_br(priv, port, true); |
| 698 | if (err) | 695 | if (err) |
| 699 | return err; | 696 | return err; |
| 697 | } | ||
| 698 | |||
| 699 | return 0; | ||
| 700 | } | ||
| 701 | |||
| 702 | static int gswip_port_enable(struct dsa_switch *ds, int port, | ||
| 703 | struct phy_device *phydev) | ||
| 704 | { | ||
| 705 | struct gswip_priv *priv = ds->priv; | ||
| 706 | |||
| 707 | if (!dsa_is_cpu_port(ds, port)) { | ||
| 708 | u32 mdio_phy = 0; | ||
| 700 | 709 | ||
| 701 | if (phydev) | 710 | if (phydev) |
| 702 | mdio_phy = phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK; | 711 | mdio_phy = phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK; |
| @@ -1359,8 +1368,9 @@ static int gswip_port_fdb(struct dsa_switch *ds, int port, · 656 unmodified lines | |||
| 1359 | int i; | 1368 | int i; |
| 1360 | int err; | 1369 | int err; |
| 1361 | 1370 | ||
| 1371 | /* Operation not supported on the CPU port, don't throw errors */ | ||
| 1362 | if (!bridge) | 1372 | if (!bridge) |
| 1363 | return -EINVAL; | 1373 | return 0; |
| 1364 | 1374 | ||
| 1365 | for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) { | 1375 | for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) { |
| 1366 | if (priv->vlans[i].bridge == bridge) { | 1376 | if (priv->vlans[i].bridge == bridge) { |
| @@ -1829,6 +1839,7 @@ static const struct phylink_mac_ops gswip_phylink_mac_ops = { · 462 unmodified lines | |||
| 1829 | static const struct dsa_switch_ops gswip_xrx200_switch_ops = { | 1839 | static const struct dsa_switch_ops gswip_xrx200_switch_ops = { |
| 1830 | .get_tag_protocol = gswip_get_tag_protocol, | 1840 | .get_tag_protocol = gswip_get_tag_protocol, |
| 1831 | .setup = gswip_setup, | 1841 | .setup = gswip_setup, |
| 1842 | .port_setup = gswip_port_setup, | ||
| 1832 | .port_enable = gswip_port_enable, | 1843 | .port_enable = gswip_port_enable, |
| 1833 | .port_disable = gswip_port_disable, | 1844 | .port_disable = gswip_port_disable, |
| 1834 | .port_bridge_join = gswip_port_bridge_join, | 1845 | .port_bridge_join = gswip_port_bridge_join, |
| @@ -244,7 +244,7 @@ bnxt_tc_parse_pedit(struct bnxt *bp, struct bnxt_tc_actions *actions, · 243 unmodified lines | |||
| 244 | offset < offset_of_ip6_daddr + 16) { | 244 | offset < offset_of_ip6_daddr + 16) { |
| 245 | actions->nat.src_xlate = false; | 245 | actions->nat.src_xlate = false; |
| 246 | idx = (offset - offset_of_ip6_daddr) / 4; | 246 | idx = (offset - offset_of_ip6_daddr) / 4; |
| 247 | actions->nat.l3.ipv6.saddr.s6_addr32[idx] = htonl(val); | 247 | actions->nat.l3.ipv6.daddr.s6_addr32[idx] = htonl(val); |
| 248 | } else { | 248 | } else { |
| 249 | netdev_err(bp->dev, | 249 | netdev_err(bp->dev, |
| 250 | "%s: IPv6_hdr: Invalid pedit field\n", | 250 | "%s: IPv6_hdr: Invalid pedit field\n", |
| @@ -1278,7 +1278,8 @@ struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi, · 1277 unmodified lines | |||
| 1278 | const u8 *macaddr); | 1278 | const u8 *macaddr); |
| 1279 | int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr); | 1279 | int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr); |
| 1280 | bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi); | 1280 | bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi); |
| 1281 | int i40e_count_filters(struct i40e_vsi *vsi); | 1281 | int i40e_count_all_filters(struct i40e_vsi *vsi); |
| 1282 | int i40e_count_active_filters(struct i40e_vsi *vsi); | ||
| 1282 | struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr); | 1283 | struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr); |
| 1283 | void i40e_vlan_stripping_enable(struct i40e_vsi *vsi); | 1284 | void i40e_vlan_stripping_enable(struct i40e_vsi *vsi); |
| 1284 | static inline bool i40e_is_sw_dcb(struct i40e_pf *pf) | 1285 | static inline bool i40e_is_sw_dcb(struct i40e_pf *pf) |
| @@ -1243,12 +1243,30 @@ void i40e_update_stats(struct i40e_vsi *vsi) · 1242 unmodified lines | |||
| 1243 | } | 1243 | } |
| 1244 | 1244 | ||
| 1245 | /** | 1245 | /** |
| 1246 | * i40e_count_filters - counts VSI mac filters | 1246 | * i40e_count_all_filters - counts VSI MAC filters |
| 1247 | * @vsi: the VSI to be searched | 1247 | * @vsi: the VSI to be searched |
| 1248 | * | 1248 | * |
| 1249 | * Returns count of mac filters | 1249 | * Return: count of MAC filters in any state. |
| 1250 | **/ | 1250 | */ |
| 1251 | int i40e_count_filters(struct i40e_vsi *vsi) | 1251 | int i40e_count_all_filters(struct i40e_vsi *vsi) |
| 1252 | { | ||
| 1253 | struct i40e_mac_filter *f; | ||
| 1254 | struct hlist_node *h; | ||
| 1255 | int bkt, cnt = 0; | ||
| 1256 | |||
| 1257 | hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) | ||
| 1258 | cnt++; | ||
| 1259 | |||
| 1260 | return cnt; | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | /** | ||
| 1264 | * i40e_count_active_filters - counts VSI MAC filters | ||
| 1265 | * @vsi: the VSI to be searched | ||
| 1266 | * | ||
| 1267 | * Return: count of active MAC filters. | ||
| 1268 | */ | ||
| 1269 | int i40e_count_active_filters(struct i40e_vsi *vsi) | ||
| 1252 | { | 1270 | { |
| 1253 | struct i40e_mac_filter *f; | 1271 | struct i40e_mac_filter *f; |
| 1254 | struct hlist_node *h; | 1272 | struct hlist_node *h; |
| @@ -448,7 +448,7 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_id, · 447 unmodified lines | |||
| 448 | (qtype << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) | | 448 | (qtype << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) | |
| 449 | (pf_queue_id << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) | | 449 | (pf_queue_id << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) | |
| 450 | BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) | | 450 | BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) | |
| 451 | (itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT); | 451 | FIELD_PREP(I40E_QINT_RQCTL_ITR_INDX_MASK, itr_idx); |
| 452 | wr32(hw, reg_idx, reg); | 452 | wr32(hw, reg_idx, reg); |
| 453 | } | 453 | } |
| 454 | 454 | ||
| @@ -653,6 +653,13 @@ static int i40e_config_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_id, · 198 unmodified lines | |||
| 653 | 653 | ||
| 654 | /* only set the required fields */ | 654 | /* only set the required fields */ |
| 655 | tx_ctx.base = info->dma_ring_addr / 128; | 655 | tx_ctx.base = info->dma_ring_addr / 128; |
| 656 | |||
| 657 | /* ring_len has to be multiple of 8 */ | ||
| 658 | if (!IS_ALIGNED(info->ring_len, 8) || | ||
| 659 | info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) { | ||
| 660 | ret = -EINVAL; | ||
| 661 | goto error_context; | ||
| 662 | } | ||
| 656 | tx_ctx.qlen = info->ring_len; | 663 | tx_ctx.qlen = info->ring_len; |
| 657 | tx_ctx.rdylist = le16_to_cpu(vsi->info.qs_handle[0]); | 664 | tx_ctx.rdylist = le16_to_cpu(vsi->info.qs_handle[0]); |
| 658 | tx_ctx.rdylist_act = 0; | 665 | tx_ctx.rdylist_act = 0; |
| @@ -716,6 +723,13 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id, · 57 unmodified lines | |||
| 716 | 723 | ||
| 717 | /* only set the required fields */ | 724 | /* only set the required fields */ |
| 718 | rx_ctx.base = info->dma_ring_addr / 128; | 725 | rx_ctx.base = info->dma_ring_addr / 128; |
| 726 | |||
| 727 | /* ring_len has to be multiple of 32 */ | ||
| 728 | if (!IS_ALIGNED(info->ring_len, 32) || | ||
| 729 | info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) { | ||
| 730 | ret = -EINVAL; | ||
| 731 | goto error_param; | ||
| 732 | } | ||
| 719 | rx_ctx.qlen = info->ring_len; | 733 | rx_ctx.qlen = info->ring_len; |
| 720 | 734 | ||
| 721 | if (info->splithdr_enabled) { | 735 | if (info->splithdr_enabled) { |
| @@ -1450,6 +1464,7 @@ static void i40e_trigger_vf_reset(struct i40e_vf *vf, bool flr) · 728 unmodified lines | |||
| 1450 | * functions that may still be running at this point. | 1464 | * functions that may still be running at this point. |
| 1451 | */ | 1465 | */ |
| 1452 | clear_bit(I40E_VF_STATE_INIT, &vf->vf_states); | 1466 | clear_bit(I40E_VF_STATE_INIT, &vf->vf_states); |
| 1467 | clear_bit(I40E_VF_STATE_RESOURCES_LOADED, &vf->vf_states); | ||
| 1453 | 1468 | ||
| 1454 | /* In the case of a VFLR, the HW has already reset the VF and we | 1469 | /* In the case of a VFLR, the HW has already reset the VF and we |
| 1455 | * just need to clean up, so don't hit the VFRTRIG register. | 1470 | * just need to clean up, so don't hit the VFRTRIG register. |
| @@ -2116,7 +2131,10 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) · 660 unmodified lines | |||
| 2116 | size_t len = 0; | 2131 | size_t len = 0; |
| 2117 | int ret; | 2132 | int ret; |
| 2118 | 2133 | ||
| 2119 | if (!i40e_sync_vf_state(vf, I40E_VF_STATE_INIT)) { | 2134 | i40e_sync_vf_state(vf, I40E_VF_STATE_INIT); |
| 2135 | |||
| 2136 | if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states) || | ||
| 2137 | test_bit(I40E_VF_STATE_RESOURCES_LOADED, &vf->vf_states)) { | ||
| 2120 | aq_ret = -EINVAL; | 2138 | aq_ret = -EINVAL; |
| 2121 | goto err; | 2139 | goto err; |
| 2122 | } | 2140 | } |
| @@ -2219,6 +2237,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) · 96 unmodified lines | |||
| 2219 | vf->default_lan_addr.addr); | 2237 | vf->default_lan_addr.addr); |
| 2220 | } | 2238 | } |
| 2221 | set_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states); | 2239 | set_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states); |
| 2240 | set_bit(I40E_VF_STATE_RESOURCES_LOADED, &vf->vf_states); | ||
| 2222 | 2241 | ||
| 2223 | err: | 2242 | err: |
| 2224 | /* send the response back to the VF */ | 2243 | /* send the response back to the VF */ |
| @@ -2381,7 +2400,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) · 156 unmodified lines | |||
| 2381 | } | 2400 | } |
| 2382 | 2401 | ||
| 2383 | if (vf->adq_enabled) { | 2402 | if (vf->adq_enabled) { |
| 2384 | if (idx >= ARRAY_SIZE(vf->ch)) { | 2403 | if (idx >= vf->num_tc) { |
| 2385 | aq_ret = -ENODEV; | 2404 | aq_ret = -ENODEV; |
| 2386 | goto error_param; | 2405 | goto error_param; |
| 2387 | } | 2406 | } |
| @@ -2402,7 +2421,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) · 14 unmodified lines | |||
| 2402 | * to its appropriate VSIs based on TC mapping | 2421 | * to its appropriate VSIs based on TC mapping |
| 2403 | */ | 2422 | */ |
| 2404 | if (vf->adq_enabled) { | 2423 | if (vf->adq_enabled) { |
| 2405 | if (idx >= ARRAY_SIZE(vf->ch)) { | 2424 | if (idx >= vf->num_tc) { |
| 2406 | aq_ret = -ENODEV; | 2425 | aq_ret = -ENODEV; |
| 2407 | goto error_param; | 2426 | goto error_param; |
| 2408 | } | 2427 | } |
| @@ -2452,8 +2471,10 @@ static int i40e_validate_queue_map(struct i40e_vf *vf, u16 vsi_id, · 43 unmodified lines | |||
| 2452 | u16 vsi_queue_id, queue_id; | 2471 | u16 vsi_queue_id, queue_id; |
| 2453 | 2472 | ||
| 2454 | for_each_set_bit(vsi_queue_id, &queuemap, I40E_MAX_VSI_QP) { | 2473 | for_each_set_bit(vsi_queue_id, &queuemap, I40E_MAX_VSI_QP) { |
| 2455 | if (vf->adq_enabled) { | 2474 | u16 idx = vsi_queue_id / I40E_MAX_VF_VSI; |
| 2456 | vsi_id = vf->ch[vsi_queue_id / I40E_MAX_VF_VSI].vsi_id; | 2475 | |
| 2476 | if (vf->adq_enabled && idx < vf->num_tc) { | ||
| 2477 | vsi_id = vf->ch[idx].vsi_id; | ||
| 2457 | queue_id = (vsi_queue_id % I40E_DEFAULT_QUEUES_PER_VF); | 2478 | queue_id = (vsi_queue_id % I40E_DEFAULT_QUEUES_PER_VF); |
| 2458 | } else { | 2479 | } else { |
| 2459 | queue_id = vsi_queue_id; | 2480 | queue_id = vsi_queue_id; |
| @@ -2841,24 +2862,6 @@ error_param: · 381 unmodified lines | |||
| 2841 | (u8 *)&stats, sizeof(stats)); | 2862 | (u8 *)&stats, sizeof(stats)); |
| 2842 | } | 2863 | } |
| 2843 | 2864 | ||
| 2844 | /** | ||
| 2845 | * i40e_can_vf_change_mac | ||
| 2846 | * @vf: pointer to the VF info | ||
| 2847 | * | ||
| 2848 | * Return true if the VF is allowed to change its MAC filters, false otherwise | ||
| 2849 | */ | ||
| 2850 | static bool i40e_can_vf_change_mac(struct i40e_vf *vf) | ||
| 2851 | { | ||
| 2852 | /* If the VF MAC address has been set administratively (via the | ||
| 2853 | * ndo_set_vf_mac command), then deny permission to the VF to | ||
| 2854 | * add/delete unicast MAC addresses, unless the VF is trusted | ||
| 2855 | */ | ||
| 2856 | if (vf->pf_set_mac && !vf->trusted) | ||
| 2857 | return false; | ||
| 2858 | |||
| 2859 | return true; | ||
| 2860 | } | ||
| 2861 | |||
| 2862 | #define I40E_MAX_MACVLAN_PER_HW 3072 | 2865 | #define I40E_MAX_MACVLAN_PER_HW 3072 |
| 2863 | #define I40E_MAX_MACVLAN_PER_PF(num_ports) (I40E_MAX_MACVLAN_PER_HW / \ | 2866 | #define I40E_MAX_MACVLAN_PER_PF(num_ports) (I40E_MAX_MACVLAN_PER_HW / \ |
| 2864 | (num_ports)) | 2867 | (num_ports)) |
| @@ -2897,8 +2900,10 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, · 32 unmodified lines | |||
| 2897 | struct i40e_pf *pf = vf->pf; | 2900 | struct i40e_pf *pf = vf->pf; |
| 2898 | struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx]; | 2901 | struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx]; |
| 2899 | struct i40e_hw *hw = &pf->hw; | 2902 | struct i40e_hw *hw = &pf->hw; |
| 2900 | int mac2add_cnt = 0; | 2903 | int i, mac_add_max, mac_add_cnt = 0; |
| 2901 | int i; | 2904 | bool vf_trusted; |
| 2905 | |||
| 2906 | vf_trusted = test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); | ||
| 2902 | 2907 | ||
| 2903 | for (i = 0; i < al->num_elements; i++) { | 2908 | for (i = 0; i < al->num_elements; i++) { |
| 2904 | struct i40e_mac_filter *f; | 2909 | struct i40e_mac_filter *f; |
| @@ -2918,9 +2923,8 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, · 13 unmodified lines | |||
| 2918 | * The VF may request to set the MAC address filter already | 2923 | * The VF may request to set the MAC address filter already |
| 2919 | * assigned to it so do not return an error in that case. | 2924 | * assigned to it so do not return an error in that case. |
| 2920 | */ | 2925 | */ |
| 2921 | if (!i40e_can_vf_change_mac(vf) && | 2926 | if (!vf_trusted && !is_multicast_ether_addr(addr) && |
| 2922 | !is_multicast_ether_addr(addr) && | 2927 | vf->pf_set_mac && !ether_addr_equal(addr, vf->default_lan_addr.addr)) { |
| 2923 | !ether_addr_equal(addr, vf->default_lan_addr.addr)) { | ||
| 2924 | dev_err(&pf->pdev->dev, | 2928 | dev_err(&pf->pdev->dev, |
| 2925 | "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n"); | 2929 | "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n"); |
| 2926 | return -EPERM; | 2930 | return -EPERM; |
| @@ -2929,29 +2933,33 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, · 2 unmodified lines | |||
| 2929 | /*count filters that really will be added*/ | 2933 | /*count filters that really will be added*/ |
| 2930 | f = i40e_find_mac(vsi, addr); | 2934 | f = i40e_find_mac(vsi, addr); |
| 2931 | if (!f) | 2935 | if (!f) |
| 2932 | ++mac2add_cnt; | 2936 | ++mac_add_cnt; |
| 2933 | } | 2937 | } |
| 2934 | 2938 | ||
| 2935 | /* If this VF is not privileged, then we can't add more than a limited | 2939 | /* If this VF is not privileged, then we can't add more than a limited |
| 2936 | * number of addresses. Check to make sure that the additions do not | 2940 | * number of addresses. |
| 2937 | * push us over the limit. | 2941 | * |
| 2938 | */ | 2942 | * If this VF is trusted, it can use more resources than untrusted. |
| 2939 | if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) { | ||
| 2940 | if ((i40e_count_filters(vsi) + mac2add_cnt) > | ||
| 2941 | I40E_VC_MAX_MAC_ADDR_PER_VF) { | ||
| 2942 | dev_err(&pf->pdev->dev, | ||
| 2943 | "Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n"); | ||
| 2944 | return -EPERM; | ||
| 2945 | } | ||
| 2946 | /* If this VF is trusted, it can use more resources than untrusted. | ||
| 2947 | * However to ensure that every trusted VF has appropriate number of | 2943 | * However to ensure that every trusted VF has appropriate number of |
| 2948 | * resources, divide whole pool of resources per port and then across | 2944 | * resources, divide whole pool of resources per port and then across |
| 2949 | * all VFs. | 2945 | * all VFs. |
| 2950 | */ | 2946 | */ |
| 2951 | } else { | 2947 | if (!vf_trusted) |
| 2952 | if ((i40e_count_filters(vsi) + mac2add_cnt) > | 2948 | mac_add_max = I40E_VC_MAX_MAC_ADDR_PER_VF; |
| 2953 | I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs, | 2949 | else |
| 2954 | hw->num_ports)) { | 2950 | mac_add_max = I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs, hw->num_ports); |
| 2951 | |||
| 2952 | /* VF can replace all its filters in one step, in this case mac_add_max | ||
| 2953 | * will be added as active and another mac_add_max will be in | ||
| 2954 | * a to-be-removed state. Account for that. | ||
| 2955 | */ | ||
| 2956 | if ((i40e_count_active_filters(vsi) + mac_add_cnt) > mac_add_max || | ||
| 2957 | (i40e_count_all_filters(vsi) + mac_add_cnt) > 2 * mac_add_max) { | ||
| 2958 | if (!vf_trusted) { | ||
| 2959 | dev_err(&pf->pdev->dev, | ||
| 2960 | "Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n"); | ||
| 2961 | return -EPERM; | ||
| 2962 | } else { | ||
| 2955 | dev_err(&pf->pdev->dev, | 2963 | dev_err(&pf->pdev->dev, |
| 2956 | "Cannot add more MAC addresses, trusted VF exhausted it's resources\n"); | 2964 | "Cannot add more MAC addresses, trusted VF exhausted it's resources\n"); |
| 2957 | return -EPERM; | 2965 | return -EPERM; |
| @@ -3587,7 +3595,7 @@ static int i40e_validate_cloud_filter(struct i40e_vf *vf, · 629 unmodified lines | |||
| 3587 | 3595 | ||
| 3588 | /* action_meta is TC number here to which the filter is applied */ | 3596 | /* action_meta is TC number here to which the filter is applied */ |
| 3589 | if (!tc_filter->action_meta || | 3597 | if (!tc_filter->action_meta || |
| 3590 | tc_filter->action_meta > vf->num_tc) { | 3598 | tc_filter->action_meta >= vf->num_tc) { |
| 3591 | dev_info(&pf->pdev->dev, "VF %d: Invalid TC number %u\n", | 3599 | dev_info(&pf->pdev->dev, "VF %d: Invalid TC number %u\n", |
| 3592 | vf->vf_id, tc_filter->action_meta); | 3600 | vf->vf_id, tc_filter->action_meta); |
| 3593 | goto err; | 3601 | goto err; |
| @@ -3884,6 +3892,8 @@ err: · 290 unmodified lines | |||
| 3884 | aq_ret); | 3892 | aq_ret); |
| 3885 | } | 3893 | } |
| 3886 | 3894 | ||
| 3895 | #define I40E_MAX_VF_CLOUD_FILTER 0xFF00 | ||
| 3896 | |||
| 3887 | /** | 3897 | /** |
| 3888 | * i40e_vc_add_cloud_filter | 3898 | * i40e_vc_add_cloud_filter |
| 3889 | * @vf: pointer to the VF info | 3899 | * @vf: pointer to the VF info |
| @@ -3923,6 +3933,14 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg) · 33 unmodified lines | |||
| 3923 | goto err_out; | 3933 | goto err_out; |
| 3924 | } | 3934 | } |
| 3925 | 3935 | ||
| 3936 | if (vf->num_cloud_filters >= I40E_MAX_VF_CLOUD_FILTER) { | ||
| 3937 | dev_warn(&pf->pdev->dev, | ||
| 3938 | "VF %d: Max number of filters reached, can't apply cloud filter\n", | ||
| 3939 | vf->vf_id); | ||
| 3940 | aq_ret = -ENOSPC; | ||
| 3941 | goto err_out; | ||
| 3942 | } | ||
| 3943 | |||
| 3926 | cfilter = kzalloc(sizeof(*cfilter), GFP_KERNEL); | 3944 | cfilter = kzalloc(sizeof(*cfilter), GFP_KERNEL); |
| 3927 | if (!cfilter) { | 3945 | if (!cfilter) { |
| 3928 | aq_ret = -ENOMEM; | 3946 | aq_ret = -ENOMEM; |
| @@ -41,7 +41,8 @@ enum i40e_vf_states { · 40 unmodified lines | |||
| 41 | I40E_VF_STATE_MC_PROMISC, | 41 | I40E_VF_STATE_MC_PROMISC, |
| 42 | I40E_VF_STATE_UC_PROMISC, | 42 | I40E_VF_STATE_UC_PROMISC, |
| 43 | I40E_VF_STATE_PRE_ENABLE, | 43 | I40E_VF_STATE_PRE_ENABLE, |
| 44 | I40E_VF_STATE_RESETTING | 44 | I40E_VF_STATE_RESETTING, |
| 45 | I40E_VF_STATE_RESOURCES_LOADED, | ||
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 47 | /* VF capabilities */ | 48 | /* VF capabilities */ |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | static const char * const libie_aq_str_arr[] = { | 7 | static const char * const libie_aq_str_arr[] = { |
| 8 | #define LIBIE_AQ_STR(x) \ | 8 | #define LIBIE_AQ_STR(x) \ |
| 9 | [LIBIE_AQ_RC_##x] = "LIBIE_AQ_RC" #x | 9 | [LIBIE_AQ_RC_##x] = "LIBIE_AQ_RC_" #x |
| 10 | LIBIE_AQ_STR(OK), | 10 | LIBIE_AQ_STR(OK), |
| 11 | LIBIE_AQ_STR(EPERM), | 11 | LIBIE_AQ_STR(EPERM), |
| 12 | LIBIE_AQ_STR(ENOENT), | 12 | LIBIE_AQ_STR(ENOENT), |
| @@ -21,8 +21,7 @@ · 20 unmodified lines | |||
| 21 | #include "rvu.h" | 21 | #include "rvu.h" |
| 22 | #include "lmac_common.h" | 22 | #include "lmac_common.h" |
| 23 | 23 | ||
| 24 | #define DRV_NAME "Marvell-CGX/RPM" | 24 | #define DRV_NAME "Marvell-CGX-RPM" |
| 25 | #define DRV_STRING "Marvell CGX/RPM Driver" | ||
| 26 | 25 | ||
| 27 | #define CGX_RX_STAT_GLOBAL_INDEX 9 | 26 | #define CGX_RX_STAT_GLOBAL_INDEX 9 |
| 28 | 27 | ||
| @@ -1326,7 +1326,6 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, · 1325 unmodified lines | |||
| 1326 | 1326 | ||
| 1327 | free_leaf: | 1327 | free_leaf: |
| 1328 | otx2_tc_del_from_flow_list(flow_cfg, new_node); | 1328 | otx2_tc_del_from_flow_list(flow_cfg, new_node); |
| 1329 | kfree_rcu(new_node, rcu); | ||
| 1330 | if (new_node->is_act_police) { | 1329 | if (new_node->is_act_police) { |
| 1331 | mutex_lock(&nic->mbox.lock); | 1330 | mutex_lock(&nic->mbox.lock); |
| 1332 | 1331 | ||
| @@ -1346,6 +1345,7 @@ free_leaf: · 13 unmodified lines | |||
| 1346 | 1345 | ||
| 1347 | mutex_unlock(&nic->mbox.lock); | 1346 | mutex_unlock(&nic->mbox.lock); |
| 1348 | } | 1347 | } |
| 1348 | kfree_rcu(new_node, rcu); | ||
| 1349 | 1349 | ||
| 1350 | return rc; | 1350 | return rc; |
| 1351 | } | 1351 | } |
| @@ -1466,6 +1466,7 @@ static void fec_set_block_stats(struct mlx5e_priv *priv, · 1465 unmodified lines | |||
| 1466 | case MLX5E_FEC_RS_528_514: | 1466 | case MLX5E_FEC_RS_528_514: |
| 1467 | case MLX5E_FEC_RS_544_514: | 1467 | case MLX5E_FEC_RS_544_514: |
| 1468 | case MLX5E_FEC_LLRS_272_257_1: | 1468 | case MLX5E_FEC_LLRS_272_257_1: |
| 1469 | case MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD: | ||
| 1469 | fec_set_rs_stats(fec_stats, out); | 1470 | fec_set_rs_stats(fec_stats, out); |
| 1470 | return; | 1471 | return; |
| 1471 | case MLX5E_FEC_FIRECODE: | 1472 | case MLX5E_FEC_FIRECODE: |
| @@ -663,7 +663,7 @@ static void del_sw_hw_rule(struct fs_node *node) · 662 unmodified lines | |||
| 663 | BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION) | | 663 | BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION) | |
| 664 | BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS); | 664 | BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS); |
| 665 | fte->act_dests.action.action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT; | 665 | fte->act_dests.action.action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT; |
| 666 | mlx5_fc_local_destroy(rule->dest_attr.counter); | 666 | mlx5_fc_local_put(rule->dest_attr.counter); |
| 667 | goto out; | 667 | goto out; |
| 668 | } | 668 | } |
| 669 | 669 | ||
| @@ -343,6 +343,7 @@ struct mlx5_fc { · 342 unmodified lines | |||
| 343 | enum mlx5_fc_type type; | 343 | enum mlx5_fc_type type; |
| 344 | struct mlx5_fc_bulk *bulk; | 344 | struct mlx5_fc_bulk *bulk; |
| 345 | struct mlx5_fc_cache cache; | 345 | struct mlx5_fc_cache cache; |
| 346 | refcount_t fc_local_refcount; | ||
| 346 | /* last{packets,bytes} are used for calculating deltas since last reading. */ | 347 | /* last{packets,bytes} are used for calculating deltas since last reading. */ |
| 347 | u64 lastpackets; | 348 | u64 lastpackets; |
| 348 | u64 lastbytes; | 349 | u64 lastbytes; |
| @@ -562,17 +562,36 @@ mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size) · 561 unmodified lines | |||
| 562 | counter->id = counter_id; | 562 | counter->id = counter_id; |
| 563 | fc_bulk->base_id = counter_id - offset; | 563 | fc_bulk->base_id = counter_id - offset; |
| 564 | fc_bulk->fs_bulk.bulk_len = bulk_size; | 564 | fc_bulk->fs_bulk.bulk_len = bulk_size; |
| 565 | refcount_set(&fc_bulk->hws_data.hws_action_refcount, 0); | ||
| 566 | mutex_init(&fc_bulk->hws_data.lock); | ||
| 565 | counter->bulk = fc_bulk; | 567 | counter->bulk = fc_bulk; |
| 568 | refcount_set(&counter->fc_local_refcount, 1); | ||
| 566 | return counter; | 569 | return counter; |
| 567 | } | 570 | } |
| 568 | EXPORT_SYMBOL(mlx5_fc_local_create); | 571 | EXPORT_SYMBOL(mlx5_fc_local_create); |
| 569 | 572 | ||
| 570 | void mlx5_fc_local_destroy(struct mlx5_fc *counter) | 573 | void mlx5_fc_local_destroy(struct mlx5_fc *counter) |
| 571 | { | 574 | { |
| 572 | if (!counter || counter->type != MLX5_FC_TYPE_LOCAL) | ||
| 573 | return; | ||
| 574 | |||
| 575 | kfree(counter->bulk); | 575 | kfree(counter->bulk); |
| 576 | kfree(counter); | 576 | kfree(counter); |
| 577 | } | 577 | } |
| 578 | EXPORT_SYMBOL(mlx5_fc_local_destroy); | 578 | EXPORT_SYMBOL(mlx5_fc_local_destroy); |
| 579 | |||
| 580 | void mlx5_fc_local_get(struct mlx5_fc *counter) | ||
| 581 | { | ||
| 582 | if (!counter || counter->type != MLX5_FC_TYPE_LOCAL) | ||
| 583 | return; | ||
| 584 | |||
| 585 | refcount_inc(&counter->fc_local_refcount); | ||
| 586 | } | ||
| 587 | |||
| 588 | void mlx5_fc_local_put(struct mlx5_fc *counter) | ||
| 589 | { | ||
| 590 | if (!counter || counter->type != MLX5_FC_TYPE_LOCAL) | ||
| 591 | return; | ||
| 592 | |||
| 593 | if (!refcount_dec_and_test(&counter->fc_local_refcount)) | ||
| 594 | return; | ||
| 595 | |||
| 596 | mlx5_fc_local_destroy(counter); | ||
| 597 | } | ||
| @@ -1360,7 +1360,7 @@ free_action: · 1359 unmodified lines | |||
| 1360 | struct mlx5hws_action * | 1360 | struct mlx5hws_action * |
| 1361 | mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest, | 1361 | mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest, |
| 1362 | struct mlx5hws_action_dest_attr *dests, | 1362 | struct mlx5hws_action_dest_attr *dests, |
| 1363 | bool ignore_flow_level, u32 flags) | 1363 | u32 flags) |
| 1364 | { | 1364 | { |
| 1365 | struct mlx5hws_cmd_set_fte_dest *dest_list = NULL; | 1365 | struct mlx5hws_cmd_set_fte_dest *dest_list = NULL; |
| 1366 | struct mlx5hws_cmd_ft_create_attr ft_attr = {0}; | 1366 | struct mlx5hws_cmd_ft_create_attr ft_attr = {0}; |
| @@ -1397,7 +1397,7 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest, · 30 unmodified lines | |||
| 1397 | MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; | 1397 | MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; |
| 1398 | dest_list[i].destination_id = dests[i].dest->dest_obj.obj_id; | 1398 | dest_list[i].destination_id = dests[i].dest->dest_obj.obj_id; |
| 1399 | fte_attr.action_flags |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; | 1399 | fte_attr.action_flags |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; |
| 1400 | fte_attr.ignore_flow_level = ignore_flow_level; | 1400 | fte_attr.ignore_flow_level = 1; |
| 1401 | if (dests[i].is_wire_ft) | 1401 | if (dests[i].is_wire_ft) |
| 1402 | last_dest_idx = i; | 1402 | last_dest_idx = i; |
| 1403 | break; | 1403 | break; |
| @@ -572,12 +572,12 @@ static void mlx5_fs_put_dest_action_sampler(struct mlx5_fs_hws_context *fs_ctx, · 571 unmodified lines | |||
| 572 | static struct mlx5hws_action * | 572 | static struct mlx5hws_action * |
| 573 | mlx5_fs_create_action_dest_array(struct mlx5hws_context *ctx, | 573 | mlx5_fs_create_action_dest_array(struct mlx5hws_context *ctx, |
| 574 | struct mlx5hws_action_dest_attr *dests, | 574 | struct mlx5hws_action_dest_attr *dests, |
| 575 | u32 num_of_dests, bool ignore_flow_level) | 575 | u32 num_of_dests) |
| 576 | { | 576 | { |
| 577 | u32 flags = MLX5HWS_ACTION_FLAG_HWS_FDB | MLX5HWS_ACTION_FLAG_SHARED; | 577 | u32 flags = MLX5HWS_ACTION_FLAG_HWS_FDB | MLX5HWS_ACTION_FLAG_SHARED; |
| 578 | 578 | ||
| 579 | return mlx5hws_action_create_dest_array(ctx, num_of_dests, dests, | 579 | return mlx5hws_action_create_dest_array(ctx, num_of_dests, dests, |
| 580 | ignore_flow_level, flags); | 580 | flags); |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | static struct mlx5hws_action * | 583 | static struct mlx5hws_action * |
| @@ -1014,19 +1014,14 @@ static int mlx5_fs_fte_get_hws_actions(struct mlx5_flow_root_namespace *ns, · 430 unmodified lines | |||
| 1014 | } | 1014 | } |
| 1015 | (*ractions)[num_actions++].action = dest_actions->dest; | 1015 | (*ractions)[num_actions++].action = dest_actions->dest; |
| 1016 | } else if (num_dest_actions > 1) { | 1016 | } else if (num_dest_actions > 1) { |
| 1017 | bool ignore_flow_level; | ||
| 1018 | |||
| 1019 | if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX || | 1017 | if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX || |
| 1020 | num_fs_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) { | 1018 | num_fs_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) { |
| 1021 | err = -EOPNOTSUPP; | 1019 | err = -EOPNOTSUPP; |
| 1022 | goto free_actions; | 1020 | goto free_actions; |
| 1023 | } | 1021 | } |
| 1024 | ignore_flow_level = | ||
| 1025 | !!(fte_action->flags & FLOW_ACT_IGNORE_FLOW_LEVEL); | ||
| 1026 | tmp_action = | 1022 | tmp_action = |
| 1027 | mlx5_fs_create_action_dest_array(ctx, dest_actions, | 1023 | mlx5_fs_create_action_dest_array(ctx, dest_actions, |
| 1028 | num_dest_actions, | 1024 | num_dest_actions); |
| 1029 | ignore_flow_level); | ||
| 1030 | if (!tmp_action) { | 1025 | if (!tmp_action) { |
| 1031 | err = -EOPNOTSUPP; | 1026 | err = -EOPNOTSUPP; |
| 1032 | goto free_actions; | 1027 | goto free_actions; |
| @@ -407,15 +407,21 @@ struct mlx5hws_action *mlx5_fc_get_hws_action(struct mlx5hws_context *ctx, · 406 unmodified lines | |||
| 407 | { | 407 | { |
| 408 | struct mlx5_fs_hws_create_action_ctx create_ctx; | 408 | struct mlx5_fs_hws_create_action_ctx create_ctx; |
| 409 | struct mlx5_fc_bulk *fc_bulk = counter->bulk; | 409 | struct mlx5_fc_bulk *fc_bulk = counter->bulk; |
| 410 | struct mlx5hws_action *hws_action; | ||
| 410 | 411 | ||
| 411 | create_ctx.hws_ctx = ctx; | 412 | create_ctx.hws_ctx = ctx; |
| 412 | create_ctx.id = fc_bulk->base_id; | 413 | create_ctx.id = fc_bulk->base_id; |
| 413 | create_ctx.actions_type = MLX5HWS_ACTION_TYP_CTR; | 414 | create_ctx.actions_type = MLX5HWS_ACTION_TYP_CTR; |
| 414 | 415 | ||
| 415 | return mlx5_fs_get_hws_action(&fc_bulk->hws_data, &create_ctx); | 416 | mlx5_fc_local_get(counter); |
| 417 | hws_action = mlx5_fs_get_hws_action(&fc_bulk->hws_data, &create_ctx); | ||
| 418 | if (!hws_action) | ||
| 419 | mlx5_fc_local_put(counter); | ||
| 420 | return hws_action; | ||
| 416 | } | 421 | } |
| 417 | 422 | ||
| 418 | void mlx5_fc_put_hws_action(struct mlx5_fc *counter) | 423 | void mlx5_fc_put_hws_action(struct mlx5_fc *counter) |
| 419 | { | 424 | { |
| 420 | mlx5_fs_put_hws_action(&counter->bulk->hws_data); | 425 | mlx5_fs_put_hws_action(&counter->bulk->hws_data); |
| 426 | mlx5_fc_local_put(counter); | ||
| 421 | } | 427 | } |
| @@ -735,7 +735,6 @@ mlx5hws_action_create_push_vlan(struct mlx5hws_context *ctx, u32 flags); · 734 unmodified lines | |||
| 735 | * @num_dest: The number of dests attributes. | 735 | * @num_dest: The number of dests attributes. |
| 736 | * @dests: The destination array. Each contains a destination action and can | 736 | * @dests: The destination array. Each contains a destination action and can |
| 737 | * have additional actions. | 737 | * have additional actions. |
| 738 | * @ignore_flow_level: Whether to turn on 'ignore_flow_level' for this dest. | ||
| 739 | * @flags: Action creation flags (enum mlx5hws_action_flags). | 738 | * @flags: Action creation flags (enum mlx5hws_action_flags). |
| 740 | * | 739 | * |
| 741 | * Return: pointer to mlx5hws_action on success NULL otherwise. | 740 | * Return: pointer to mlx5hws_action on success NULL otherwise. |
| @@ -743,7 +742,7 @@ mlx5hws_action_create_push_vlan(struct mlx5hws_context *ctx, u32 flags); · 1 unmodified line | |||
| 743 | struct mlx5hws_action * | 742 | struct mlx5hws_action * |
| 744 | mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest, | 743 | mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest, |
| 745 | struct mlx5hws_action_dest_attr *dests, | 744 | struct mlx5hws_action_dest_attr *dests, |
| 746 | bool ignore_flow_level, u32 flags); | 745 | u32 flags); |
| 747 | 746 | ||
| 748 | /** | 747 | /** |
| 749 | * mlx5hws_action_create_insert_header - Create insert header action. | 748 | * mlx5hws_action_create_insert_header - Create insert header action. |
| @@ -597,10 +597,6 @@ static int bcm_ptp_perout_locked(struct bcm_ptp_private *priv, · 596 unmodified lines | |||
| 597 | 597 | ||
| 598 | period = BCM_MAX_PERIOD_8NS; /* write nonzero value */ | 598 | period = BCM_MAX_PERIOD_8NS; /* write nonzero value */ |
| 599 | 599 | ||
| 600 | /* Reject unsupported flags */ | ||
| 601 | if (req->flags & ~PTP_PEROUT_DUTY_CYCLE) | ||
| 602 | return -EOPNOTSUPP; | ||
| 603 | |||
| 604 | if (req->flags & PTP_PEROUT_DUTY_CYCLE) | 600 | if (req->flags & PTP_PEROUT_DUTY_CYCLE) |
| 605 | pulse = ktime_to_ns(ktime_set(req->on.sec, req->on.nsec)); | 601 | pulse = ktime_to_ns(ktime_set(req->on.sec, req->on.nsec)); |
| 606 | else | 602 | else |
| @@ -741,6 +737,8 @@ static const struct ptp_clock_info bcm_ptp_clock_info = { · 134 unmodified lines | |||
| 741 | .n_pins = 1, | 737 | .n_pins = 1, |
| 742 | .n_per_out = 1, | 738 | .n_per_out = 1, |
| 743 | .n_ext_ts = 1, | 739 | .n_ext_ts = 1, |
| 740 | .supported_perout_flags = PTP_PEROUT_DUTY_CYCLE, | ||
| 741 | .supported_extts_flags = PTP_STRICT_FLAGS | PTP_RISING_EDGE, | ||
| 744 | }; | 742 | }; |
| 745 | 743 | ||
| 746 | static void bcm_ptp_txtstamp(struct mii_timestamper *mii_ts, | 744 | static void bcm_ptp_txtstamp(struct mii_timestamper *mii_ts, |
| @@ -1875,6 +1875,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, · 1874 unmodified lines | |||
| 1875 | local_bh_enable(); | 1875 | local_bh_enable(); |
| 1876 | goto unlock_frags; | 1876 | goto unlock_frags; |
| 1877 | } | 1877 | } |
| 1878 | |||
| 1879 | if (frags && skb != tfile->napi.skb) | ||
| 1880 | tfile->napi.skb = skb; | ||
| 1878 | } | 1881 | } |
| 1879 | rcu_read_unlock(); | 1882 | rcu_read_unlock(); |
| 1880 | local_bh_enable(); | 1883 | local_bh_enable(); |
| @@ -308,6 +308,8 @@ struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging); · 307 unmodified lines | |||
| 308 | void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter); | 308 | void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter); |
| 309 | struct mlx5_fc *mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size); | 309 | struct mlx5_fc *mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size); |
| 310 | void mlx5_fc_local_destroy(struct mlx5_fc *counter); | 310 | void mlx5_fc_local_destroy(struct mlx5_fc *counter); |
| 311 | void mlx5_fc_local_get(struct mlx5_fc *counter); | ||
| 312 | void mlx5_fc_local_put(struct mlx5_fc *counter); | ||
| 311 | u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter); | 313 | u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter); |
| 312 | void mlx5_fc_query_cached(struct mlx5_fc *counter, | 314 | void mlx5_fc_query_cached(struct mlx5_fc *counter, |
| 313 | u64 *bytes, u64 *packets, u64 *lastuse); | 315 | u64 *bytes, u64 *packets, u64 *lastuse); |
| @@ -1245,6 +1245,27 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev, · 1244 unmodified lines | |||
| 1245 | return NULL; | 1245 | return NULL; |
| 1246 | } | 1246 | } |
| 1247 | 1247 | ||
| 1248 | static inline struct hci_conn *hci_conn_hash_lookup_role(struct hci_dev *hdev, | ||
| 1249 | __u8 type, __u8 role, | ||
| 1250 | bdaddr_t *ba) | ||
| 1251 | { | ||
| 1252 | struct hci_conn_hash *h = &hdev->conn_hash; | ||
| 1253 | struct hci_conn *c; | ||
| 1254 | |||
| 1255 | rcu_read_lock(); | ||
| 1256 | |||
| 1257 | list_for_each_entry_rcu(c, &h->list, list) { | ||
| 1258 | if (c->type == type && c->role == role && !bacmp(&c->dst, ba)) { | ||
| 1259 | rcu_read_unlock(); | ||
| 1260 | return c; | ||
| 1261 | } | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | rcu_read_unlock(); | ||
| 1265 | |||
| 1266 | return NULL; | ||
| 1267 | } | ||
| 1268 | |||
| 1248 | static inline struct hci_conn *hci_conn_hash_lookup_le(struct hci_dev *hdev, | 1269 | static inline struct hci_conn *hci_conn_hash_lookup_le(struct hci_dev *hdev, |
| 1249 | bdaddr_t *ba, | 1270 | bdaddr_t *ba, |
| 1250 | __u8 ba_type) | 1271 | __u8 ba_type) |
| @@ -37,6 +37,9 @@ · 36 unmodified lines | |||
| 37 | 37 | ||
| 38 | /* | 38 | /* |
| 39 | * flag fields valid for the new PTP_EXTTS_REQUEST2 ioctl. | 39 | * flag fields valid for the new PTP_EXTTS_REQUEST2 ioctl. |
| 40 | * | ||
| 41 | * Note: PTP_STRICT_FLAGS is always enabled by the kernel for | ||
| 42 | * PTP_EXTTS_REQUEST2 regardless of whether it is set by userspace. | ||
| 40 | */ | 43 | */ |
| 41 | #define PTP_EXTTS_VALID_FLAGS (PTP_ENABLE_FEATURE | \ | 44 | #define PTP_EXTTS_VALID_FLAGS (PTP_ENABLE_FEATURE | \ |
| 42 | PTP_RISING_EDGE | \ | 45 | PTP_RISING_EDGE | \ |
| @@ -3087,8 +3087,18 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, · 3086 unmodified lines | |||
| 3087 | 3087 | ||
| 3088 | hci_dev_lock(hdev); | 3088 | hci_dev_lock(hdev); |
| 3089 | 3089 | ||
| 3090 | /* Check for existing connection: | ||
| 3091 | * | ||
| 3092 | * 1. If it doesn't exist then it must be receiver/slave role. | ||
| 3093 | * 2. If it does exist confirm that it is connecting/BT_CONNECT in case | ||
| 3094 | * of initiator/master role since there could be a collision where | ||
| 3095 | * either side is attempting to connect or something like a fuzzing | ||
| 3096 | * testing is trying to play tricks to destroy the hcon object before | ||
| 3097 | * it even attempts to connect (e.g. hcon->state == BT_OPEN). | ||
| 3098 | */ | ||
| 3090 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | 3099 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); |
| 3091 | if (!conn) { | 3100 | if (!conn || |
| 3101 | (conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) { | ||
| 3092 | /* In case of error status and there is no connection pending | 3102 | /* In case of error status and there is no connection pending |
| 3093 | * just unlock as there is nothing to cleanup. | 3103 | * just unlock as there is nothing to cleanup. |
| 3094 | */ | 3104 | */ |
| @@ -4391,6 +4401,8 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, · 1296 unmodified lines | |||
| 4391 | 4401 | ||
| 4392 | bt_dev_dbg(hdev, "num %d", ev->num); | 4402 | bt_dev_dbg(hdev, "num %d", ev->num); |
| 4393 | 4403 | ||
| 4404 | hci_dev_lock(hdev); | ||
| 4405 | |||
| 4394 | for (i = 0; i < ev->num; i++) { | 4406 | for (i = 0; i < ev->num; i++) { |
| 4395 | struct hci_comp_pkts_info *info = &ev->handles[i]; | 4407 | struct hci_comp_pkts_info *info = &ev->handles[i]; |
| 4396 | struct hci_conn *conn; | 4408 | struct hci_conn *conn; |
| @@ -4472,6 +4484,8 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, · 75 unmodified lines | |||
| 4472 | } | 4484 | } |
| 4473 | 4485 | ||
| 4474 | queue_work(hdev->workqueue, &hdev->tx_work); | 4486 | queue_work(hdev->workqueue, &hdev->tx_work); |
| 4487 | |||
| 4488 | hci_dev_unlock(hdev); | ||
| 4475 | } | 4489 | } |
| 4476 | 4490 | ||
| 4477 | static void hci_mode_change_evt(struct hci_dev *hdev, void *data, | 4491 | static void hci_mode_change_evt(struct hci_dev *hdev, void *data, |
| @@ -5634,8 +5648,18 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, · 1156 unmodified lines | |||
| 5634 | */ | 5648 | */ |
| 5635 | hci_dev_clear_flag(hdev, HCI_LE_ADV); | 5649 | hci_dev_clear_flag(hdev, HCI_LE_ADV); |
| 5636 | 5650 | ||
| 5637 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr); | 5651 | /* Check for existing connection: |
| 5638 | if (!conn) { | 5652 | * |
| 5653 | * 1. If it doesn't exist then use the role to create a new object. | ||
| 5654 | * 2. If it does exist confirm that it is connecting/BT_CONNECT in case | ||
| 5655 | * of initiator/master role since there could be a collision where | ||
| 5656 | * either side is attempting to connect or something like a fuzzing | ||
| 5657 | * testing is trying to play tricks to destroy the hcon object before | ||
| 5658 | * it even attempts to connect (e.g. hcon->state == BT_OPEN). | ||
| 5659 | */ | ||
| 5660 | conn = hci_conn_hash_lookup_role(hdev, LE_LINK, role, bdaddr); | ||
| 5661 | if (!conn || | ||
| 5662 | (conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) { | ||
| 5639 | /* In case of error status and there is no connection pending | 5663 | /* In case of error status and there is no connection pending |
| 5640 | * just unlock as there is nothing to cleanup. | 5664 | * just unlock as there is nothing to cleanup. |
| 5641 | */ | 5665 | */ |
| @@ -2594,6 +2594,13 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev) · 2593 unmodified lines | |||
| 2594 | hci_remove_ext_adv_instance_sync(hdev, adv->instance, | 2594 | hci_remove_ext_adv_instance_sync(hdev, adv->instance, |
| 2595 | NULL); | 2595 | NULL); |
| 2596 | } | 2596 | } |
| 2597 | |||
| 2598 | /* If current advertising instance is set to instance 0x00 | ||
| 2599 | * then we need to re-enable it. | ||
| 2600 | */ | ||
| 2601 | if (!hdev->cur_adv_instance) | ||
| 2602 | err = hci_enable_ext_advertising_sync(hdev, | ||
| 2603 | hdev->cur_adv_instance); | ||
| 2597 | } else { | 2604 | } else { |
| 2598 | /* Schedule for most recent instance to be restarted and begin | 2605 | /* Schedule for most recent instance to be restarted and begin |
| 2599 | * the software rotation loop | 2606 | * the software rotation loop |
| @@ -1323,8 +1323,7 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err) · 1322 unmodified lines | |||
| 1323 | struct mgmt_mode *cp; | 1323 | struct mgmt_mode *cp; |
| 1324 | 1324 | ||
| 1325 | /* Make sure cmd still outstanding. */ | 1325 | /* Make sure cmd still outstanding. */ |
| 1326 | if (err == -ECANCELED || | 1326 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) |
| 1327 | cmd != pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
| 1328 | return; | 1327 | return; |
| 1329 | 1328 | ||
| 1330 | cp = cmd->param; | 1329 | cp = cmd->param; |
| @@ -1351,23 +1350,29 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err) · 20 unmodified lines | |||
| 1351 | mgmt_status(err)); | 1350 | mgmt_status(err)); |
| 1352 | } | 1351 | } |
| 1353 | 1352 | ||
| 1354 | mgmt_pending_remove(cmd); | 1353 | mgmt_pending_free(cmd); |
| 1355 | } | 1354 | } |
| 1356 | 1355 | ||
| 1357 | static int set_powered_sync(struct hci_dev *hdev, void *data) | 1356 | static int set_powered_sync(struct hci_dev *hdev, void *data) |
| 1358 | { | 1357 | { |
| 1359 | struct mgmt_pending_cmd *cmd = data; | 1358 | struct mgmt_pending_cmd *cmd = data; |
| 1360 | struct mgmt_mode *cp; | 1359 | struct mgmt_mode cp; |
| 1360 | |||
| 1361 | mutex_lock(&hdev->mgmt_pending_lock); | ||
| 1361 | 1362 | ||
| 1362 | /* Make sure cmd still outstanding. */ | 1363 | /* Make sure cmd still outstanding. */ |
| 1363 | if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev)) | 1364 | if (!__mgmt_pending_listed(hdev, cmd)) { |
| 1365 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 1364 | return -ECANCELED; | 1366 | return -ECANCELED; |
| 1367 | } | ||
| 1365 | 1368 | ||
| 1366 | cp = cmd->param; | 1369 | memcpy(&cp, cmd->param, sizeof(cp)); |
| 1370 | |||
| 1371 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 1367 | 1372 | ||
| 1368 | BT_DBG("%s", hdev->name); | 1373 | BT_DBG("%s", hdev->name); |
| 1369 | 1374 | ||
| 1370 | return hci_set_powered_sync(hdev, cp->val); | 1375 | return hci_set_powered_sync(hdev, cp.val); |
| 1371 | } | 1376 | } |
| 1372 | 1377 | ||
| 1373 | static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, | 1378 | static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, |
| @@ -1516,8 +1521,7 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data, · 142 unmodified lines | |||
| 1516 | bt_dev_dbg(hdev, "err %d", err); | 1521 | bt_dev_dbg(hdev, "err %d", err); |
| 1517 | 1522 | ||
| 1518 | /* Make sure cmd still outstanding. */ | 1523 | /* Make sure cmd still outstanding. */ |
| 1519 | if (err == -ECANCELED || | 1524 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) |
| 1520 | cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) | ||
| 1521 | return; | 1525 | return; |
| 1522 | 1526 | ||
| 1523 | hci_dev_lock(hdev); | 1527 | hci_dev_lock(hdev); |
| @@ -1539,12 +1543,15 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data, · 15 unmodified lines | |||
| 1539 | new_settings(hdev, cmd->sk); | 1543 | new_settings(hdev, cmd->sk); |
| 1540 | 1544 | ||
| 1541 | done: | 1545 | done: |
| 1542 | mgmt_pending_remove(cmd); | 1546 | mgmt_pending_free(cmd); |
| 1543 | hci_dev_unlock(hdev); | 1547 | hci_dev_unlock(hdev); |
| 1544 | } | 1548 | } |
| 1545 | 1549 | ||
| 1546 | static int set_discoverable_sync(struct hci_dev *hdev, void *data) | 1550 | static int set_discoverable_sync(struct hci_dev *hdev, void *data) |
| 1547 | { | 1551 | { |
| 1552 | if (!mgmt_pending_listed(hdev, data)) | ||
| 1553 | return -ECANCELED; | ||
| 1554 | |||
| 1548 | BT_DBG("%s", hdev->name); | 1555 | BT_DBG("%s", hdev->name); |
| 1549 | 1556 | ||
| 1550 | return hci_update_discoverable_sync(hdev); | 1557 | return hci_update_discoverable_sync(hdev); |
| @@ -1691,8 +1698,7 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data, · 140 unmodified lines | |||
| 1691 | bt_dev_dbg(hdev, "err %d", err); | 1698 | bt_dev_dbg(hdev, "err %d", err); |
| 1692 | 1699 | ||
| 1693 | /* Make sure cmd still outstanding. */ | 1700 | /* Make sure cmd still outstanding. */ |
| 1694 | if (err == -ECANCELED || | 1701 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) |
| 1695 | cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) | ||
| 1696 | return; | 1702 | return; |
| 1697 | 1703 | ||
| 1698 | hci_dev_lock(hdev); | 1704 | hci_dev_lock(hdev); |
| @@ -1707,7 +1713,7 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data, · 8 unmodified lines | |||
| 1707 | new_settings(hdev, cmd->sk); | 1713 | new_settings(hdev, cmd->sk); |
| 1708 | 1714 | ||
| 1709 | done: | 1715 | done: |
| 1710 | mgmt_pending_remove(cmd); | 1716 | mgmt_pending_free(cmd); |
| 1711 | 1717 | ||
| 1712 | hci_dev_unlock(hdev); | 1718 | hci_dev_unlock(hdev); |
| 1713 | } | 1719 | } |
| @@ -1743,6 +1749,9 @@ static int set_connectable_update_settings(struct hci_dev *hdev, · 29 unmodified lines | |||
| 1743 | 1749 | ||
| 1744 | static int set_connectable_sync(struct hci_dev *hdev, void *data) | 1750 | static int set_connectable_sync(struct hci_dev *hdev, void *data) |
| 1745 | { | 1751 | { |
| 1752 | if (!mgmt_pending_listed(hdev, data)) | ||
| 1753 | return -ECANCELED; | ||
| 1754 | |||
| 1746 | BT_DBG("%s", hdev->name); | 1755 | BT_DBG("%s", hdev->name); |
| 1747 | 1756 | ||
| 1748 | return hci_update_connectable_sync(hdev); | 1757 | return hci_update_connectable_sync(hdev); |
| @@ -1919,14 +1928,17 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) · 170 unmodified lines | |||
| 1919 | { | 1928 | { |
| 1920 | struct cmd_lookup match = { NULL, hdev }; | 1929 | struct cmd_lookup match = { NULL, hdev }; |
| 1921 | struct mgmt_pending_cmd *cmd = data; | 1930 | struct mgmt_pending_cmd *cmd = data; |
| 1922 | struct mgmt_mode *cp = cmd->param; | 1931 | struct mgmt_mode *cp; |
| 1923 | u8 enable = cp->val; | 1932 | u8 enable; |
| 1924 | bool changed; | 1933 | bool changed; |
| 1925 | 1934 | ||
| 1926 | /* Make sure cmd still outstanding. */ | 1935 | /* Make sure cmd still outstanding. */ |
| 1927 | if (err == -ECANCELED || cmd != pending_find(MGMT_OP_SET_SSP, hdev)) | 1936 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) |
| 1928 | return; | 1937 | return; |
| 1929 | 1938 | ||
| 1939 | cp = cmd->param; | ||
| 1940 | enable = cp->val; | ||
| 1941 | |||
| 1930 | if (err) { | 1942 | if (err) { |
| 1931 | u8 mgmt_err = mgmt_status(err); | 1943 | u8 mgmt_err = mgmt_status(err); |
| 1932 | 1944 | ||
| @@ -1935,8 +1947,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) · 2 unmodified lines | |||
| 1935 | new_settings(hdev, NULL); | 1947 | new_settings(hdev, NULL); |
| 1936 | } | 1948 | } |
| 1937 | 1949 | ||
| 1938 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true, | 1950 | mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); |
| 1939 | cmd_status_rsp, &mgmt_err); | ||
| 1940 | return; | 1951 | return; |
| 1941 | } | 1952 | } |
| 1942 | 1953 | ||
| @@ -1946,7 +1957,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) · 3 unmodified lines | |||
| 1946 | changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED); | 1957 | changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED); |
| 1947 | } | 1958 | } |
| 1948 | 1959 | ||
| 1949 | mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true, settings_rsp, &match); | 1960 | settings_rsp(cmd, &match); |
| 1950 | 1961 | ||
| 1951 | if (changed) | 1962 | if (changed) |
| 1952 | new_settings(hdev, match.sk); | 1963 | new_settings(hdev, match.sk); |
| @@ -1960,14 +1971,25 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) · 7 unmodified lines | |||
| 1960 | static int set_ssp_sync(struct hci_dev *hdev, void *data) | 1971 | static int set_ssp_sync(struct hci_dev *hdev, void *data) |
| 1961 | { | 1972 | { |
| 1962 | struct mgmt_pending_cmd *cmd = data; | 1973 | struct mgmt_pending_cmd *cmd = data; |
| 1963 | struct mgmt_mode *cp = cmd->param; | 1974 | struct mgmt_mode cp; |
| 1964 | bool changed = false; | 1975 | bool changed = false; |
| 1965 | int err; | 1976 | int err; |
| 1966 | 1977 | ||
| 1967 | if (cp->val) | 1978 | mutex_lock(&hdev->mgmt_pending_lock); |
| 1979 | |||
| 1980 | if (!__mgmt_pending_listed(hdev, cmd)) { | ||
| 1981 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 1982 | return -ECANCELED; | ||
| 1983 | } | ||
| 1984 | |||
| 1985 | memcpy(&cp, cmd->param, sizeof(cp)); | ||
| 1986 | |||
| 1987 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 1988 | |||
| 1989 | if (cp.val) | ||
| 1968 | changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED); | 1990 | changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED); |
| 1969 | 1991 | ||
| 1970 | err = hci_write_ssp_mode_sync(hdev, cp->val); | 1992 | err = hci_write_ssp_mode_sync(hdev, cp.val); |
| 1971 | 1993 | ||
| 1972 | if (!err && changed) | 1994 | if (!err && changed) |
| 1973 | hci_dev_clear_flag(hdev, HCI_SSP_ENABLED); | 1995 | hci_dev_clear_flag(hdev, HCI_SSP_ENABLED); |
| @@ -2060,32 +2082,50 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) · 86 unmodified lines | |||
| 2060 | 2082 | ||
| 2061 | static void set_le_complete(struct hci_dev *hdev, void *data, int err) | 2083 | static void set_le_complete(struct hci_dev *hdev, void *data, int err) |
| 2062 | { | 2084 | { |
| 2085 | struct mgmt_pending_cmd *cmd = data; | ||
| 2063 | struct cmd_lookup match = { NULL, hdev }; | 2086 | struct cmd_lookup match = { NULL, hdev }; |
| 2064 | u8 status = mgmt_status(err); | 2087 | u8 status = mgmt_status(err); |
| 2065 | 2088 | ||
| 2066 | bt_dev_dbg(hdev, "err %d", err); | 2089 | bt_dev_dbg(hdev, "err %d", err); |
| 2067 | 2090 | ||
| 2068 | if (status) { | 2091 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, data)) |
| 2069 | mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, cmd_status_rsp, | ||
| 2070 | &status); | ||
| 2071 | return; | 2092 | return; |
| 2093 | |||
| 2094 | if (status) { | ||
| 2095 | mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, status); | ||
| 2096 | goto done; | ||
| 2072 | } | 2097 | } |
| 2073 | 2098 | ||
| 2074 | mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, settings_rsp, &match); | 2099 | settings_rsp(cmd, &match); |
| 2075 | 2100 | ||
| 2076 | new_settings(hdev, match.sk); | 2101 | new_settings(hdev, match.sk); |
| 2077 | 2102 | ||
| 2078 | if (match.sk) | 2103 | if (match.sk) |
| 2079 | sock_put(match.sk); | 2104 | sock_put(match.sk); |
| 2105 | |||
| 2106 | done: | ||
| 2107 | mgmt_pending_free(cmd); | ||
| 2080 | } | 2108 | } |
| 2081 | 2109 | ||
| 2082 | static int set_le_sync(struct hci_dev *hdev, void *data) | 2110 | static int set_le_sync(struct hci_dev *hdev, void *data) |
| 2083 | { | 2111 | { |
| 2084 | struct mgmt_pending_cmd *cmd = data; | 2112 | struct mgmt_pending_cmd *cmd = data; |
| 2085 | struct mgmt_mode *cp = cmd->param; | 2113 | struct mgmt_mode cp; |
| 2086 | u8 val = !!cp->val; | 2114 | u8 val; |
| 2087 | int err; | 2115 | int err; |
| 2088 | 2116 | ||
| 2117 | mutex_lock(&hdev->mgmt_pending_lock); | ||
| 2118 | |||
| 2119 | if (!__mgmt_pending_listed(hdev, cmd)) { | ||
| 2120 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 2121 | return -ECANCELED; | ||
| 2122 | } | ||
| 2123 | |||
| 2124 | memcpy(&cp, cmd->param, sizeof(cp)); | ||
| 2125 | val = !!cp.val; | ||
| 2126 | |||
| 2127 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 2128 | |||
| 2089 | if (!val) { | 2129 | if (!val) { |
| 2090 | hci_clear_adv_instance_sync(hdev, NULL, 0x00, true); | 2130 | hci_clear_adv_instance_sync(hdev, NULL, 0x00, true); |
| 2091 | 2131 | ||
| @@ -2127,7 +2167,12 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err) · 35 unmodified lines | |||
| 2127 | { | 2167 | { |
| 2128 | struct mgmt_pending_cmd *cmd = data; | 2168 | struct mgmt_pending_cmd *cmd = data; |
| 2129 | u8 status = mgmt_status(err); | 2169 | u8 status = mgmt_status(err); |
| 2130 | struct sock *sk = cmd->sk; | 2170 | struct sock *sk; |
| 2171 | |||
| 2172 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) | ||
| 2173 | return; | ||
| 2174 | |||
| 2175 | sk = cmd->sk; | ||
| 2131 | 2176 | ||
| 2132 | if (status) { | 2177 | if (status) { |
| 2133 | mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true, | 2178 | mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true, |
| @@ -2142,24 +2187,37 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err) · 8 unmodified lines | |||
| 2142 | static int set_mesh_sync(struct hci_dev *hdev, void *data) | 2187 | static int set_mesh_sync(struct hci_dev *hdev, void *data) |
| 2143 | { | 2188 | { |
| 2144 | struct mgmt_pending_cmd *cmd = data; | 2189 | struct mgmt_pending_cmd *cmd = data; |
| 2145 | struct mgmt_cp_set_mesh *cp = cmd->param; | 2190 | struct mgmt_cp_set_mesh cp; |
| 2146 | size_t len = cmd->param_len; | 2191 | size_t len; |
| 2192 | |||
| 2193 | mutex_lock(&hdev->mgmt_pending_lock); | ||
| 2194 | |||
| 2195 | if (!__mgmt_pending_listed(hdev, cmd)) { | ||
| 2196 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 2197 | return -ECANCELED; | ||
| 2198 | } | ||
| 2199 | |||
| 2200 | memcpy(&cp, cmd->param, sizeof(cp)); | ||
| 2201 | |||
| 2202 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 2203 | |||
| 2204 | len = cmd->param_len; | ||
| 2147 | 2205 | ||
| 2148 | memset(hdev->mesh_ad_types, 0, sizeof(hdev->mesh_ad_types)); | 2206 | memset(hdev->mesh_ad_types, 0, sizeof(hdev->mesh_ad_types)); |
| 2149 | 2207 | ||
| 2150 | if (cp->enable) | 2208 | if (cp.enable) |
| 2151 | hci_dev_set_flag(hdev, HCI_MESH); | 2209 | hci_dev_set_flag(hdev, HCI_MESH); |
| 2152 | else | 2210 | else |
| 2153 | hci_dev_clear_flag(hdev, HCI_MESH); | 2211 | hci_dev_clear_flag(hdev, HCI_MESH); |
| 2154 | 2212 | ||
| 2155 | hdev->le_scan_interval = __le16_to_cpu(cp->period); | 2213 | hdev->le_scan_interval = __le16_to_cpu(cp.period); |
| 2156 | hdev->le_scan_window = __le16_to_cpu(cp->window); | 2214 | hdev->le_scan_window = __le16_to_cpu(cp.window); |
| 2157 | 2215 | ||
| 2158 | len -= sizeof(*cp); | 2216 | len -= sizeof(cp); |
| 2159 | 2217 | ||
| 2160 | /* If filters don't fit, forward all adv pkts */ | 2218 | /* If filters don't fit, forward all adv pkts */ |
| 2161 | if (len <= sizeof(hdev->mesh_ad_types)) | 2219 | if (len <= sizeof(hdev->mesh_ad_types)) |
| 2162 | memcpy(hdev->mesh_ad_types, cp->ad_types, len); | 2220 | memcpy(hdev->mesh_ad_types, cp.ad_types, len); |
| 2163 | 2221 | ||
| 2164 | hci_update_passive_scan_sync(hdev); | 2222 | hci_update_passive_scan_sync(hdev); |
| 2165 | return 0; | 2223 | return 0; |
| @@ -3867,15 +3925,16 @@ static int name_changed_sync(struct hci_dev *hdev, void *data) · 1701 unmodified lines | |||
| 3867 | static void set_name_complete(struct hci_dev *hdev, void *data, int err) | 3925 | static void set_name_complete(struct hci_dev *hdev, void *data, int err) |
| 3868 | { | 3926 | { |
| 3869 | struct mgmt_pending_cmd *cmd = data; | 3927 | struct mgmt_pending_cmd *cmd = data; |
| 3870 | struct mgmt_cp_set_local_name *cp = cmd->param; | 3928 | struct mgmt_cp_set_local_name *cp; |
| 3871 | u8 status = mgmt_status(err); | 3929 | u8 status = mgmt_status(err); |
| 3872 | 3930 | ||
| 3873 | bt_dev_dbg(hdev, "err %d", err); | 3931 | bt_dev_dbg(hdev, "err %d", err); |
| 3874 | 3932 | ||
| 3875 | if (err == -ECANCELED || | 3933 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) |
| 3876 | cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev)) | ||
| 3877 | return; | 3934 | return; |
| 3878 | 3935 | ||
| 3936 | cp = cmd->param; | ||
| 3937 | |||
| 3879 | if (status) { | 3938 | if (status) { |
| 3880 | mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, | 3939 | mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, |
| 3881 | status); | 3940 | status); |
| @@ -3887,16 +3946,27 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err) · 5 unmodified lines | |||
| 3887 | hci_cmd_sync_queue(hdev, name_changed_sync, NULL, NULL); | 3946 | hci_cmd_sync_queue(hdev, name_changed_sync, NULL, NULL); |
| 3888 | } | 3947 | } |
| 3889 | 3948 | ||
| 3890 | mgmt_pending_remove(cmd); | 3949 | mgmt_pending_free(cmd); |
| 3891 | } | 3950 | } |
| 3892 | 3951 | ||
| 3893 | static int set_name_sync(struct hci_dev *hdev, void *data) | 3952 | static int set_name_sync(struct hci_dev *hdev, void *data) |
| 3894 | { | 3953 | { |
| 3895 | struct mgmt_pending_cmd *cmd = data; | 3954 | struct mgmt_pending_cmd *cmd = data; |
| 3896 | struct mgmt_cp_set_local_name *cp = cmd->param; | 3955 | struct mgmt_cp_set_local_name cp; |
| 3956 | |||
| 3957 | mutex_lock(&hdev->mgmt_pending_lock); | ||
| 3958 | |||
| 3959 | if (!__mgmt_pending_listed(hdev, cmd)) { | ||
| 3960 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 3961 | return -ECANCELED; | ||
| 3962 | } | ||
| 3963 | |||
| 3964 | memcpy(&cp, cmd->param, sizeof(cp)); | ||
| 3965 | |||
| 3966 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 3897 | 3967 | ||
| 3898 | if (lmp_bredr_capable(hdev)) { | 3968 | if (lmp_bredr_capable(hdev)) { |
| 3899 | hci_update_name_sync(hdev, cp->name); | 3969 | hci_update_name_sync(hdev, cp.name); |
| 3900 | hci_update_eir_sync(hdev); | 3970 | hci_update_eir_sync(hdev); |
| 3901 | } | 3971 | } |
| 3902 | 3972 | ||
| @@ -4048,12 +4118,10 @@ int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip) · 145 unmodified lines | |||
| 4048 | static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err) | 4118 | static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err) |
| 4049 | { | 4119 | { |
| 4050 | struct mgmt_pending_cmd *cmd = data; | 4120 | struct mgmt_pending_cmd *cmd = data; |
| 4051 | struct sk_buff *skb = cmd->skb; | 4121 | struct sk_buff *skb; |
| 4052 | u8 status = mgmt_status(err); | 4122 | u8 status = mgmt_status(err); |
| 4053 | 4123 | ||
| 4054 | if (err == -ECANCELED || | 4124 | skb = cmd->skb; |
| 4055 | cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev)) | ||
| 4056 | return; | ||
| 4057 | 4125 | ||
| 4058 | if (!status) { | 4126 | if (!status) { |
| 4059 | if (!skb) | 4127 | if (!skb) |
| @@ -4080,7 +4148,7 @@ static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err) · 20 unmodified lines | |||
| 4080 | if (skb && !IS_ERR(skb)) | 4148 | if (skb && !IS_ERR(skb)) |
| 4081 | kfree_skb(skb); | 4149 | kfree_skb(skb); |
| 4082 | 4150 | ||
| 4083 | mgmt_pending_remove(cmd); | 4151 | mgmt_pending_free(cmd); |
| 4084 | } | 4152 | } |
| 4085 | 4153 | ||
| 4086 | static int set_default_phy_sync(struct hci_dev *hdev, void *data) | 4154 | static int set_default_phy_sync(struct hci_dev *hdev, void *data) |
| @@ -4088,7 +4156,9 @@ static int set_default_phy_sync(struct hci_dev *hdev, void *data) · 1 unmodified line | |||
| 4088 | struct mgmt_pending_cmd *cmd = data; | 4156 | struct mgmt_pending_cmd *cmd = data; |
| 4089 | struct mgmt_cp_set_phy_configuration *cp = cmd->param; | 4157 | struct mgmt_cp_set_phy_configuration *cp = cmd->param; |
| 4090 | struct hci_cp_le_set_default_phy cp_phy; | 4158 | struct hci_cp_le_set_default_phy cp_phy; |
| 4091 | u32 selected_phys = __le32_to_cpu(cp->selected_phys); | 4159 | u32 selected_phys; |
| 4160 | |||
| 4161 | selected_phys = __le32_to_cpu(cp->selected_phys); | ||
| 4092 | 4162 | ||
| 4093 | memset(&cp_phy, 0, sizeof(cp_phy)); | 4163 | memset(&cp_phy, 0, sizeof(cp_phy)); |
| 4094 | 4164 | ||
| @@ -4228,7 +4298,7 @@ static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev, · 133 unmodified lines | |||
| 4228 | goto unlock; | 4298 | goto unlock; |
| 4229 | } | 4299 | } |
| 4230 | 4300 | ||
| 4231 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data, | 4301 | cmd = mgmt_pending_new(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data, |
| 4232 | len); | 4302 | len); |
| 4233 | if (!cmd) | 4303 | if (!cmd) |
| 4234 | err = -ENOMEM; | 4304 | err = -ENOMEM; |
| @@ -5189,7 +5259,17 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, · 954 unmodified lines | |||
| 5189 | { | 5259 | { |
| 5190 | struct mgmt_rp_add_adv_patterns_monitor rp; | 5260 | struct mgmt_rp_add_adv_patterns_monitor rp; |
| 5191 | struct mgmt_pending_cmd *cmd = data; | 5261 | struct mgmt_pending_cmd *cmd = data; |
| 5192 | struct adv_monitor *monitor = cmd->user_data; | 5262 | struct adv_monitor *monitor; |
| 5263 | |||
| 5264 | /* This is likely the result of hdev being closed and mgmt_index_removed | ||
| 5265 | * is attempting to clean up any pending command so | ||
| 5266 | * hci_adv_monitors_clear is about to be called which will take care of | ||
| 5267 | * freeing the adv_monitor instances. | ||
| 5268 | */ | ||
| 5269 | if (status == -ECANCELED && !mgmt_pending_valid(hdev, cmd)) | ||
| 5270 | return; | ||
| 5271 | |||
| 5272 | monitor = cmd->user_data; | ||
| 5193 | 5273 | ||
| 5194 | hci_dev_lock(hdev); | 5274 | hci_dev_lock(hdev); |
| 5195 | 5275 | ||
| @@ -5215,9 +5295,20 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, · 19 unmodified lines | |||
| 5215 | static int mgmt_add_adv_patterns_monitor_sync(struct hci_dev *hdev, void *data) | 5295 | static int mgmt_add_adv_patterns_monitor_sync(struct hci_dev *hdev, void *data) |
| 5216 | { | 5296 | { |
| 5217 | struct mgmt_pending_cmd *cmd = data; | 5297 | struct mgmt_pending_cmd *cmd = data; |
| 5218 | struct adv_monitor *monitor = cmd->user_data; | 5298 | struct adv_monitor *mon; |
| 5299 | |||
| 5300 | mutex_lock(&hdev->mgmt_pending_lock); | ||
| 5301 | |||
| 5302 | if (!__mgmt_pending_listed(hdev, cmd)) { | ||
| 5303 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 5304 | return -ECANCELED; | ||
| 5305 | } | ||
| 5306 | |||
| 5307 | mon = cmd->user_data; | ||
| 5308 | |||
| 5309 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 5219 | 5310 | ||
| 5220 | return hci_add_adv_monitor(hdev, monitor); | 5311 | return hci_add_adv_monitor(hdev, mon); |
| 5221 | } | 5312 | } |
| 5222 | 5313 | ||
| 5223 | static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev, | 5314 | static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev, |
| @@ -5484,7 +5575,8 @@ unlock: · 260 unmodified lines | |||
| 5484 | status); | 5575 | status); |
| 5485 | } | 5576 | } |
| 5486 | 5577 | ||
| 5487 | static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, int err) | 5578 | static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, |
| 5579 | int err) | ||
| 5488 | { | 5580 | { |
| 5489 | struct mgmt_rp_read_local_oob_data mgmt_rp; | 5581 | struct mgmt_rp_read_local_oob_data mgmt_rp; |
| 5490 | size_t rp_size = sizeof(mgmt_rp); | 5582 | size_t rp_size = sizeof(mgmt_rp); |
| @@ -5504,7 +5596,8 @@ static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, int e · 13 unmodified lines | |||
| 5504 | bt_dev_dbg(hdev, "status %d", status); | 5596 | bt_dev_dbg(hdev, "status %d", status); |
| 5505 | 5597 | ||
| 5506 | if (status) { | 5598 | if (status) { |
| 5507 | mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, status); | 5599 | mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, |
| 5600 | status); | ||
| 5508 | goto remove; | 5601 | goto remove; |
| 5509 | } | 5602 | } |
| 5510 | 5603 | ||
| @@ -5786,17 +5879,12 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err) · 275 unmodified lines | |||
| 5786 | 5879 | ||
| 5787 | bt_dev_dbg(hdev, "err %d", err); | 5880 | bt_dev_dbg(hdev, "err %d", err); |
| 5788 | 5881 | ||
| 5789 | if (err == -ECANCELED) | 5882 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) |
| 5790 | return; | ||
| 5791 | |||
| 5792 | if (cmd != pending_find(MGMT_OP_START_DISCOVERY, hdev) && | ||
| 5793 | cmd != pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev) && | ||
| 5794 | cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev)) | ||
| 5795 | return; | 5883 | return; |
| 5796 | 5884 | ||
| 5797 | mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), | 5885 | mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), |
| 5798 | cmd->param, 1); | 5886 | cmd->param, 1); |
| 5799 | mgmt_pending_remove(cmd); | 5887 | mgmt_pending_free(cmd); |
| 5800 | 5888 | ||
| 5801 | hci_discovery_set_state(hdev, err ? DISCOVERY_STOPPED: | 5889 | hci_discovery_set_state(hdev, err ? DISCOVERY_STOPPED: |
| 5802 | DISCOVERY_FINDING); | 5890 | DISCOVERY_FINDING); |
| @@ -5804,6 +5892,9 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err) · 1 unmodified line | |||
| 5804 | 5892 | ||
| 5805 | static int start_discovery_sync(struct hci_dev *hdev, void *data) | 5893 | static int start_discovery_sync(struct hci_dev *hdev, void *data) |
| 5806 | { | 5894 | { |
| 5895 | if (!mgmt_pending_listed(hdev, data)) | ||
| 5896 | return -ECANCELED; | ||
| 5897 | |||
| 5807 | return hci_start_discovery_sync(hdev); | 5898 | return hci_start_discovery_sync(hdev); |
| 5808 | } | 5899 | } |
| 5809 | 5900 | ||
| @@ -6009,15 +6100,14 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err) · 199 unmodified lines | |||
| 6009 | { | 6100 | { |
| 6010 | struct mgmt_pending_cmd *cmd = data; | 6101 | struct mgmt_pending_cmd *cmd = data; |
| 6011 | 6102 | ||
| 6012 | if (err == -ECANCELED || | 6103 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) |
| 6013 | cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev)) | ||
| 6014 | return; | 6104 | return; |
| 6015 | 6105 | ||
| 6016 | bt_dev_dbg(hdev, "err %d", err); | 6106 | bt_dev_dbg(hdev, "err %d", err); |
| 6017 | 6107 | ||
| 6018 | mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), | 6108 | mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), |
| 6019 | cmd->param, 1); | 6109 | cmd->param, 1); |
| 6020 | mgmt_pending_remove(cmd); | 6110 | mgmt_pending_free(cmd); |
| 6021 | 6111 | ||
| 6022 | if (!err) | 6112 | if (!err) |
| 6023 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | 6113 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); |
| @@ -6025,6 +6115,9 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err) · 1 unmodified line | |||
| 6025 | 6115 | ||
| 6026 | static int stop_discovery_sync(struct hci_dev *hdev, void *data) | 6116 | static int stop_discovery_sync(struct hci_dev *hdev, void *data) |
| 6027 | { | 6117 | { |
| 6118 | if (!mgmt_pending_listed(hdev, data)) | ||
| 6119 | return -ECANCELED; | ||
| 6120 | |||
| 6028 | return hci_stop_discovery_sync(hdev); | 6121 | return hci_stop_discovery_sync(hdev); |
| 6029 | } | 6122 | } |
| 6030 | 6123 | ||
| @@ -6234,14 +6327,18 @@ static void enable_advertising_instance(struct hci_dev *hdev, int err) · 203 unmodified lines | |||
| 6234 | 6327 | ||
| 6235 | static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) | 6328 | static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) |
| 6236 | { | 6329 | { |
| 6330 | struct mgmt_pending_cmd *cmd = data; | ||
| 6237 | struct cmd_lookup match = { NULL, hdev }; | 6331 | struct cmd_lookup match = { NULL, hdev }; |
| 6238 | u8 instance; | 6332 | u8 instance; |
| 6239 | struct adv_info *adv_instance; | 6333 | struct adv_info *adv_instance; |
| 6240 | u8 status = mgmt_status(err); | 6334 | u8 status = mgmt_status(err); |
| 6241 | 6335 | ||
| 6336 | if (err == -ECANCELED || !mgmt_pending_valid(hdev, data)) | ||
| 6337 | return; | ||
| 6338 | |||
| 6242 | if (status) { | 6339 | if (status) { |
| 6243 | mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true, | 6340 | mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, status); |
| 6244 | cmd_status_rsp, &status); | 6341 | mgmt_pending_free(cmd); |
| 6245 | return; | 6342 | return; |
| 6246 | } | 6343 | } |
| 6247 | 6344 | ||
| @@ -6250,8 +6347,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) · 2 unmodified lines | |||
| 6250 | else | 6347 | else |
| 6251 | hci_dev_clear_flag(hdev, HCI_ADVERTISING); | 6348 | hci_dev_clear_flag(hdev, HCI_ADVERTISING); |
| 6252 | 6349 | ||
| 6253 | mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true, settings_rsp, | 6350 | settings_rsp(cmd, &match); |
| 6254 | &match); | ||
| 6255 | 6351 | ||
| 6256 | new_settings(hdev, match.sk); | 6352 | new_settings(hdev, match.sk); |
| 6257 | 6353 | ||
| @@ -6283,10 +6379,23 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) · 25 unmodified lines | |||
| 6283 | static int set_adv_sync(struct hci_dev *hdev, void *data) | 6379 | static int set_adv_sync(struct hci_dev *hdev, void *data) |
| 6284 | { | 6380 | { |
| 6285 | struct mgmt_pending_cmd *cmd = data; | 6381 | struct mgmt_pending_cmd *cmd = data; |
| 6286 | struct mgmt_mode *cp = cmd->param; | 6382 | struct mgmt_mode cp; |
| 6287 | u8 val = !!cp->val; | 6383 | u8 val; |
| 6288 | 6384 | ||
| 6289 | if (cp->val == 0x02) | 6385 | mutex_lock(&hdev->mgmt_pending_lock); |
| 6386 | |||
| 6387 | if (!__mgmt_pending_listed(hdev, cmd)) { | ||
| 6388 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 6389 | return -ECANCELED; | ||
| 6390 | } | ||
| 6391 | |||
| 6392 | memcpy(&cp, cmd->param, sizeof(cp)); | ||
| 6393 | |||
| 6394 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 6395 | |||
| 6396 | val = !!cp.val; | ||
| 6397 | |||
| 6398 | if (cp.val == 0x02) | ||
| 6290 | hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE); | 6399 | hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE); |
| 6291 | else | 6400 | else |
| 6292 | hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE); | 6401 | hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE); |
| @@ -8039,10 +8148,6 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data, · 1746 unmodified lines | |||
| 8039 | u8 status = mgmt_status(err); | 8148 | u8 status = mgmt_status(err); |
| 8040 | u16 eir_len; | 8149 | u16 eir_len; |
| 8041 | 8150 | ||
| 8042 | if (err == -ECANCELED || | ||
| 8043 | cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev)) | ||
| 8044 | return; | ||
| 8045 | |||
| 8046 | if (!status) { | 8151 | if (!status) { |
| 8047 | if (!skb) | 8152 | if (!skb) |
| 8048 | status = MGMT_STATUS_FAILED; | 8153 | status = MGMT_STATUS_FAILED; |
| @@ -8149,7 +8254,7 @@ done: · 100 unmodified lines | |||
| 8149 | kfree_skb(skb); | 8254 | kfree_skb(skb); |
| 8150 | 8255 | ||
| 8151 | kfree(mgmt_rp); | 8256 | kfree(mgmt_rp); |
| 8152 | mgmt_pending_remove(cmd); | 8257 | mgmt_pending_free(cmd); |
| 8153 | } | 8258 | } |
| 8154 | 8259 | ||
| 8155 | static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk, | 8260 | static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk, |
| @@ -8158,7 +8263,7 @@ static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk, · 2 unmodified lines | |||
| 8158 | struct mgmt_pending_cmd *cmd; | 8263 | struct mgmt_pending_cmd *cmd; |
| 8159 | int err; | 8264 | int err; |
| 8160 | 8265 | ||
| 8161 | cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev, | 8266 | cmd = mgmt_pending_new(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev, |
| 8162 | cp, sizeof(*cp)); | 8267 | cp, sizeof(*cp)); |
| 8163 | if (!cmd) | 8268 | if (!cmd) |
| 8164 | return -ENOMEM; | 8269 | return -ENOMEM; |
| @@ -320,6 +320,52 @@ void mgmt_pending_remove(struct mgmt_pending_cmd *cmd) · 319 unmodified lines | |||
| 320 | mgmt_pending_free(cmd); | 320 | mgmt_pending_free(cmd); |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | bool __mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd) | ||
| 324 | { | ||
| 325 | struct mgmt_pending_cmd *tmp; | ||
| 326 | |||
| 327 | lockdep_assert_held(&hdev->mgmt_pending_lock); | ||
| 328 | |||
| 329 | if (!cmd) | ||
| 330 | return false; | ||
| 331 | |||
| 332 | list_for_each_entry(tmp, &hdev->mgmt_pending, list) { | ||
| 333 | if (cmd == tmp) | ||
| 334 | return true; | ||
| 335 | } | ||
| 336 | |||
| 337 | return false; | ||
| 338 | } | ||
| 339 | |||
| 340 | bool mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd) | ||
| 341 | { | ||
| 342 | bool listed; | ||
| 343 | |||
| 344 | mutex_lock(&hdev->mgmt_pending_lock); | ||
| 345 | listed = __mgmt_pending_listed(hdev, cmd); | ||
| 346 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 347 | |||
| 348 | return listed; | ||
| 349 | } | ||
| 350 | |||
| 351 | bool mgmt_pending_valid(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd) | ||
| 352 | { | ||
| 353 | bool listed; | ||
| 354 | |||
| 355 | if (!cmd) | ||
| 356 | return false; | ||
| 357 | |||
| 358 | mutex_lock(&hdev->mgmt_pending_lock); | ||
| 359 | |||
| 360 | listed = __mgmt_pending_listed(hdev, cmd); | ||
| 361 | if (listed) | ||
| 362 | list_del(&cmd->list); | ||
| 363 | |||
| 364 | mutex_unlock(&hdev->mgmt_pending_lock); | ||
| 365 | |||
| 366 | return listed; | ||
| 367 | } | ||
| 368 | |||
| 323 | void mgmt_mesh_foreach(struct hci_dev *hdev, | 369 | void mgmt_mesh_foreach(struct hci_dev *hdev, |
| 324 | void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data), | 370 | void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data), |
| 325 | void *data, struct sock *sk) | 371 | void *data, struct sock *sk) |
| @@ -65,6 +65,9 @@ struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode, · 64 unmodified lines | |||
| 65 | void *data, u16 len); | 65 | void *data, u16 len); |
| 66 | void mgmt_pending_free(struct mgmt_pending_cmd *cmd); | 66 | void mgmt_pending_free(struct mgmt_pending_cmd *cmd); |
| 67 | void mgmt_pending_remove(struct mgmt_pending_cmd *cmd); | 67 | void mgmt_pending_remove(struct mgmt_pending_cmd *cmd); |
| 68 | bool __mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd); | ||
| 69 | bool mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd); | ||
| 70 | bool mgmt_pending_valid(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd); | ||
| 68 | void mgmt_mesh_foreach(struct hci_dev *hdev, | 71 | void mgmt_mesh_foreach(struct hci_dev *hdev, |
| 69 | void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data), | 72 | void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data), |
| 70 | void *data, struct sock *sk); | 73 | void *data, struct sock *sk); |
| @@ -6667,7 +6667,7 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len, · 6666 unmodified lines | |||
| 6667 | return NULL; | 6667 | return NULL; |
| 6668 | 6668 | ||
| 6669 | while (data_len) { | 6669 | while (data_len) { |
| 6670 | if (nr_frags == MAX_SKB_FRAGS - 1) | 6670 | if (nr_frags == MAX_SKB_FRAGS) |
| 6671 | goto failure; | 6671 | goto failure; |
| 6672 | while (order && PAGE_ALIGN(data_len) < (PAGE_SIZE << order)) | 6672 | while (order && PAGE_ALIGN(data_len) < (PAGE_SIZE << order)) |
| 6673 | order--; | 6673 | order--; |
| @@ -2399,6 +2399,13 @@ static int replace_nexthop_single(struct net *net, struct nexthop *old, · 2398 unmodified lines | |||
| 2399 | return -EINVAL; | 2399 | return -EINVAL; |
| 2400 | } | 2400 | } |
| 2401 | 2401 | ||
| 2402 | if (!list_empty(&old->grp_list) && | ||
| 2403 | rtnl_dereference(new->nh_info)->fdb_nh != | ||
| 2404 | rtnl_dereference(old->nh_info)->fdb_nh) { | ||
| 2405 | NL_SET_ERR_MSG(extack, "Cannot change nexthop FDB status while in a group"); | ||
| 2406 | return -EINVAL; | ||
| 2407 | } | ||
| 2408 | |||
| 2402 | err = call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE, new, extack); | 2409 | err = call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE, new, extack); |
| 2403 | if (err) | 2410 | if (err) |
| 2404 | return err; | 2411 | return err; |
| @@ -56,6 +56,7 @@ static int smc_lo_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb, · 55 unmodified lines | |||
| 56 | { | 56 | { |
| 57 | struct smc_lo_dmb_node *dmb_node, *tmp_node; | 57 | struct smc_lo_dmb_node *dmb_node, *tmp_node; |
| 58 | struct smc_lo_dev *ldev = smcd->priv; | 58 | struct smc_lo_dev *ldev = smcd->priv; |
| 59 | struct folio *folio; | ||
| 59 | int sba_idx, rc; | 60 | int sba_idx, rc; |
| 60 | 61 | ||
| 61 | /* check space for new dmb */ | 62 | /* check space for new dmb */ |
| @@ -74,13 +75,16 @@ static int smc_lo_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb, · 12 unmodified lines | |||
| 74 | 75 | ||
| 75 | dmb_node->sba_idx = sba_idx; | 76 | dmb_node->sba_idx = sba_idx; |
| 76 | dmb_node->len = dmb->dmb_len; | 77 | dmb_node->len = dmb->dmb_len; |
| 77 | dmb_node->cpu_addr = kzalloc(dmb_node->len, GFP_KERNEL | | 78 | |
| 78 | __GFP_NOWARN | __GFP_NORETRY | | 79 | /* not critical; fail under memory pressure and fallback to TCP */ |
| 79 | __GFP_NOMEMALLOC); | 80 | folio = folio_alloc(GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC | |
| 80 | if (!dmb_node->cpu_addr) { | 81 | __GFP_NORETRY | __GFP_ZERO, |
| 82 | get_order(dmb_node->len)); | ||
| 83 | if (!folio) { | ||
| 81 | rc = -ENOMEM; | 84 | rc = -ENOMEM; |
| 82 | goto err_node; | 85 | goto err_node; |
| 83 | } | 86 | } |
| 87 | dmb_node->cpu_addr = folio_address(folio); | ||
| 84 | dmb_node->dma_addr = SMC_DMA_ADDR_INVALID; | 88 | dmb_node->dma_addr = SMC_DMA_ADDR_INVALID; |
| 85 | refcount_set(&dmb_node->refcnt, 1); | 89 | refcount_set(&dmb_node->refcnt, 1); |
| 86 | 90 | ||
| @@ -122,7 +126,7 @@ static void __smc_lo_unregister_dmb(struct smc_lo_dev *ldev, · 35 unmodified lines | |||
| 122 | write_unlock_bh(&ldev->dmb_ht_lock); | 126 | write_unlock_bh(&ldev->dmb_ht_lock); |
| 123 | 127 | ||
| 124 | clear_bit(dmb_node->sba_idx, ldev->sba_idx_mask); | 128 | clear_bit(dmb_node->sba_idx, ldev->sba_idx_mask); |
| 125 | kvfree(dmb_node->cpu_addr); | 129 | folio_put(virt_to_folio(dmb_node->cpu_addr)); |
| 126 | kfree(dmb_node); | 130 | kfree(dmb_node); |
| 127 | 131 | ||
| 128 | if (atomic_dec_and_test(&ldev->dmb_cnt)) | 132 | if (atomic_dec_and_test(&ldev->dmb_cnt)) |
| @@ -438,7 +438,7 @@ ok: · 437 unmodified lines | |||
| 438 | 438 | ||
| 439 | check_tunnel_size = x->xso.type == XFRM_DEV_OFFLOAD_PACKET && | 439 | check_tunnel_size = x->xso.type == XFRM_DEV_OFFLOAD_PACKET && |
| 440 | x->props.mode == XFRM_MODE_TUNNEL; | 440 | x->props.mode == XFRM_MODE_TUNNEL; |
| 441 | switch (x->props.family) { | 441 | switch (x->inner_mode.family) { |
| 442 | case AF_INET: | 442 | case AF_INET: |
| 443 | /* Check for IPv4 options */ | 443 | /* Check for IPv4 options */ |
| 444 | if (ip_hdr(skb)->ihl != 5) | 444 | if (ip_hdr(skb)->ihl != 5) |
| @@ -2583,6 +2583,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high, · 2582 unmodified lines | |||
| 2583 | 2583 | ||
| 2584 | for (h = 0; h < range; h++) { | 2584 | for (h = 0; h < range; h++) { |
| 2585 | u32 spi = (low == high) ? low : get_random_u32_inclusive(low, high); | 2585 | u32 spi = (low == high) ? low : get_random_u32_inclusive(low, high); |
| 2586 | if (spi == 0) | ||
| 2587 | goto next; | ||
| 2586 | newspi = htonl(spi); | 2588 | newspi = htonl(spi); |
| 2587 | 2589 | ||
| 2588 | spin_lock_bh(&net->xfrm.xfrm_state_lock); | 2590 | spin_lock_bh(&net->xfrm.xfrm_state_lock); |
| @@ -2598,6 +2600,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high, · 9 unmodified lines | |||
| 2598 | xfrm_state_put(x0); | 2600 | xfrm_state_put(x0); |
| 2599 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); | 2601 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); |
| 2600 | 2602 | ||
| 2603 | next: | ||
| 2601 | if (signal_pending(current)) { | 2604 | if (signal_pending(current)) { |
| 2602 | err = -ERESTARTSYS; | 2605 | err = -ERESTARTSYS; |
| 2603 | goto unlock; | 2606 | goto unlock; |
| @@ -467,8 +467,8 @@ ipv6_fdb_grp_fcnal() · 466 unmodified lines | |||
| 467 | log_test $? 0 "Get Fdb nexthop group by id" | 467 | log_test $? 0 "Get Fdb nexthop group by id" |
| 468 | 468 | ||
| 469 | # fdb nexthop group can only contain fdb nexthops | 469 | # fdb nexthop group can only contain fdb nexthops |
| 470 | run_cmd "$IP nexthop add id 63 via 2001:db8:91::4" | 470 | run_cmd "$IP nexthop add id 63 via 2001:db8:91::4 dev veth1" |
| 471 | run_cmd "$IP nexthop add id 64 via 2001:db8:91::5" | 471 | run_cmd "$IP nexthop add id 64 via 2001:db8:91::5 dev veth1" |
| 472 | run_cmd "$IP nexthop add id 103 group 63/64 fdb" | 472 | run_cmd "$IP nexthop add id 103 group 63/64 fdb" |
| 473 | log_test $? 2 "Fdb Nexthop group with non-fdb nexthops" | 473 | log_test $? 2 "Fdb Nexthop group with non-fdb nexthops" |
| 474 | 474 | ||
| @@ -494,6 +494,26 @@ ipv6_fdb_grp_fcnal() · 19 unmodified lines | |||
| 494 | run_cmd "$IP nexthop add id 69 encap mpls 101 via 2001:db8:91::8 dev veth1 fdb" | 494 | run_cmd "$IP nexthop add id 69 encap mpls 101 via 2001:db8:91::8 dev veth1 fdb" |
| 495 | log_test $? 2 "Fdb Nexthop with encap" | 495 | log_test $? 2 "Fdb Nexthop with encap" |
| 496 | 496 | ||
| 497 | # Replace FDB nexthop to non-FDB and vice versa | ||
| 498 | run_cmd "$IP nexthop add id 70 via 2001:db8:91::2 fdb" | ||
| 499 | run_cmd "$IP nexthop replace id 70 via 2001:db8:91::2 dev veth1" | ||
| 500 | log_test $? 0 "Replace FDB nexthop to non-FDB nexthop" | ||
| 501 | run_cmd "$IP nexthop replace id 70 via 2001:db8:91::2 fdb" | ||
| 502 | log_test $? 0 "Replace non-FDB nexthop to FDB nexthop" | ||
| 503 | |||
| 504 | # Replace FDB nexthop address while in a group | ||
| 505 | run_cmd "$IP nexthop add id 71 group 70 fdb" | ||
| 506 | run_cmd "$IP nexthop replace id 70 via 2001:db8:91::3 fdb" | ||
| 507 | log_test $? 0 "Replace FDB nexthop address while in a group" | ||
| 508 | |||
| 509 | # Cannot replace FDB nexthop to non-FDB and vice versa while in a group | ||
| 510 | run_cmd "$IP nexthop replace id 70 via 2001:db8:91::2 dev veth1" | ||
| 511 | log_test $? 2 "Replace FDB nexthop to non-FDB nexthop while in a group" | ||
| 512 | run_cmd "$IP nexthop add id 72 via 2001:db8:91::2 dev veth1" | ||
| 513 | run_cmd "$IP nexthop add id 73 group 72" | ||
| 514 | run_cmd "$IP nexthop replace id 72 via 2001:db8:91::2 fdb" | ||
| 515 | log_test $? 2 "Replace non-FDB nexthop to FDB nexthop while in a group" | ||
| 516 | |||
| 497 | run_cmd "$IP link add name vx10 type vxlan id 1010 local 2001:db8:91::9 remote 2001:db8:91::10 dstport 4789 nolearning noudpcsum tos inherit ttl 100" | 517 | run_cmd "$IP link add name vx10 type vxlan id 1010 local 2001:db8:91::9 remote 2001:db8:91::10 dstport 4789 nolearning noudpcsum tos inherit ttl 100" |
| 498 | run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self" | 518 | run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self" |
| 499 | log_test $? 0 "Fdb mac add with nexthop group" | 519 | log_test $? 0 "Fdb mac add with nexthop group" |
| @@ -547,15 +567,15 @@ ipv4_fdb_grp_fcnal() · 47 unmodified lines | |||
| 547 | log_test $? 0 "Get Fdb nexthop group by id" | 567 | log_test $? 0 "Get Fdb nexthop group by id" |
| 548 | 568 | ||
| 549 | # fdb nexthop group can only contain fdb nexthops | 569 | # fdb nexthop group can only contain fdb nexthops |
| 550 | run_cmd "$IP nexthop add id 14 via 172.16.1.2" | 570 | run_cmd "$IP nexthop add id 14 via 172.16.1.2 dev veth1" |
| 551 | run_cmd "$IP nexthop add id 15 via 172.16.1.3" | 571 | run_cmd "$IP nexthop add id 15 via 172.16.1.3 dev veth1" |
| 552 | run_cmd "$IP nexthop add id 103 group 14/15 fdb" | 572 | run_cmd "$IP nexthop add id 103 group 14/15 fdb" |
| 553 | log_test $? 2 "Fdb Nexthop group with non-fdb nexthops" | 573 | log_test $? 2 "Fdb Nexthop group with non-fdb nexthops" |
| 554 | 574 | ||
| 555 | # Non fdb nexthop group can not contain fdb nexthops | 575 | # Non fdb nexthop group can not contain fdb nexthops |
| 556 | run_cmd "$IP nexthop add id 16 via 172.16.1.2 fdb" | 576 | run_cmd "$IP nexthop add id 16 via 172.16.1.2 fdb" |
| 557 | run_cmd "$IP nexthop add id 17 via 172.16.1.3 fdb" | 577 | run_cmd "$IP nexthop add id 17 via 172.16.1.3 fdb" |
| 558 | run_cmd "$IP nexthop add id 104 group 14/15" | 578 | run_cmd "$IP nexthop add id 104 group 16/17" |
| 559 | log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops" | 579 | log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops" |
| 560 | 580 | ||
| 561 | # fdb nexthop cannot have blackhole | 581 | # fdb nexthop cannot have blackhole |
| @@ -574,6 +594,26 @@ ipv4_fdb_grp_fcnal() · 12 unmodified lines | |||
| 574 | run_cmd "$IP nexthop add id 17 encap mpls 101 via 172.16.1.2 dev veth1 fdb" | 594 | run_cmd "$IP nexthop add id 17 encap mpls 101 via 172.16.1.2 dev veth1 fdb" |
| 575 | log_test $? 2 "Fdb Nexthop with encap" | 595 | log_test $? 2 "Fdb Nexthop with encap" |
| 576 | 596 | ||
| 597 | # Replace FDB nexthop to non-FDB and vice versa | ||
| 598 | run_cmd "$IP nexthop add id 18 via 172.16.1.2 fdb" | ||
| 599 | run_cmd "$IP nexthop replace id 18 via 172.16.1.2 dev veth1" | ||
| 600 | log_test $? 0 "Replace FDB nexthop to non-FDB nexthop" | ||
| 601 | run_cmd "$IP nexthop replace id 18 via 172.16.1.2 fdb" | ||
| 602 | log_test $? 0 "Replace non-FDB nexthop to FDB nexthop" | ||
| 603 | |||
| 604 | # Replace FDB nexthop address while in a group | ||
| 605 | run_cmd "$IP nexthop add id 19 group 18 fdb" | ||
| 606 | run_cmd "$IP nexthop replace id 18 via 172.16.1.3 fdb" | ||
| 607 | log_test $? 0 "Replace FDB nexthop address while in a group" | ||
| 608 | |||
| 609 | # Cannot replace FDB nexthop to non-FDB and vice versa while in a group | ||
| 610 | run_cmd "$IP nexthop replace id 18 via 172.16.1.2 dev veth1" | ||
| 611 | log_test $? 2 "Replace FDB nexthop to non-FDB nexthop while in a group" | ||
| 612 | run_cmd "$IP nexthop add id 20 via 172.16.1.2 dev veth1" | ||
| 613 | run_cmd "$IP nexthop add id 21 group 20" | ||
| 614 | run_cmd "$IP nexthop replace id 20 via 172.16.1.2 fdb" | ||
| 615 | log_test $? 2 "Replace non-FDB nexthop to FDB nexthop while in a group" | ||
| 616 | |||
| 577 | run_cmd "$IP link add name vx10 type vxlan id 1010 local 10.0.0.1 remote 10.0.0.2 dstport 4789 nolearning noudpcsum tos inherit ttl 100" | 617 | run_cmd "$IP link add name vx10 type vxlan id 1010 local 10.0.0.1 remote 10.0.0.2 dstport 4789 nolearning noudpcsum tos inherit ttl 100" |
| 578 | run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self" | 618 | run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self" |
| 579 | log_test $? 0 "Fdb mac add with nexthop group" | 619 | log_test $? 0 "Fdb mac add with nexthop group" |
| @@ -582,7 +622,7 @@ ipv4_fdb_grp_fcnal() · 2 unmodified lines | |||
| 582 | run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 12 self" | 622 | run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 12 self" |
| 583 | log_test $? 255 "Fdb mac add with nexthop" | 623 | log_test $? 255 "Fdb mac add with nexthop" |
| 584 | 624 | ||
| 585 | run_cmd "$IP ro add 172.16.0.0/22 nhid 15" | 625 | run_cmd "$IP ro add 172.16.0.0/22 nhid 16" |
| 586 | log_test $? 2 "Route add with fdb nexthop" | 626 | log_test $? 2 "Route add with fdb nexthop" |
| 587 | 627 | ||
| 588 | run_cmd "$IP ro add 172.16.0.0/22 nhid 103" | 628 | run_cmd "$IP ro add 172.16.0.0/22 nhid 103" |