Merge tag 'net-6.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 25 Apr 2024 18:19:38 +0000 (11:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 25 Apr 2024 18:19:38 +0000 (11:19 -0700)
Pull networking fixes from Jakub Kicinski:
 "Including fixes from netfilter, wireless and bluetooth.

  Nothing major, regression fixes are mostly in drivers, two more of
  those are flowing towards us thru various trees. I wish some of the
  changes went into -rc5, we'll try to keep an eye on frequency of PRs
  from sub-trees.

  Also disproportional number of fixes for bugs added in v6.4, strange
  coincidence.

  Current release - regressions:

   - igc: fix LED-related deadlock on driver unbind

   - wifi: mac80211: small fixes to recent clean up of the connection
     process

   - Revert "wifi: iwlwifi: bump FW API to 90 for BZ/SC devices", kernel
     doesn't have all the code to deal with that version, yet

   - Bluetooth:
       - set power_ctrl_enabled on NULL returned by gpiod_get_optional()
       - qca: fix invalid device address check, again

   - eth: ravb: fix registered interrupt names

  Current release - new code bugs:

   - wifi: mac80211: check EHT/TTLM action frame length

  Previous releases - regressions:

   - fix sk_memory_allocated_{add|sub} for architectures where
     __this_cpu_{add|sub}* are not IRQ-safe

   - dsa: mv88e6xx: fix link setup for 88E6250

  Previous releases - always broken:

   - ip: validate dev returned from __in_dev_get_rcu(), prevent possible
     null-derefs in a few places

   - switch number of for_each_rcu() loops using call_rcu() on the
     iterator to for_each_safe()

   - macsec: fix isolation of broadcast traffic in presence of offload

   - vxlan: drop packets from invalid source address

   - eth: mlxsw: trap and ACL programming fixes

   - eth: bnxt: PCIe error recovery fixes, fix counting dropped packets

   - Bluetooth:
       - lots of fixes for the command submission rework from v6.4
       - qca: fix NULL-deref on non-serdev suspend

  Misc:

   - tools: ynl: don't ignore errors in NLMSG_DONE messages"

* tag 'net-6.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (88 commits)
  af_unix: Suppress false-positive lockdep splat for spin_lock() in __unix_gc().
  net: b44: set pause params only when interface is up
  tls: fix lockless read of strp->msg_ready in ->poll
  dpll: fix dpll_pin_on_pin_register() for multiple parent pins
  net: ravb: Fix registered interrupt names
  octeontx2-af: fix the double free in rvu_npc_freemem()
  net: ethernet: ti: am65-cpts: Fix PTPv1 message type on TX packets
  ice: fix LAG and VF lock dependency in ice_reset_vf()
  iavf: Fix TC config comparison with existing adapter TC config
  i40e: Report MFS in decimal base instead of hex
  i40e: Do not use WQ_MEM_RECLAIM flag for workqueue
  net: ti: icssg-prueth: Fix signedness bug in prueth_init_rx_chns()
  net/mlx5e: Advertise mlx5 ethernet driver updates sk_buff md_dst for MACsec
  macsec: Detect if Rx skb is macsec-related for offloading devices that update md_dst
  ethernet: Add helper for assigning packet type when dest address does not match device address
  macsec: Enable devices to advertise whether they update sk_buff md_dst during offloads
  net: phy: dp83869: Fix MII mode failure
  netfilter: nf_tables: honor table dormant flag from netdev release event path
  eth: bnxt: fix counting packets discarded due to OOM and netpoll
  igc: Fix LED-related deadlock on driver unbind
  ...

85 files changed:
.mailmap
MAINTAINERS
drivers/bluetooth/btmtk.c
drivers/bluetooth/btqca.c
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_qca.c
drivers/dpll/dpll_core.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/port.h
drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/ice/ice_vf_lib.c
drivers/net/ethernet/intel/igc/igc.h
drivers/net/ethernet/intel/igc/igc_leds.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/core_env.c
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/ti/am65-cpts.c
drivers/net/ethernet/ti/icssg/icssg_prueth.c
drivers/net/ethernet/wangxun/libwx/wx_lib.c
drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
drivers/net/gtp.c
drivers/net/macsec.c
drivers/net/phy/dp83869.c
drivers/net/phy/mediatek-ge-soc.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/qmi_wwan.c
drivers/net/vxlan/vxlan_core.c
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/intel/iwlwifi/cfg/bz.c
drivers/net/wireless/intel/iwlwifi/cfg/sc.c
drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
drivers/net/wireless/intel/iwlwifi/mvm/link.c
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
drivers/net/wireless/virtual/mac80211_hwsim.c
drivers/nfc/trf7970a.c
include/linux/etherdevice.h
include/net/af_unix.h
include/net/bluetooth/hci_core.h
include/net/mac80211.h
include/net/macsec.h
include/net/sock.h
include/net/tls.h
net/ax25/af_ax25.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/sco.c
net/bridge/br_netlink.c
net/ethernet/eth.c
net/ipv4/icmp.c
net/ipv4/route.c
net/ipv4/tcp_ao.c
net/ipv4/udp.c
net/ipv6/udp.c
net/mac80211/chan.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_pathtbl.c
net/mac80211/mlme.c
net/mac80211/rate.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/tx.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/nft_chain_filter.c
net/openvswitch/conntrack.c
net/tls/tls.h
net/tls/tls_strp.c
net/unix/garbage.c
net/wireless/nl80211.c
net/wireless/trace.h
tools/net/ynl/lib/ynl.py

index 09fecfe78aba810602b6a226fece6272508bd3a1..16b704e1d5d3665d178f48992a8e3d03cad57cac 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -38,6 +38,16 @@ Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com>
 Alexei Starovoitov <ast@kernel.org> <ast@fb.com>
 Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com>
 Alexey Makhalov <alexey.amakhalov@broadcom.com> <amakhalov@vmware.com>
+Alex Elder <elder@kernel.org>
+Alex Elder <elder@kernel.org> <aelder@sgi.com>
+Alex Elder <elder@kernel.org> <alex.elder@linaro.org>
+Alex Elder <elder@kernel.org> <alex.elder@linary.org>
+Alex Elder <elder@kernel.org> <elder@dreamhost.com>
+Alex Elder <elder@kernel.org> <elder@dreawmhost.com>
+Alex Elder <elder@kernel.org> <elder@ieee.org>
+Alex Elder <elder@kernel.org> <elder@inktank.com>
+Alex Elder <elder@kernel.org> <elder@linaro.org>
+Alex Elder <elder@kernel.org> <elder@newdream.net>
 Alex Hung <alexhung@gmail.com> <alex.hung@canonical.com>
 Alex Shi <alexs@kernel.org> <alex.shi@intel.com>
 Alex Shi <alexs@kernel.org> <alex.shi@linaro.org>
index 75218382e4a63220d78bbd2efa3d6d0fc958019d..62b1a16b791beec3a67968974e5ea0e7269cd2dc 100644 (file)
@@ -7829,9 +7829,8 @@ W:        http://aeschi.ch.eu.org/efs/
 F:     fs/efs/
 
 EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
-M:     Douglas Miller <dougmill@linux.ibm.com>
 L:     netdev@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/ethernet/ibm/ehea/
 
 ELM327 CAN NETWORK DRIVER
index ac8ebccd350756747eee3400596e04fcbac3cabd..812fd2a8f853e1dc305fa6aab04db8098ea28872 100644 (file)
@@ -380,8 +380,10 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
        switch (data->cd_info.state) {
        case HCI_DEVCOREDUMP_IDLE:
                err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
-               if (err < 0)
+               if (err < 0) {
+                       kfree_skb(skb);
                        break;
+               }
                data->cd_info.cnt = 0;
 
                /* It is supposed coredump can be done within 5 seconds */
@@ -407,9 +409,6 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
                break;
        }
 
-       if (err < 0)
-               kfree_skb(skb);
-
        return err;
 }
 EXPORT_SYMBOL_GPL(btmtk_process_coredump);
index 19cfc342fc7bbb67af65cb4de10e074622a991a4..216826c31ee34f0e65ef74edcab98c7cd9eff7e5 100644 (file)
@@ -15,6 +15,8 @@
 
 #define VERSION "0.1"
 
+#define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }})
+
 int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
                         enum qca_btsoc_type soc_type)
 {
@@ -612,6 +614,38 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
 }
 EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
 
+static int qca_check_bdaddr(struct hci_dev *hdev)
+{
+       struct hci_rp_read_bd_addr *bda;
+       struct sk_buff *skb;
+       int err;
+
+       if (bacmp(&hdev->public_addr, BDADDR_ANY))
+               return 0;
+
+       skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
+                            HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb)) {
+               err = PTR_ERR(skb);
+               bt_dev_err(hdev, "Failed to read device address (%d)", err);
+               return err;
+       }
+
+       if (skb->len != sizeof(*bda)) {
+               bt_dev_err(hdev, "Device address length mismatch");
+               kfree_skb(skb);
+               return -EIO;
+       }
+
+       bda = (struct hci_rp_read_bd_addr *)skb->data;
+       if (!bacmp(&bda->bdaddr, QCA_BDADDR_DEFAULT))
+               set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
+
+       kfree_skb(skb);
+
+       return 0;
+}
+
 static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
                struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
 {
@@ -818,6 +852,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
                break;
        }
 
+       err = qca_check_bdaddr(hdev);
+       if (err)
+               return err;
+
        bt_dev_info(hdev, "QCA setup on UART is completed");
 
        return 0;
index 06e915b57283f8ca3d3ab19b64e1e248e6ecb2bc..e3946f7b736e3cccfe727575096ff073fd86cf1d 100644 (file)
@@ -542,6 +542,8 @@ static const struct usb_device_id quirks_table[] = {
        /* Realtek 8852BE Bluetooth devices */
        { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
                                                     BTUSB_WIDEBAND_SPEECH },
+       { USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK |
+                                                    BTUSB_WIDEBAND_SPEECH },
        { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
                                                     BTUSB_WIDEBAND_SPEECH },
        { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
@@ -3480,13 +3482,12 @@ static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void btusb_coredump_qca(struct hci_dev *hdev)
 {
+       int err;
        static const u8 param[] = { 0x26 };
-       struct sk_buff *skb;
 
-       skb = __hci_cmd_sync(hdev, 0xfc0c, 1, param, HCI_CMD_TIMEOUT);
-       if (IS_ERR(skb))
-               bt_dev_err(hdev, "%s: triggle crash failed (%ld)", __func__, PTR_ERR(skb));
-       kfree_skb(skb);
+       err = __hci_cmd_send(hdev, 0xfc0c, 1, param);
+       if (err < 0)
+               bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err);
 }
 
 /*
index ecbc52eaf1010912b9024ddbc3c87aac4254e1e3..0c9c9ee56592dc851ab12f98be5a6be2465b812e 100644 (file)
@@ -1672,6 +1672,9 @@ static bool qca_wakeup(struct hci_dev *hdev)
        struct hci_uart *hu = hci_get_drvdata(hdev);
        bool wakeup;
 
+       if (!hu->serdev)
+               return true;
+
        /* BT SoC attached through the serial bus is handled by the serdev driver.
         * So we need to use the device handle of the serdev driver to get the
         * status of device may wakeup.
@@ -1905,8 +1908,6 @@ retry:
        case QCA_WCN6750:
        case QCA_WCN6855:
        case QCA_WCN7850:
-               set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
-
                qcadev = serdev_device_get_drvdata(hu->serdev);
                if (qcadev->bdaddr_property_broken)
                        set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks);
@@ -1957,8 +1958,10 @@ retry:
                qca_debugfs_init(hdev);
                hu->hdev->hw_error = qca_hw_error;
                hu->hdev->cmd_timeout = qca_cmd_timeout;
-               if (device_can_wakeup(hu->serdev->ctrl->dev.parent))
-                       hu->hdev->wakeup = qca_wakeup;
+               if (hu->serdev) {
+                       if (device_can_wakeup(hu->serdev->ctrl->dev.parent))
+                               hu->hdev->wakeup = qca_wakeup;
+               }
        } else if (ret == -ENOENT) {
                /* No patch/nvm-config found, run with original fw/config */
                set_bit(QCA_ROM_FW, &qca->flags);
@@ -2329,16 +2332,21 @@ static int qca_serdev_probe(struct serdev_device *serdev)
                    (data->soc_type == QCA_WCN6750 ||
                     data->soc_type == QCA_WCN6855)) {
                        dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n");
-                       power_ctrl_enabled = false;
+                       return PTR_ERR(qcadev->bt_en);
                }
 
+               if (!qcadev->bt_en)
+                       power_ctrl_enabled = false;
+
                qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl",
                                               GPIOD_IN);
                if (IS_ERR(qcadev->sw_ctrl) &&
                    (data->soc_type == QCA_WCN6750 ||
                     data->soc_type == QCA_WCN6855 ||
-                    data->soc_type == QCA_WCN7850))
-                       dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
+                    data->soc_type == QCA_WCN7850)) {
+                       dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
+                       return PTR_ERR(qcadev->sw_ctrl);
+               }
 
                qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
                if (IS_ERR(qcadev->susclk)) {
@@ -2357,10 +2365,13 @@ static int qca_serdev_probe(struct serdev_device *serdev)
                qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
                                               GPIOD_OUT_LOW);
                if (IS_ERR(qcadev->bt_en)) {
-                       dev_warn(&serdev->dev, "failed to acquire enable gpio\n");
-                       power_ctrl_enabled = false;
+                       dev_err(&serdev->dev, "failed to acquire enable gpio\n");
+                       return PTR_ERR(qcadev->bt_en);
                }
 
+               if (!qcadev->bt_en)
+                       power_ctrl_enabled = false;
+
                qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
                if (IS_ERR(qcadev->susclk)) {
                        dev_warn(&serdev->dev, "failed to acquire clk\n");
index 64eaca80d736c5652958ddb5e21bc64ff3a6bc65..d0f6693ca142623af740bf69ee8664fc88926fcb 100644 (file)
@@ -42,6 +42,7 @@ struct dpll_pin_registration {
        struct list_head list;
        const struct dpll_pin_ops *ops;
        void *priv;
+       void *cookie;
 };
 
 struct dpll_device *dpll_device_get_by_id(int id)
@@ -54,12 +55,14 @@ struct dpll_device *dpll_device_get_by_id(int id)
 
 static struct dpll_pin_registration *
 dpll_pin_registration_find(struct dpll_pin_ref *ref,
-                          const struct dpll_pin_ops *ops, void *priv)
+                          const struct dpll_pin_ops *ops, void *priv,
+                          void *cookie)
 {
        struct dpll_pin_registration *reg;
 
        list_for_each_entry(reg, &ref->registration_list, list) {
-               if (reg->ops == ops && reg->priv == priv)
+               if (reg->ops == ops && reg->priv == priv &&
+                   reg->cookie == cookie)
                        return reg;
        }
        return NULL;
@@ -67,7 +70,8 @@ dpll_pin_registration_find(struct dpll_pin_ref *ref,
 
 static int
 dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
-                   const struct dpll_pin_ops *ops, void *priv)
+                   const struct dpll_pin_ops *ops, void *priv,
+                   void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -78,7 +82,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
        xa_for_each(xa_pins, i, ref) {
                if (ref->pin != pin)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (reg) {
                        refcount_inc(&ref->refcount);
                        return 0;
@@ -111,6 +115,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
        }
        reg->ops = ops;
        reg->priv = priv;
+       reg->cookie = cookie;
        if (ref_exists)
                refcount_inc(&ref->refcount);
        list_add_tail(&reg->list, &ref->registration_list);
@@ -119,7 +124,8 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
 }
 
 static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
-                              const struct dpll_pin_ops *ops, void *priv)
+                              const struct dpll_pin_ops *ops, void *priv,
+                              void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -128,7 +134,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
        xa_for_each(xa_pins, i, ref) {
                if (ref->pin != pin)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (WARN_ON(!reg))
                        return -EINVAL;
                list_del(&reg->list);
@@ -146,7 +152,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
 
 static int
 dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
-                    const struct dpll_pin_ops *ops, void *priv)
+                    const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -157,7 +163,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
        xa_for_each(xa_dplls, i, ref) {
                if (ref->dpll != dpll)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (reg) {
                        refcount_inc(&ref->refcount);
                        return 0;
@@ -190,6 +196,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
        }
        reg->ops = ops;
        reg->priv = priv;
+       reg->cookie = cookie;
        if (ref_exists)
                refcount_inc(&ref->refcount);
        list_add_tail(&reg->list, &ref->registration_list);
@@ -199,7 +206,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
 
 static void
 dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
-                    const struct dpll_pin_ops *ops, void *priv)
+                    const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -208,7 +215,7 @@ dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
        xa_for_each(xa_dplls, i, ref) {
                if (ref->dpll != dpll)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (WARN_ON(!reg))
                        return;
                list_del(&reg->list);
@@ -594,14 +601,14 @@ EXPORT_SYMBOL_GPL(dpll_pin_put);
 
 static int
 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
-                   const struct dpll_pin_ops *ops, void *priv)
+                   const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        int ret;
 
-       ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv);
+       ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie);
        if (ret)
                return ret;
-       ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv);
+       ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie);
        if (ret)
                goto ref_pin_del;
        xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
@@ -610,7 +617,7 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
        return ret;
 
 ref_pin_del:
-       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
+       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
        return ret;
 }
 
@@ -642,7 +649,7 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
                      dpll->clock_id == pin->clock_id)))
                ret = -EINVAL;
        else
-               ret = __dpll_pin_register(dpll, pin, ops, priv);
+               ret = __dpll_pin_register(dpll, pin, ops, priv, NULL);
        mutex_unlock(&dpll_lock);
 
        return ret;
@@ -651,11 +658,11 @@ EXPORT_SYMBOL_GPL(dpll_pin_register);
 
 static void
 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
-                     const struct dpll_pin_ops *ops, void *priv)
+                     const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        ASSERT_DPLL_PIN_REGISTERED(pin);
-       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
-       dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv);
+       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
+       dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie);
        if (xa_empty(&pin->dpll_refs))
                xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
 }
@@ -680,7 +687,7 @@ void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
 
        mutex_lock(&dpll_lock);
        dpll_pin_delete_ntf(pin);
-       __dpll_pin_unregister(dpll, pin, ops, priv);
+       __dpll_pin_unregister(dpll, pin, ops, priv, NULL);
        mutex_unlock(&dpll_lock);
 }
 EXPORT_SYMBOL_GPL(dpll_pin_unregister);
@@ -716,12 +723,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
                return -EINVAL;
 
        mutex_lock(&dpll_lock);
-       ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv);
+       ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin);
        if (ret)
                goto unlock;
        refcount_inc(&pin->refcount);
        xa_for_each(&parent->dpll_refs, i, ref) {
-               ret = __dpll_pin_register(ref->dpll, pin, ops, priv);
+               ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent);
                if (ret) {
                        stop = i;
                        goto dpll_unregister;
@@ -735,11 +742,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
 dpll_unregister:
        xa_for_each(&parent->dpll_refs, i, ref)
                if (i < stop) {
-                       __dpll_pin_unregister(ref->dpll, pin, ops, priv);
+                       __dpll_pin_unregister(ref->dpll, pin, ops, priv,
+                                             parent);
                        dpll_pin_delete_ntf(pin);
                }
        refcount_dec(&pin->refcount);
-       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
+       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
 unlock:
        mutex_unlock(&dpll_lock);
        return ret;
@@ -764,10 +772,10 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
 
        mutex_lock(&dpll_lock);
        dpll_pin_delete_ntf(pin);
-       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
+       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
        refcount_dec(&pin->refcount);
        xa_for_each(&pin->dpll_refs, i, ref)
-               __dpll_pin_unregister(ref->dpll, pin, ops, priv);
+               __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent);
        mutex_unlock(&dpll_lock);
 }
 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister);
index c95787cb908673c6ab1b236e9c447952e5e8e452..59b5dd0e2f41d2a8751a4f5139e39302acb2b7bd 100644 (file)
@@ -566,13 +566,61 @@ static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported)
                phy_interface_set_rgmii(supported);
 }
 
-static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
-                                      struct phylink_config *config)
+static void
+mv88e6250_setup_supported_interfaces(struct mv88e6xxx_chip *chip, int port,
+                                    struct phylink_config *config)
 {
        unsigned long *supported = config->supported_interfaces;
+       int err;
+       u16 reg;
 
-       /* Translate the default cmode */
-       mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
+       if (err) {
+               dev_err(chip->dev, "p%d: failed to read port status\n", port);
+               return;
+       }
+
+       switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY:
+               __set_bit(PHY_INTERFACE_MODE_REVMII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_HALF:
+       case MV88E6250_PORT_STS_PORTMODE_MII_FULL:
+               __set_bit(PHY_INTERFACE_MODE_MII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY:
+               __set_bit(PHY_INTERFACE_MODE_REVRMII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL:
+               __set_bit(PHY_INTERFACE_MODE_RMII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII:
+               __set_bit(PHY_INTERFACE_MODE_RGMII, supported);
+               break;
+
+       default:
+               dev_err(chip->dev,
+                       "p%d: invalid port mode in status register: %04x\n",
+                       port, reg);
+       }
+}
+
+static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
+                                      struct phylink_config *config)
+{
+       if (!mv88e6xxx_phy_is_internal(chip, port))
+               mv88e6250_setup_supported_interfaces(chip, port, config);
 
        config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
 }
index 86deeb347cbc1d82526f362f719c57ac17039bf0..ddadeb9bfdaeed6978d85d55ccd2e52710971529 100644 (file)
 #define MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF       0x0900
 #define MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL                0x0a00
 #define MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL       0x0b00
-#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF                0x0c00
-#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF       0x0d00
-#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL                0x0e00
-#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL       0x0f00
+/* - Modes with PHY suffix use output instead of input clock
+ * - Modes without RMII or RGMII use MII
+ * - Modes without speed do not have a fixed speed specified in the manual
+ *   ("DC to x MHz" - variable clock support?)
+ */
+#define MV88E6250_PORT_STS_PORTMODE_MII_DISABLED               0x0000
+#define MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII              0x0100
+#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY 0x0200
+#define MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY      0x0400
+#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL     0x0600
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL       0x0700
+#define MV88E6250_PORT_STS_PORTMODE_MII_HALF                   0x0800
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY   0x0900
+#define MV88E6250_PORT_STS_PORTMODE_MII_FULL                   0x0a00
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY   0x0b00
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY            0x0c00
+#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY           0x0d00
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY            0x0e00
+#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY           0x0f00
 #define MV88E6XXX_PORT_STS_LINK                        0x0800
 #define MV88E6XXX_PORT_STS_DUPLEX              0x0400
 #define MV88E6XXX_PORT_STS_SPEED_MASK          0x0300
index 72ea97c5d5d424482fe6812cef1a013158319a70..82768b0e90262b80b949b959b40151a0ddd0b6a9 100644 (file)
@@ -436,10 +436,8 @@ static void umac_init(struct bcmasp_intf *intf)
        umac_wl(intf, 0x800, UMC_RX_MAX_PKT_SZ);
 }
 
-static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
+static int bcmasp_tx_reclaim(struct bcmasp_intf *intf)
 {
-       struct bcmasp_intf *intf =
-               container_of(napi, struct bcmasp_intf, tx_napi);
        struct bcmasp_intf_stats64 *stats = &intf->stats64;
        struct device *kdev = &intf->parent->pdev->dev;
        unsigned long read, released = 0;
@@ -482,10 +480,16 @@ static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
                                                        DESC_RING_COUNT);
        }
 
-       /* Ensure all descriptors have been written to DRAM for the hardware
-        * to see updated contents.
-        */
-       wmb();
+       return released;
+}
+
+static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
+{
+       struct bcmasp_intf *intf =
+               container_of(napi, struct bcmasp_intf, tx_napi);
+       int released = 0;
+
+       released = bcmasp_tx_reclaim(intf);
 
        napi_complete(&intf->tx_napi);
 
@@ -797,6 +801,7 @@ static void bcmasp_init_tx(struct bcmasp_intf *intf)
        intf->tx_spb_dma_read = intf->tx_spb_dma_addr;
        intf->tx_spb_index = 0;
        intf->tx_spb_clean_index = 0;
+       memset(intf->tx_cbs, 0, sizeof(struct bcmasp_tx_cb) * DESC_RING_COUNT);
 
        /* Make sure channels are disabled */
        tx_spb_ctrl_wl(intf, 0x0, TX_SPB_CTRL_ENABLE);
@@ -885,6 +890,8 @@ static void bcmasp_netif_deinit(struct net_device *dev)
        } while (timeout-- > 0);
        tx_spb_dma_wl(intf, 0x0, TX_SPB_DMA_FIFO_CTRL);
 
+       bcmasp_tx_reclaim(intf);
+
        umac_enable_set(intf, UMC_CMD_TX_EN, 0);
 
        phy_stop(dev->phydev);
index 3e4fb3c3e8342ad3dbf7aa32df03fc4ce57e3cad..1be6d14030bcffc0fd149b6be0af819964284a4e 100644 (file)
@@ -2009,12 +2009,14 @@ static int b44_set_pauseparam(struct net_device *dev,
                bp->flags |= B44_FLAG_TX_PAUSE;
        else
                bp->flags &= ~B44_FLAG_TX_PAUSE;
-       if (bp->flags & B44_FLAG_PAUSE_AUTO) {
-               b44_halt(bp);
-               b44_init_rings(bp);
-               b44_init_hw(bp, B44_FULL_RESET);
-       } else {
-               __b44_set_flow_ctrl(bp, bp->flags);
+       if (netif_running(dev)) {
+               if (bp->flags & B44_FLAG_PAUSE_AUTO) {
+                       b44_halt(bp);
+                       b44_init_rings(bp);
+                       b44_init_hw(bp, B44_FULL_RESET);
+               } else {
+                       __b44_set_flow_ctrl(bp, bp->flags);
+               }
        }
        spin_unlock_irq(&bp->lock);
 
index 57e61f9631678edf31a2ff237fe0301254a396e5..2c2ee79c4d77957761d8f3d9ca85bcecedd5fd0f 100644 (file)
@@ -1778,7 +1778,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                skb = bnxt_copy_skb(bnapi, data_ptr, len, mapping);
                if (!skb) {
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
        } else {
@@ -1788,7 +1788,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, GFP_ATOMIC);
                if (!new_data) {
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
 
@@ -1804,7 +1804,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                if (!skb) {
                        skb_free_frag(data);
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
                skb_reserve(skb, bp->rx_offset);
@@ -1815,7 +1815,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, idx, agg_bufs, true);
                if (!skb) {
                        /* Page reuse already handled by bnxt_rx_pages(). */
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
        }
@@ -2094,11 +2094,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                        u32 frag_len = bnxt_rx_agg_pages_xdp(bp, cpr, &xdp,
                                                             cp_cons, agg_bufs,
                                                             false);
-                       if (!frag_len) {
-                               cpr->sw_stats.rx.rx_oom_discards += 1;
-                               rc = -ENOMEM;
-                               goto next_rx;
-                       }
+                       if (!frag_len)
+                               goto oom_next_rx;
                }
                xdp_active = true;
        }
@@ -2121,9 +2118,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                                else
                                        bnxt_xdp_buff_frags_free(rxr, &xdp);
                        }
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
-                       rc = -ENOMEM;
-                       goto next_rx;
+                       goto oom_next_rx;
                }
        } else {
                u32 payload;
@@ -2134,29 +2129,21 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                        payload = 0;
                skb = bp->rx_skb_func(bp, rxr, cons, data, data_ptr, dma_addr,
                                      payload | len);
-               if (!skb) {
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
-                       rc = -ENOMEM;
-                       goto next_rx;
-               }
+               if (!skb)
+                       goto oom_next_rx;
        }
 
        if (agg_bufs) {
                if (!xdp_active) {
                        skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, cp_cons, agg_bufs, false);
-                       if (!skb) {
-                               cpr->sw_stats.rx.rx_oom_discards += 1;
-                               rc = -ENOMEM;
-                               goto next_rx;
-                       }
+                       if (!skb)
+                               goto oom_next_rx;
                } else {
                        skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, rxr->page_pool, &xdp, rxcmp1);
                        if (!skb) {
                                /* we should be able to free the old skb here */
                                bnxt_xdp_buff_frags_free(rxr, &xdp);
-                               cpr->sw_stats.rx.rx_oom_discards += 1;
-                               rc = -ENOMEM;
-                               goto next_rx;
+                               goto oom_next_rx;
                        }
                }
        }
@@ -2234,6 +2221,11 @@ next_rx_no_prod_no_len:
        *raw_cons = tmp_raw_cons;
 
        return rc;
+
+oom_next_rx:
+       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
+       rc = -ENOMEM;
+       goto next_rx;
 }
 
 /* In netpoll mode, if we are using a combined completion ring, we need to
@@ -2280,7 +2272,7 @@ static int bnxt_force_rx_discard(struct bnxt *bp,
        }
        rc = bnxt_rx_pkt(bp, cpr, raw_cons, event);
        if (rc && rc != -EBUSY)
-               cpr->sw_stats.rx.rx_netpoll_discards += 1;
+               cpr->bnapi->cp_ring.sw_stats.rx.rx_netpoll_discards += 1;
        return rc;
 }
 
@@ -9089,7 +9081,7 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
                                             BNXT_FW_HEALTH_WIN_BASE +
                                             BNXT_GRC_REG_CHIP_NUM);
                }
-               if (!BNXT_CHIP_P5(bp))
+               if (!BNXT_CHIP_P5_PLUS(bp))
                        return;
 
                status_loc = BNXT_GRC_REG_STATUS_P5 |
@@ -13037,6 +13029,16 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
        bnxt_rtnl_unlock_sp(bp);
 }
 
+static void bnxt_fw_fatal_close(struct bnxt *bp)
+{
+       bnxt_tx_disable(bp);
+       bnxt_disable_napi(bp);
+       bnxt_disable_int_sync(bp);
+       bnxt_free_irq(bp);
+       bnxt_clear_int_mode(bp);
+       pci_disable_device(bp->pdev);
+}
+
 static void bnxt_fw_reset_close(struct bnxt *bp)
 {
        bnxt_ulp_stop(bp);
@@ -13050,12 +13052,7 @@ static void bnxt_fw_reset_close(struct bnxt *bp)
                pci_read_config_word(bp->pdev, PCI_SUBSYSTEM_ID, &val);
                if (val == 0xffff)
                        bp->fw_reset_min_dsecs = 0;
-               bnxt_tx_disable(bp);
-               bnxt_disable_napi(bp);
-               bnxt_disable_int_sync(bp);
-               bnxt_free_irq(bp);
-               bnxt_clear_int_mode(bp);
-               pci_disable_device(bp->pdev);
+               bnxt_fw_fatal_close(bp);
        }
        __bnxt_close_nic(bp, true, false);
        bnxt_vf_reps_free(bp);
@@ -15373,6 +15370,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct bnxt *bp = netdev_priv(netdev);
+       bool abort = false;
 
        netdev_info(netdev, "PCI I/O error detected\n");
 
@@ -15381,16 +15379,27 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
 
        bnxt_ulp_stop(bp);
 
-       if (state == pci_channel_io_perm_failure) {
+       if (test_and_set_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
+               netdev_err(bp->dev, "Firmware reset already in progress\n");
+               abort = true;
+       }
+
+       if (abort || state == pci_channel_io_perm_failure) {
                rtnl_unlock();
                return PCI_ERS_RESULT_DISCONNECT;
        }
 
-       if (state == pci_channel_io_frozen)
+       /* Link is not reliable anymore if state is pci_channel_io_frozen
+        * so we disable bus master to prevent any potential bad DMAs before
+        * freeing kernel memory.
+        */
+       if (state == pci_channel_io_frozen) {
                set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state);
+               bnxt_fw_fatal_close(bp);
+       }
 
        if (netif_running(netdev))
-               bnxt_close(netdev);
+               __bnxt_close_nic(bp, true, true);
 
        if (pci_is_enabled(pdev))
                pci_disable_device(pdev);
@@ -15474,6 +15483,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
        }
 
 reset_exit:
+       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
        bnxt_clear_reservations(bp, true);
        rtnl_unlock();
 
index 48b9ddb2b1b38b385527f137124ce86a36ac036d..ffb9f9f15c5232e2aeb4a45c1209b6a0763062d7 100644 (file)
@@ -16107,8 +16107,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        val = FIELD_GET(I40E_PRTGL_SAH_MFS_MASK,
                        rd32(&pf->hw, I40E_PRTGL_SAH));
        if (val < MAX_FRAME_SIZE_DEFAULT)
-               dev_warn(&pdev->dev, "MFS for port %x has been set below the default: %x\n",
-                        pf->hw.port, val);
+               dev_warn(&pdev->dev, "MFS for port %x (%d) has been set below the default (%d)\n",
+                        pf->hw.port, val, MAX_FRAME_SIZE_DEFAULT);
 
        /* Add a filter to drop all Flow control frames from any VSI from being
         * transmitted. By doing so we stop a malicious VF from sending out
@@ -16650,7 +16650,7 @@ static int __init i40e_init_module(void)
         * since we need to be able to guarantee forward progress even under
         * memory pressure.
         */
-       i40e_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, i40e_driver_name);
+       i40e_wq = alloc_workqueue("%s", 0, 0, i40e_driver_name);
        if (!i40e_wq) {
                pr_err("%s: Failed to create workqueue\n", i40e_driver_name);
                return -ENOMEM;
index ef2440f3abf8b6aed9f47e5948f67a5dec52b51e..166832a4213a289f17198d748f4abea1d5e4efc4 100644 (file)
@@ -3502,6 +3502,34 @@ static void iavf_del_all_cloud_filters(struct iavf_adapter *adapter)
        spin_unlock_bh(&adapter->cloud_filter_list_lock);
 }
 
+/**
+ * iavf_is_tc_config_same - Compare the mqprio TC config with the
+ * TC config already configured on this adapter.
+ * @adapter: board private structure
+ * @mqprio_qopt: TC config received from kernel.
+ *
+ * This function compares the TC config received from the kernel
+ * with the config already configured on the adapter.
+ *
+ * Return: True if configuration is same, false otherwise.
+ **/
+static bool iavf_is_tc_config_same(struct iavf_adapter *adapter,
+                                  struct tc_mqprio_qopt *mqprio_qopt)
+{
+       struct virtchnl_channel_info *ch = &adapter->ch_config.ch_info[0];
+       int i;
+
+       if (adapter->num_tc != mqprio_qopt->num_tc)
+               return false;
+
+       for (i = 0; i < adapter->num_tc; i++) {
+               if (ch[i].count != mqprio_qopt->count[i] ||
+                   ch[i].offset != mqprio_qopt->offset[i])
+                       return false;
+       }
+       return true;
+}
+
 /**
  * __iavf_setup_tc - configure multiple traffic classes
  * @netdev: network interface device structure
@@ -3559,7 +3587,7 @@ static int __iavf_setup_tc(struct net_device *netdev, void *type_data)
                if (ret)
                        return ret;
                /* Return if same TC config is requested */
-               if (adapter->num_tc == num_tc)
+               if (iavf_is_tc_config_same(adapter, &mqprio_qopt->qopt))
                        return 0;
                adapter->num_tc = num_tc;
 
index 21d26e19338a69acb265a279bfc633bbfea0cad2..d10a4be965b591027c357be2c5ede2ab3269a7da 100644 (file)
@@ -856,6 +856,11 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
                return 0;
        }
 
+       if (flags & ICE_VF_RESET_LOCK)
+               mutex_lock(&vf->cfg_lock);
+       else
+               lockdep_assert_held(&vf->cfg_lock);
+
        lag = pf->lag;
        mutex_lock(&pf->lag_mutex);
        if (lag && lag->bonded && lag->primary) {
@@ -867,11 +872,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
                        act_prt = ICE_LAG_INVALID_PORT;
        }
 
-       if (flags & ICE_VF_RESET_LOCK)
-               mutex_lock(&vf->cfg_lock);
-       else
-               lockdep_assert_held(&vf->cfg_lock);
-
        if (ice_is_vf_disabled(vf)) {
                vsi = ice_get_vf_vsi(vf);
                if (!vsi) {
@@ -956,14 +956,14 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
        ice_mbx_clear_malvf(&vf->mbx_info);
 
 out_unlock:
-       if (flags & ICE_VF_RESET_LOCK)
-               mutex_unlock(&vf->cfg_lock);
-
        if (lag && lag->bonded && lag->primary &&
            act_prt != ICE_LAG_INVALID_PORT)
                ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt);
        mutex_unlock(&pf->lag_mutex);
 
+       if (flags & ICE_VF_RESET_LOCK)
+               mutex_unlock(&vf->cfg_lock);
+
        return err;
 }
 
index 90316dc58630874d98aeb4095dc991c259a593f4..6bc56c7c181e4882d3ec99ea86e01c8188682175 100644 (file)
@@ -298,6 +298,7 @@ struct igc_adapter {
 
        /* LEDs */
        struct mutex led_mutex;
+       struct igc_led_classdev *leds;
 };
 
 void igc_up(struct igc_adapter *adapter);
@@ -723,6 +724,7 @@ void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts);
 void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter);
 
 int igc_led_setup(struct igc_adapter *adapter);
+void igc_led_free(struct igc_adapter *adapter);
 
 #define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
 
index bf240c5daf8657b3f9dd89f58fda05f87e57e5ae..3929b25b6ae6eb55335a5a6eb7b6494c4cc21982 100644 (file)
@@ -236,8 +236,8 @@ static void igc_led_get_name(struct igc_adapter *adapter, int index, char *buf,
                 pci_dev_id(adapter->pdev), index);
 }
 
-static void igc_setup_ldev(struct igc_led_classdev *ldev,
-                          struct net_device *netdev, int index)
+static int igc_setup_ldev(struct igc_led_classdev *ldev,
+                         struct net_device *netdev, int index)
 {
        struct igc_adapter *adapter = netdev_priv(netdev);
        struct led_classdev *led_cdev = &ldev->led;
@@ -257,24 +257,46 @@ static void igc_setup_ldev(struct igc_led_classdev *ldev,
        led_cdev->hw_control_get = igc_led_hw_control_get;
        led_cdev->hw_control_get_device = igc_led_hw_control_get_device;
 
-       devm_led_classdev_register(&netdev->dev, led_cdev);
+       return led_classdev_register(&netdev->dev, led_cdev);
 }
 
 int igc_led_setup(struct igc_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
-       struct device *dev = &netdev->dev;
        struct igc_led_classdev *leds;
-       int i;
+       int i, err;
 
        mutex_init(&adapter->led_mutex);
 
-       leds = devm_kcalloc(dev, IGC_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
+       leds = kcalloc(IGC_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
        if (!leds)
                return -ENOMEM;
 
-       for (i = 0; i < IGC_NUM_LEDS; i++)
-               igc_setup_ldev(leds + i, netdev, i);
+       for (i = 0; i < IGC_NUM_LEDS; i++) {
+               err = igc_setup_ldev(leds + i, netdev, i);
+               if (err)
+                       goto err;
+       }
+
+       adapter->leds = leds;
 
        return 0;
+
+err:
+       for (i--; i >= 0; i--)
+               led_classdev_unregister(&((leds + i)->led));
+
+       kfree(leds);
+       return err;
+}
+
+void igc_led_free(struct igc_adapter *adapter)
+{
+       struct igc_led_classdev *leds = adapter->leds;
+       int i;
+
+       for (i = 0; i < IGC_NUM_LEDS; i++)
+               led_classdev_unregister(&((leds + i)->led));
+
+       kfree(leds);
 }
index 35ad40a803cb64a66b983b3a2103a8f15b808df5..4d975d620a8e4b925fe3798a792f2a365877c5a8 100644 (file)
@@ -7021,6 +7021,9 @@ static void igc_remove(struct pci_dev *pdev)
        cancel_work_sync(&adapter->watchdog_task);
        hrtimer_cancel(&adapter->hrtimer);
 
+       if (IS_ENABLED(CONFIG_IGC_LEDS))
+               igc_led_free(adapter);
+
        /* Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant.
         */
index be709f83f3318cd8766ca6a2e6b51b88fa8a30e3..e8b73b9d75e3118f56ee42a322d05491b0c325f0 100644 (file)
@@ -2181,7 +2181,6 @@ void rvu_npc_freemem(struct rvu *rvu)
 
        kfree(pkind->rsrc.bmap);
        npc_mcam_rsrcs_deinit(rvu);
-       kfree(mcam->counters.bmap);
        if (rvu->kpu_prfl_addr)
                iounmap(rvu->kpu_prfl_addr);
        else
index b2cabd6ab86cb9044f8d0dc404fa8a052d31938c..cc9bcc420032428eee5188e692991d50aaffc684 100644 (file)
@@ -1640,6 +1640,7 @@ static const struct macsec_ops macsec_offload_ops = {
        .mdo_add_secy = mlx5e_macsec_add_secy,
        .mdo_upd_secy = mlx5e_macsec_upd_secy,
        .mdo_del_secy = mlx5e_macsec_del_secy,
+       .rx_uses_md_dst = true,
 };
 
 bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb)
index e4d7739bd7c888fc774aeb82a5ece0ed894497d8..4a79c0d7e7ad8546aae5e51f7c23ce7ee8642674 100644 (file)
@@ -849,7 +849,7 @@ free_skb:
 
 static const struct mlxsw_listener mlxsw_emad_rx_listener =
        MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
-                 EMAD, DISCARD);
+                 EMAD, FORWARD);
 
 static int mlxsw_emad_tlv_enable(struct mlxsw_core *mlxsw_core)
 {
index 53b150b7ae4e708080cf152c1260983f4cbfc54e..6c06b0592760845f19311fdf4f91672f9209daef 100644 (file)
@@ -1357,24 +1357,20 @@ static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = {
        .got_inactive = mlxsw_env_got_inactive,
 };
 
-static int mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env)
+static void mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env)
 {
        char mcam_pl[MLXSW_REG_MCAM_LEN];
-       bool mcia_128b_supported;
+       bool mcia_128b_supported = false;
        int err;
 
        mlxsw_reg_mcam_pack(mcam_pl,
                            MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
        err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mcam), mcam_pl);
-       if (err)
-               return err;
-
-       mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B,
-                             &mcia_128b_supported);
+       if (!err)
+               mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B,
+                                     &mcia_128b_supported);
 
        mlxsw_env->max_eeprom_len = mcia_128b_supported ? 128 : 48;
-
-       return 0;
 }
 
 int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
@@ -1445,15 +1441,11 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
        if (err)
                goto err_type_set;
 
-       err = mlxsw_env_max_module_eeprom_len_query(env);
-       if (err)
-               goto err_eeprom_len_query;
-
+       mlxsw_env_max_module_eeprom_len_query(env);
        env->line_cards[0]->active = true;
 
        return 0;
 
-err_eeprom_len_query:
 err_type_set:
        mlxsw_env_module_event_disable(env, 0);
 err_mlxsw_env_module_event_enable:
index af99bf17eb36de0793b008c063c2a93c6c5b22c8..f42a1b1c9368733d2623643ac6abdd8ffe9b9aff 100644 (file)
@@ -1530,7 +1530,7 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
 {
        struct pci_dev *pdev = mlxsw_pci->pdev;
        char mcam_pl[MLXSW_REG_MCAM_LEN];
-       bool pci_reset_supported;
+       bool pci_reset_supported = false;
        u32 sys_status;
        int err;
 
@@ -1548,11 +1548,9 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
        mlxsw_reg_mcam_pack(mcam_pl,
                            MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
        err = mlxsw_reg_query(mlxsw_pci->core, MLXSW_REG(mcam), mcam_pl);
-       if (err)
-               return err;
-
-       mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
-                             &pci_reset_supported);
+       if (!err)
+               mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
+                                     &pci_reset_supported);
 
        if (pci_reset_supported) {
                pci_dbg(pdev, "Starting PCI reset flow\n");
index f20052776b3f2e9a3ac7181921a12c3858abea4b..92a406f02eae746b4244ca56619fb75c1a2f9d93 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
 #include <linux/refcount.h>
+#include <linux/idr.h>
 #include <net/devlink.h>
 #include <trace/events/mlxsw.h>
 
@@ -58,41 +59,43 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
 static int mlxsw_sp_acl_tcam_region_id_get(struct mlxsw_sp_acl_tcam *tcam,
                                           u16 *p_id)
 {
-       u16 id;
+       int id;
 
-       id = find_first_zero_bit(tcam->used_regions, tcam->max_regions);
-       if (id < tcam->max_regions) {
-               __set_bit(id, tcam->used_regions);
-               *p_id = id;
-               return 0;
-       }
-       return -ENOBUFS;
+       id = ida_alloc_max(&tcam->used_regions, tcam->max_regions - 1,
+                          GFP_KERNEL);
+       if (id < 0)
+               return id;
+
+       *p_id = id;
+
+       return 0;
 }
 
 static void mlxsw_sp_acl_tcam_region_id_put(struct mlxsw_sp_acl_tcam *tcam,
                                            u16 id)
 {
-       __clear_bit(id, tcam->used_regions);
+       ida_free(&tcam->used_regions, id);
 }
 
 static int mlxsw_sp_acl_tcam_group_id_get(struct mlxsw_sp_acl_tcam *tcam,
                                          u16 *p_id)
 {
-       u16 id;
+       int id;
 
-       id = find_first_zero_bit(tcam->used_groups, tcam->max_groups);
-       if (id < tcam->max_groups) {
-               __set_bit(id, tcam->used_groups);
-               *p_id = id;
-               return 0;
-       }
-       return -ENOBUFS;
+       id = ida_alloc_max(&tcam->used_groups, tcam->max_groups - 1,
+                          GFP_KERNEL);
+       if (id < 0)
+               return id;
+
+       *p_id = id;
+
+       return 0;
 }
 
 static void mlxsw_sp_acl_tcam_group_id_put(struct mlxsw_sp_acl_tcam *tcam,
                                           u16 id)
 {
-       __clear_bit(id, tcam->used_groups);
+       ida_free(&tcam->used_groups, id);
 }
 
 struct mlxsw_sp_acl_tcam_pattern {
@@ -715,7 +718,9 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
                             rehash.dw.work);
        int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS;
 
+       mutex_lock(&vregion->lock);
        mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits);
+       mutex_unlock(&vregion->lock);
        if (credits < 0)
                /* Rehash gone out of credits so it was interrupted.
                 * Schedule the work as soon as possible to continue.
@@ -725,6 +730,17 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
                mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
 }
 
+static void
+mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+       /* The entry markers are relative to the current chunk and therefore
+        * needs to be reset together with the chunk marker.
+        */
+       ctx->current_vchunk = NULL;
+       ctx->start_ventry = NULL;
+       ctx->stop_ventry = NULL;
+}
+
 static void
 mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk)
 {
@@ -747,7 +763,7 @@ mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *v
         * the current chunk pointer to make sure all chunks
         * are properly migrated.
         */
-       vregion->rehash.ctx.current_vchunk = NULL;
+       mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(&vregion->rehash.ctx);
 }
 
 static struct mlxsw_sp_acl_tcam_vregion *
@@ -820,10 +836,14 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
        struct mlxsw_sp_acl_tcam *tcam = vregion->tcam;
 
        if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
+               struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
+
                mutex_lock(&tcam->lock);
                list_del(&vregion->tlist);
                mutex_unlock(&tcam->lock);
-               cancel_delayed_work_sync(&vregion->rehash.dw);
+               if (cancel_delayed_work_sync(&vregion->rehash.dw) &&
+                   ctx->hints_priv)
+                       ops->region_rehash_hints_put(ctx->hints_priv);
        }
        mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
        if (vregion->region2)
@@ -1154,8 +1174,14 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp,
                                      struct mlxsw_sp_acl_tcam_ventry *ventry,
                                      bool *activity)
 {
-       return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp,
-                                                   ventry->entry, activity);
+       struct mlxsw_sp_acl_tcam_vregion *vregion = ventry->vchunk->vregion;
+       int err;
+
+       mutex_lock(&vregion->lock);
+       err = mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, ventry->entry,
+                                                  activity);
+       mutex_unlock(&vregion->lock);
+       return err;
 }
 
 static int
@@ -1189,6 +1215,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp,
 {
        struct mlxsw_sp_acl_tcam_chunk *new_chunk;
 
+       WARN_ON(vchunk->chunk2);
+
        new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
        if (IS_ERR(new_chunk))
                return PTR_ERR(new_chunk);
@@ -1207,7 +1235,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp,
 {
        mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
        vchunk->chunk2 = NULL;
-       ctx->current_vchunk = NULL;
+       mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
 }
 
 static int
@@ -1230,6 +1258,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
                return 0;
        }
 
+       if (list_empty(&vchunk->ventry_list))
+               goto out;
+
        /* If the migration got interrupted, we have the ventry to start from
         * stored in context.
         */
@@ -1239,6 +1270,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
                ventry = list_first_entry(&vchunk->ventry_list,
                                          typeof(*ventry), list);
 
+       WARN_ON(ventry->vchunk != vchunk);
+
        list_for_each_entry_from(ventry, &vchunk->ventry_list, list) {
                /* During rollback, once we reach the ventry that failed
                 * to migrate, we are done.
@@ -1279,6 +1312,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
                }
        }
 
+out:
        mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx);
        return 0;
 }
@@ -1292,6 +1326,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
        struct mlxsw_sp_acl_tcam_vchunk *vchunk;
        int err;
 
+       if (list_empty(&vregion->vchunk_list))
+               return 0;
+
        /* If the migration got interrupted, we have the vchunk
         * we are working on stored in context.
         */
@@ -1320,16 +1357,17 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
        int err, err2;
 
        trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
-       mutex_lock(&vregion->lock);
        err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
                                                   ctx, credits);
        if (err) {
+               if (ctx->this_is_rollback)
+                       return err;
                /* In case migration was not successful, we need to swap
                 * so the original region pointer is assigned again
                 * to vregion->region.
                 */
                swap(vregion->region, vregion->region2);
-               ctx->current_vchunk = NULL;
+               mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
                ctx->this_is_rollback = true;
                err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
                                                            ctx, credits);
@@ -1340,7 +1378,6 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
                        /* Let the rollback to be continued later on. */
                }
        }
-       mutex_unlock(&vregion->lock);
        trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
        return err;
 }
@@ -1389,6 +1426,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 
        ctx->hints_priv = hints_priv;
        ctx->this_is_rollback = false;
+       mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
 
        return 0;
 
@@ -1441,7 +1479,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
        err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion,
                                                ctx, credits);
        if (err) {
-               dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
+               dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
+               return;
        }
 
        if (*credits >= 0)
@@ -1549,19 +1588,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
        if (max_tcam_regions < max_regions)
                max_regions = max_tcam_regions;
 
-       tcam->used_regions = bitmap_zalloc(max_regions, GFP_KERNEL);
-       if (!tcam->used_regions) {
-               err = -ENOMEM;
-               goto err_alloc_used_regions;
-       }
+       ida_init(&tcam->used_regions);
        tcam->max_regions = max_regions;
 
        max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS);
-       tcam->used_groups = bitmap_zalloc(max_groups, GFP_KERNEL);
-       if (!tcam->used_groups) {
-               err = -ENOMEM;
-               goto err_alloc_used_groups;
-       }
+       ida_init(&tcam->used_groups);
        tcam->max_groups = max_groups;
        tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
                                                  ACL_MAX_GROUP_SIZE);
@@ -1575,10 +1606,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
        return 0;
 
 err_tcam_init:
-       bitmap_free(tcam->used_groups);
-err_alloc_used_groups:
-       bitmap_free(tcam->used_regions);
-err_alloc_used_regions:
+       ida_destroy(&tcam->used_groups);
+       ida_destroy(&tcam->used_regions);
        mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
 err_rehash_params_register:
        mutex_destroy(&tcam->lock);
@@ -1591,8 +1620,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
        const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
 
        ops->fini(mlxsw_sp, tcam->priv);
-       bitmap_free(tcam->used_groups);
-       bitmap_free(tcam->used_regions);
+       ida_destroy(&tcam->used_groups);
+       ida_destroy(&tcam->used_regions);
        mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
        mutex_destroy(&tcam->lock);
 }
index 462bf448497d33b74618c1f78001c0924c666dd5..79a1d8606512531730c2da490e01f47ac0fc6399 100644 (file)
@@ -6,15 +6,16 @@
 
 #include <linux/list.h>
 #include <linux/parman.h>
+#include <linux/idr.h>
 
 #include "reg.h"
 #include "spectrum.h"
 #include "core_acl_flex_keys.h"
 
 struct mlxsw_sp_acl_tcam {
-       unsigned long *used_regions; /* bit array */
+       struct ida used_regions;
        unsigned int max_regions;
-       unsigned long *used_groups;  /* bit array */
+       struct ida used_groups;
        unsigned int max_groups;
        unsigned int max_group_size;
        struct mutex lock; /* guards vregion list */
index fcb756d77681cbaf2a17d3e21ddffa5543bc9a84..9b1f639f64a10cfe89255996bb43d68771f38e5e 100644 (file)
@@ -2722,19 +2722,18 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name,
        struct platform_device *pdev = priv->pdev;
        struct net_device *ndev = priv->ndev;
        struct device *dev = &pdev->dev;
-       const char *dev_name;
+       const char *devname = dev_name(dev);
        unsigned long flags;
        int error, irq_num;
 
        if (irq_name) {
-               dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch);
-               if (!dev_name)
+               devname = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", devname, ch);
+               if (!devname)
                        return -ENOMEM;
 
                irq_num = platform_get_irq_byname(pdev, irq_name);
                flags = 0;
        } else {
-               dev_name = ndev->name;
                irq_num = platform_get_irq(pdev, 0);
                flags = IRQF_SHARED;
        }
@@ -2744,9 +2743,9 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name,
        if (irq)
                *irq = irq_num;
 
-       error = devm_request_irq(dev, irq_num, handler, flags, dev_name, ndev);
+       error = devm_request_irq(dev, irq_num, handler, flags, devname, ndev);
        if (error)
-               netdev_err(ndev, "cannot request IRQ %s\n", dev_name);
+               netdev_err(ndev, "cannot request IRQ %s\n", devname);
 
        return error;
 }
index c66618d91c28fe2bdf9886b3c476bdb014cd5fe5..f89716b1cfb640577d7ca009adfb99e9b9f00c54 100644 (file)
@@ -784,6 +784,11 @@ static bool am65_cpts_match_tx_ts(struct am65_cpts *cpts,
                struct am65_cpts_skb_cb_data *skb_cb =
                                        (struct am65_cpts_skb_cb_data *)skb->cb;
 
+               if ((ptp_classify_raw(skb) & PTP_CLASS_V1) &&
+                   ((mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK) ==
+                    (skb_cb->skb_mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK)))
+                       mtype_seqid = skb_cb->skb_mtype_seqid;
+
                if (mtype_seqid == skb_cb->skb_mtype_seqid) {
                        u64 ns = event->timestamp;
 
index cf7b73f8f450728930587dc0646a0bbaa1d2b476..b69af69a1ccd3614ab0051b3c7675ab6a42a7872 100644 (file)
@@ -421,12 +421,14 @@ static int prueth_init_rx_chns(struct prueth_emac *emac,
                if (!i)
                        fdqring_id = k3_udma_glue_rx_flow_get_fdq_id(rx_chn->rx_chn,
                                                                     i);
-               rx_chn->irq[i] = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i);
-               if (rx_chn->irq[i] <= 0) {
-                       ret = rx_chn->irq[i];
+               ret = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i);
+               if (ret <= 0) {
+                       if (!ret)
+                               ret = -ENXIO;
                        netdev_err(ndev, "Failed to get rx dma irq");
                        goto fail;
                }
+               rx_chn->irq[i] = ret;
        }
 
        return 0;
index 6dff2c85682d8bcdd97ca614447e205919d5decd..6fae161cbcb822614a8f36935559f364ee0a7dc8 100644 (file)
@@ -1598,7 +1598,7 @@ static void wx_set_num_queues(struct wx *wx)
  */
 static int wx_acquire_msix_vectors(struct wx *wx)
 {
-       struct irq_affinity affd = {0, };
+       struct irq_affinity affd = { .pre_vectors = 1 };
        int nvecs, i;
 
        /* We start by asking for one vector per queue pair */
index 2fa511227eac8490314c09821c7b6f1e1fdfed43..93295916b1d2b80751637dee4a0006688958c428 100644 (file)
@@ -20,8 +20,6 @@
 #include "txgbe_phy.h"
 #include "txgbe_hw.h"
 
-#define TXGBE_I2C_CLK_DEV_NAME "i2c_dw"
-
 static int txgbe_swnodes_register(struct txgbe *txgbe)
 {
        struct txgbe_nodes *nodes = &txgbe->nodes;
@@ -573,8 +571,8 @@ static int txgbe_clock_register(struct txgbe *txgbe)
        char clk_name[32];
        struct clk *clk;
 
-       snprintf(clk_name, sizeof(clk_name), "%s.%d",
-                TXGBE_I2C_CLK_DEV_NAME, pci_dev_id(pdev));
+       snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d",
+                pci_dev_id(pdev));
 
        clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000);
        if (IS_ERR(clk))
@@ -636,7 +634,7 @@ static int txgbe_i2c_register(struct txgbe *txgbe)
 
        info.parent = &pdev->dev;
        info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]);
-       info.name = TXGBE_I2C_CLK_DEV_NAME;
+       info.name = "i2c_designware";
        info.id = pci_dev_id(pdev);
 
        info.res = &DEFINE_RES_IRQ(pdev->irq);
index ba4704c2c640b860c55655607f8dd5cc044cfa3e..e62d6cbdf9bc6458064c7c0852fc23db095ae642 100644 (file)
@@ -1098,11 +1098,12 @@ out_hashtable:
 static void gtp_dellink(struct net_device *dev, struct list_head *head)
 {
        struct gtp_dev *gtp = netdev_priv(dev);
+       struct hlist_node *next;
        struct pdp_ctx *pctx;
        int i;
 
        for (i = 0; i < gtp->hash_size; i++)
-               hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid)
+               hlist_for_each_entry_safe(pctx, next, &gtp->tid_hash[i], hlist_tid)
                        pdp_context_delete(pctx);
 
        list_del_rcu(&gtp->list);
index 0206b84284ab5e0c95981ff86fa4b2a2a14c5c51..ff016c11b4a0383b6653a37ef4bc6344fff3f703 100644 (file)
@@ -999,10 +999,12 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
        struct metadata_dst *md_dst;
        struct macsec_rxh_data *rxd;
        struct macsec_dev *macsec;
+       bool is_macsec_md_dst;
 
        rcu_read_lock();
        rxd = macsec_data_rcu(skb->dev);
        md_dst = skb_metadata_dst(skb);
+       is_macsec_md_dst = md_dst && md_dst->type == METADATA_MACSEC;
 
        list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
                struct sk_buff *nskb;
@@ -1013,14 +1015,42 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
                 * the SecTAG, so we have to deduce which port to deliver to.
                 */
                if (macsec_is_offloaded(macsec) && netif_running(ndev)) {
-                       struct macsec_rx_sc *rx_sc = NULL;
+                       const struct macsec_ops *ops;
 
-                       if (md_dst && md_dst->type == METADATA_MACSEC)
-                               rx_sc = find_rx_sc(&macsec->secy, md_dst->u.macsec_info.sci);
+                       ops = macsec_get_ops(macsec, NULL);
 
-                       if (md_dst && md_dst->type == METADATA_MACSEC && !rx_sc)
+                       if (ops->rx_uses_md_dst && !is_macsec_md_dst)
                                continue;
 
+                       if (is_macsec_md_dst) {
+                               struct macsec_rx_sc *rx_sc;
+
+                               /* All drivers that implement MACsec offload
+                                * support using skb metadata destinations must
+                                * indicate that they do so.
+                                */
+                               DEBUG_NET_WARN_ON_ONCE(!ops->rx_uses_md_dst);
+                               rx_sc = find_rx_sc(&macsec->secy,
+                                                  md_dst->u.macsec_info.sci);
+                               if (!rx_sc)
+                                       continue;
+                               /* device indicated macsec offload occurred */
+                               skb->dev = ndev;
+                               skb->pkt_type = PACKET_HOST;
+                               eth_skb_pkt_type(skb, ndev);
+                               ret = RX_HANDLER_ANOTHER;
+                               goto out;
+                       }
+
+                       /* This datapath is insecure because it is unable to
+                        * enforce isolation of broadcast/multicast traffic and
+                        * unicast traffic with promiscuous mode on the macsec
+                        * netdev. Since the core stack has no mechanism to
+                        * check that the hardware did indeed receive MACsec
+                        * traffic, it is possible that the response handling
+                        * done by the MACsec port was to a plaintext packet.
+                        * This violates the MACsec protocol standard.
+                        */
                        if (ether_addr_equal_64bits(hdr->h_dest,
                                                    ndev->dev_addr)) {
                                /* exact match, divert skb to this port */
@@ -1036,14 +1066,10 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
                                        break;
 
                                nskb->dev = ndev;
-                               if (ether_addr_equal_64bits(hdr->h_dest,
-                                                           ndev->broadcast))
-                                       nskb->pkt_type = PACKET_BROADCAST;
-                               else
-                                       nskb->pkt_type = PACKET_MULTICAST;
+                               eth_skb_pkt_type(nskb, ndev);
 
                                __netif_rx(nskb);
-                       } else if (rx_sc || ndev->flags & IFF_PROMISC) {
+                       } else if (ndev->flags & IFF_PROMISC) {
                                skb->dev = ndev;
                                skb->pkt_type = PACKET_HOST;
                                ret = RX_HANDLER_ANOTHER;
index fa8c6fdcf30181067c7c3f164e997171908a70b8..d7aaefb5226b62ad5de3c3783c189b8f45b1a7c2 100644 (file)
@@ -695,7 +695,8 @@ static int dp83869_configure_mode(struct phy_device *phydev,
        phy_ctrl_val = dp83869->mode;
        if (phydev->interface == PHY_INTERFACE_MODE_MII) {
                if (dp83869->mode == DP83869_100M_MEDIA_CONVERT ||
-                   dp83869->mode == DP83869_RGMII_100_BASE) {
+                   dp83869->mode == DP83869_RGMII_100_BASE ||
+                   dp83869->mode == DP83869_RGMII_COPPER_ETHERNET) {
                        phy_ctrl_val |= DP83869_OP_MODE_MII;
                } else {
                        phydev_err(phydev, "selected op-mode is not valid with MII mode\n");
index 0f3a1538a8b8ee045953a3c5ff308dc824ea7c0a..f4f9412d0cd7e256f4b2e962dd18974e1120c0fb 100644 (file)
 #define   MTK_PHY_LED_ON_LINK1000              BIT(0)
 #define   MTK_PHY_LED_ON_LINK100               BIT(1)
 #define   MTK_PHY_LED_ON_LINK10                        BIT(2)
+#define   MTK_PHY_LED_ON_LINK                  (MTK_PHY_LED_ON_LINK10 |\
+                                                MTK_PHY_LED_ON_LINK100 |\
+                                                MTK_PHY_LED_ON_LINK1000)
 #define   MTK_PHY_LED_ON_LINKDOWN              BIT(3)
 #define   MTK_PHY_LED_ON_FDX                   BIT(4) /* Full duplex */
 #define   MTK_PHY_LED_ON_HDX                   BIT(5) /* Half duplex */
 #define   MTK_PHY_LED_BLINK_100RX              BIT(3)
 #define   MTK_PHY_LED_BLINK_10TX               BIT(4)
 #define   MTK_PHY_LED_BLINK_10RX               BIT(5)
+#define   MTK_PHY_LED_BLINK_RX                 (MTK_PHY_LED_BLINK_10RX |\
+                                                MTK_PHY_LED_BLINK_100RX |\
+                                                MTK_PHY_LED_BLINK_1000RX)
+#define   MTK_PHY_LED_BLINK_TX                 (MTK_PHY_LED_BLINK_10TX |\
+                                                MTK_PHY_LED_BLINK_100TX |\
+                                                MTK_PHY_LED_BLINK_1000TX)
 #define   MTK_PHY_LED_BLINK_COLLISION          BIT(6)
 #define   MTK_PHY_LED_BLINK_RX_CRC_ERR         BIT(7)
 #define   MTK_PHY_LED_BLINK_RX_IDLE_ERR                BIT(8)
@@ -1247,11 +1256,9 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
        if (blink < 0)
                return -EIO;
 
-       if ((on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 |
-                  MTK_PHY_LED_ON_LINK10)) ||
-           (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX |
-                     MTK_PHY_LED_BLINK_10RX | MTK_PHY_LED_BLINK_1000TX |
-                     MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX)))
+       if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
+                  MTK_PHY_LED_ON_LINKDOWN)) ||
+           (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
                set_bit(bit_netdev, &priv->led_state);
        else
                clear_bit(bit_netdev, &priv->led_state);
@@ -1269,7 +1276,7 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
        if (!rules)
                return 0;
 
-       if (on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK10))
+       if (on & MTK_PHY_LED_ON_LINK)
                *rules |= BIT(TRIGGER_NETDEV_LINK);
 
        if (on & MTK_PHY_LED_ON_LINK10)
@@ -1287,10 +1294,10 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
        if (on & MTK_PHY_LED_ON_HDX)
                *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
 
-       if (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | MTK_PHY_LED_BLINK_10RX))
+       if (blink & MTK_PHY_LED_BLINK_RX)
                *rules |= BIT(TRIGGER_NETDEV_RX);
 
-       if (blink & (MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX))
+       if (blink & MTK_PHY_LED_BLINK_TX)
                *rules |= BIT(TRIGGER_NETDEV_TX);
 
        return 0;
@@ -1323,15 +1330,19 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
                on |= MTK_PHY_LED_ON_LINK1000;
 
        if (rules & BIT(TRIGGER_NETDEV_RX)) {
-               blink |= MTK_PHY_LED_BLINK_10RX  |
-                        MTK_PHY_LED_BLINK_100RX |
-                        MTK_PHY_LED_BLINK_1000RX;
+               blink |= (on & MTK_PHY_LED_ON_LINK) ?
+                         (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) :
+                         MTK_PHY_LED_BLINK_RX;
        }
 
        if (rules & BIT(TRIGGER_NETDEV_TX)) {
-               blink |= MTK_PHY_LED_BLINK_10TX  |
-                        MTK_PHY_LED_BLINK_100TX |
-                        MTK_PHY_LED_BLINK_1000TX;
+               blink |= (on & MTK_PHY_LED_ON_LINK) ?
+                         (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) :
+                         MTK_PHY_LED_BLINK_TX;
        }
 
        if (blink || on)
@@ -1344,9 +1355,7 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
                                MTK_PHY_LED0_ON_CTRL,
                             MTK_PHY_LED_ON_FDX     |
                             MTK_PHY_LED_ON_HDX     |
-                            MTK_PHY_LED_ON_LINK10  |
-                            MTK_PHY_LED_ON_LINK100 |
-                            MTK_PHY_LED_ON_LINK1000,
+                            MTK_PHY_LED_ON_LINK,
                             on);
 
        if (ret)
index 752f821a19901f313a1aca51fe332539ce82385b..df9d767cb524241848c744504d6e2999efc42ed5 100644 (file)
@@ -1456,21 +1456,16 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                        /* Skip IP alignment pseudo header */
                        skb_pull(skb, 2);
 
-                       skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd);
                        ax88179_rx_checksum(skb, pkt_hdr);
                        return 1;
                }
 
-               ax_skb = skb_clone(skb, GFP_ATOMIC);
+               ax_skb = netdev_alloc_skb_ip_align(dev->net, pkt_len);
                if (!ax_skb)
                        return 0;
-               skb_trim(ax_skb, pkt_len);
+               skb_put(ax_skb, pkt_len);
+               memcpy(ax_skb->data, skb->data + 2, pkt_len);
 
-               /* Skip IP alignment pseudo header */
-               skb_pull(ax_skb, 2);
-
-               skb->truesize = pkt_len_plus_padd +
-                               SKB_DATA_ALIGN(sizeof(struct sk_buff));
                ax88179_rx_checksum(ax_skb, pkt_hdr);
                usbnet_skb_return(dev, ax_skb);
 
index edc34402e787f9ff84a345ecb892cc7b720ef312..a5469cf5cf6706de2c3ded24f675f504c794227c 100644 (file)
@@ -1368,6 +1368,9 @@ static const struct usb_device_id products[] = {
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990 */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1080, 2)}, /* Telit FE990 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */
        {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)},    /* Telit ME910 */
        {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)},    /* Telit ME910 dual modem */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
index 3495591a5c29b2aa929fcf307c2970c661ec2ea6..ba319fc219571975597bf7aad3d913e77dac6898 100644 (file)
@@ -1615,6 +1615,10 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
        if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
                return false;
 
+       /* Ignore packets from invalid src-address */
+       if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
+               return false;
+
        /* Get address from the outer IP header */
        if (vxlan_get_sk_family(vs) == AF_INET) {
                saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
index a6a37d67a50ad552b4185af654289d635c2cfd70..9f4bf41a3d41e4e1395aa77fb6874130e5783d96 100644 (file)
@@ -9020,6 +9020,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
        offload = &arvif->arp_ns_offload;
        count = 0;
 
+       /* Note: read_lock_bh() calls rcu_read_lock() */
        read_lock_bh(&idev->lock);
 
        memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr));
@@ -9050,7 +9051,8 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
        }
 
        /* get anycast address */
-       for (ifaca6 = idev->ac_list; ifaca6; ifaca6 = ifaca6->aca_next) {
+       for (ifaca6 = rcu_dereference(idev->ac_list); ifaca6;
+            ifaca6 = rcu_dereference(ifaca6->aca_next)) {
                if (count >= ATH11K_IPV6_MAX_COUNT)
                        goto generate;
 
index 072b0a5827d19f801d9f0da38933aef21044b7fc..eca1457caa0cad9eb13edce501beba6d5540fe57 100644 (file)
@@ -10,7 +10,7 @@
 #include "fw/api/txq.h"
 
 /* Highest firmware API version supported */
-#define IWL_BZ_UCODE_API_MAX   90
+#define IWL_BZ_UCODE_API_MAX   89
 
 /* Lowest firmware API version supported */
 #define IWL_BZ_UCODE_API_MIN   80
index 9b79279fd76cad94170d28614b7eee0729ac02f8..dbbcb2d0968c0992d15f652409cf651dc625428c 100644 (file)
@@ -10,7 +10,7 @@
 #include "fw/api/txq.h"
 
 /* Highest firmware API version supported */
-#define IWL_SC_UCODE_API_MAX   90
+#define IWL_SC_UCODE_API_MAX   89
 
 /* Lowest firmware API version supported */
 #define IWL_SC_UCODE_API_MIN   82
index 4863a3c746406ed70a398d8939e080e72636fa0b..d84d7e955bb021fc1994d1b5fa9e21183e01027a 100644 (file)
@@ -53,6 +53,8 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        if (!pasn)
                return -ENOBUFS;
 
+       iwl_mvm_ftm_remove_pasn_sta(mvm, addr);
+
        pasn->cipher = iwl_mvm_cipher_to_location_cipher(cipher);
 
        switch (pasn->cipher) {
index 9f69e04594e49cb59f3102071c905bd75b93f825..fe5bba8561d0c69abeef30221c5cc040f64c7b96 100644 (file)
@@ -279,6 +279,7 @@ int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id],
                         NULL);
+       iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
        return 0;
 }
 
@@ -296,7 +297,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                return 0;
 
        cmd.link_id = cpu_to_le32(link_info->fw_link_id);
-       iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
        link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
        cmd.spec_link_id = link_conf->link_id;
        cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);
index f3e3986b4c72f2aabfd9ff67edf8c11a1bebc03c..11559563ae38162e8c138dddc79e0cc89f3b349d 100644 (file)
@@ -2813,7 +2813,8 @@ static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm,
                if (ver_handler->version != scan_ver)
                        continue;
 
-               return ver_handler->handler(mvm, vif, params, type, uid);
+               err = ver_handler->handler(mvm, vif, params, type, uid);
+               return err ? : uid;
        }
 
        err = iwl_mvm_scan_umac(mvm, vif, params, type, uid);
index b55fe320633c74b42618d37be6bc40a951f0c898..59e1fc0018df3f32d60e3e52341350c10a44d0f0 100644 (file)
@@ -3899,7 +3899,7 @@ static int hwsim_pmsr_report_nl(struct sk_buff *msg, struct genl_info *info)
        }
 
        nla_for_each_nested(peer, peers, rem) {
-               struct cfg80211_pmsr_result result;
+               struct cfg80211_pmsr_result result = {};
 
                err = mac80211_hwsim_parse_pmsr_result(peer, &result, info);
                if (err)
index 7eb17f46a8153d88705603e421f350b0fd091c2b..9e1a34e23af26e0a2bd7e18b4e3fe5f6726f560d 100644 (file)
@@ -424,7 +424,8 @@ struct trf7970a {
        enum trf7970a_state             state;
        struct device                   *dev;
        struct spi_device               *spi;
-       struct regulator                *regulator;
+       struct regulator                *vin_regulator;
+       struct regulator                *vddio_regulator;
        struct nfc_digital_dev          *ddev;
        u32                             quirks;
        bool                            is_initiator;
@@ -1883,7 +1884,7 @@ static int trf7970a_power_up(struct trf7970a *trf)
        if (trf->state != TRF7970A_ST_PWR_OFF)
                return 0;
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vin_regulator);
        if (ret) {
                dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
                return ret;
@@ -1926,7 +1927,7 @@ static int trf7970a_power_down(struct trf7970a *trf)
        if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW))
                gpiod_set_value_cansleep(trf->en2_gpiod, 0);
 
-       ret = regulator_disable(trf->regulator);
+       ret = regulator_disable(trf->vin_regulator);
        if (ret)
                dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
                        ret);
@@ -2065,37 +2066,37 @@ static int trf7970a_probe(struct spi_device *spi)
        mutex_init(&trf->lock);
        INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);
 
-       trf->regulator = devm_regulator_get(&spi->dev, "vin");
-       if (IS_ERR(trf->regulator)) {
-               ret = PTR_ERR(trf->regulator);
+       trf->vin_regulator = devm_regulator_get(&spi->dev, "vin");
+       if (IS_ERR(trf->vin_regulator)) {
+               ret = PTR_ERR(trf->vin_regulator);
                dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
                goto err_destroy_lock;
        }
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vin_regulator);
        if (ret) {
                dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
                goto err_destroy_lock;
        }
 
-       uvolts = regulator_get_voltage(trf->regulator);
+       uvolts = regulator_get_voltage(trf->vin_regulator);
        if (uvolts > 4000000)
                trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
 
-       trf->regulator = devm_regulator_get(&spi->dev, "vdd-io");
-       if (IS_ERR(trf->regulator)) {
-               ret = PTR_ERR(trf->regulator);
+       trf->vddio_regulator = devm_regulator_get(&spi->dev, "vdd-io");
+       if (IS_ERR(trf->vddio_regulator)) {
+               ret = PTR_ERR(trf->vddio_regulator);
                dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
-               goto err_destroy_lock;
+               goto err_disable_vin_regulator;
        }
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vddio_regulator);
        if (ret) {
                dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
-               goto err_destroy_lock;
+               goto err_disable_vin_regulator;
        }
 
-       if (regulator_get_voltage(trf->regulator) == 1800000) {
+       if (regulator_get_voltage(trf->vddio_regulator) == 1800000) {
                trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
                dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
        }
@@ -2108,7 +2109,7 @@ static int trf7970a_probe(struct spi_device *spi)
        if (!trf->ddev) {
                dev_err(trf->dev, "Can't allocate NFC digital device\n");
                ret = -ENOMEM;
-               goto err_disable_regulator;
+               goto err_disable_vddio_regulator;
        }
 
        nfc_digital_set_parent_dev(trf->ddev, trf->dev);
@@ -2137,8 +2138,10 @@ err_shutdown:
        trf7970a_shutdown(trf);
 err_free_ddev:
        nfc_digital_free_device(trf->ddev);
-err_disable_regulator:
-       regulator_disable(trf->regulator);
+err_disable_vddio_regulator:
+       regulator_disable(trf->vddio_regulator);
+err_disable_vin_regulator:
+       regulator_disable(trf->vin_regulator);
 err_destroy_lock:
        mutex_destroy(&trf->lock);
        return ret;
@@ -2157,7 +2160,8 @@ static void trf7970a_remove(struct spi_device *spi)
        nfc_digital_unregister_device(trf->ddev);
        nfc_digital_free_device(trf->ddev);
 
-       regulator_disable(trf->regulator);
+       regulator_disable(trf->vddio_regulator);
+       regulator_disable(trf->vin_regulator);
 
        mutex_destroy(&trf->lock);
 }
index 224645f17c333b2311573197a28b41701eb35f92..297231854ada51ebeb5a8976db22e0e4702e5adb 100644 (file)
@@ -607,6 +607,31 @@ static inline void eth_hw_addr_gen(struct net_device *dev, const u8 *base_addr,
        eth_hw_addr_set(dev, addr);
 }
 
+/**
+ * eth_skb_pkt_type - Assign packet type if destination address does not match
+ * @skb: Assigned a packet type if address does not match @dev address
+ * @dev: Network device used to compare packet address against
+ *
+ * If the destination MAC address of the packet does not match the network
+ * device address, assign an appropriate packet type.
+ */
+static inline void eth_skb_pkt_type(struct sk_buff *skb,
+                                   const struct net_device *dev)
+{
+       const struct ethhdr *eth = eth_hdr(skb);
+
+       if (unlikely(!ether_addr_equal_64bits(eth->h_dest, dev->dev_addr))) {
+               if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
+                       if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
+                               skb->pkt_type = PACKET_BROADCAST;
+                       else
+                               skb->pkt_type = PACKET_MULTICAST;
+               } else {
+                       skb->pkt_type = PACKET_OTHERHOST;
+               }
+       }
+}
+
 /**
  * eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
  * @skb: Buffer to pad
index 627ea8e2d915984091944cf114c4d46d4631f6f4..3dee0b2721aa402ce020fcbda72250980afc52ad 100644 (file)
@@ -85,6 +85,9 @@ enum unix_socket_lock_class {
        U_LOCK_NORMAL,
        U_LOCK_SECOND,  /* for double locking, see unix_state_double_lock(). */
        U_LOCK_DIAG, /* used while dumping icons, see sk_diag_dump_icons(). */
+       U_LOCK_GC_LISTENER, /* used for listening socket while determining gc
+                            * candidates to close a small race window.
+                            */
 };
 
 static inline void unix_state_lock_nested(struct sock *sk,
index 56fb42df44a3331f3665499f5e81cdcdf2c2f64d..e8f581f3f3ce6d4fe3d0d6db8c8a9688daf4addb 100644 (file)
@@ -738,6 +738,8 @@ struct hci_conn {
        __u8            le_per_adv_data[HCI_MAX_PER_AD_TOT_LEN];
        __u16           le_per_adv_data_len;
        __u16           le_per_adv_data_offset;
+       __u8            le_adv_phy;
+       __u8            le_adv_sec_phy;
        __u8            le_tx_phy;
        __u8            le_rx_phy;
        __s8            rssi;
@@ -1512,7 +1514,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
                                     enum conn_reasons conn_reason);
 struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
                                u8 dst_type, bool dst_resolved, u8 sec_level,
-                               u16 conn_timeout, u8 role);
+                               u16 conn_timeout, u8 role, u8 phy, u8 sec_phy);
 void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status);
 struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
                                 u8 sec_level, u8 auth_type,
@@ -1905,6 +1907,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define privacy_mode_capable(dev) (use_ll_privacy(dev) && \
                                   (hdev->commands[39] & 0x04))
 
+#define read_key_size_capable(dev) \
+       ((dev)->commands[20] & 0x10 && \
+        !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks))
+
 /* Use enhanced synchronous connection if command is supported and its quirk
  * has not been set.
  */
index 353488ab94a294fd1fb2a985d015f9c8b59d421d..2d7f87bc5324b4823a8f70b960f0545bab8549c4 100644 (file)
@@ -953,6 +953,8 @@ enum mac80211_tx_info_flags {
  *     of their QoS TID or other priority field values.
  * @IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX: first MLO TX, used mostly internally
  *     for sequence number assignment
+ * @IEEE80211_TX_CTRL_SCAN_TX: Indicates that this frame is transmitted
+ *     due to scanning, not in normal operation on the interface.
  * @IEEE80211_TX_CTRL_MLO_LINK: If not @IEEE80211_LINK_UNSPECIFIED, this
  *     frame should be transmitted on the specific link. This really is
  *     only relevant for frames that do not have data present, and is
@@ -973,6 +975,7 @@ enum mac80211_tx_control_flags {
        IEEE80211_TX_CTRL_NO_SEQNO              = BIT(7),
        IEEE80211_TX_CTRL_DONT_REORDER          = BIT(8),
        IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX    = BIT(9),
+       IEEE80211_TX_CTRL_SCAN_TX               = BIT(10),
        IEEE80211_TX_CTRL_MLO_LINK              = 0xf0000000,
 };
 
index dbd22180cc5c3418cfa47261639d3ab7bbf55bee..de216cbc6b059fba9f795f83c6be43f5169c8649 100644 (file)
@@ -321,6 +321,7 @@ struct macsec_context {
  *     for the TX tag
  * @needed_tailroom: number of bytes reserved at the end of the sk_buff for the
  *     TX tag
+ * @rx_uses_md_dst: whether MACsec device offload supports sk_buff md_dst
  */
 struct macsec_ops {
        /* Device wide */
@@ -352,6 +353,7 @@ struct macsec_ops {
                                 struct sk_buff *skb);
        unsigned int needed_headroom;
        unsigned int needed_tailroom;
+       bool rx_uses_md_dst;
 };
 
 void macsec_pn_wrapped(struct macsec_secy *secy, struct macsec_tx_sa *tx_sa);
index f57bfd8a2ad2deaedf3f351325ab9336ae040504..b4b553df7870c0290ae632c51828ad7161ba332d 100644 (file)
@@ -1410,32 +1410,34 @@ sk_memory_allocated(const struct sock *sk)
 #define SK_MEMORY_PCPU_RESERVE (1 << (20 - PAGE_SHIFT))
 extern int sysctl_mem_pcpu_rsv;
 
+static inline void proto_memory_pcpu_drain(struct proto *proto)
+{
+       int val = this_cpu_xchg(*proto->per_cpu_fw_alloc, 0);
+
+       if (val)
+               atomic_long_add(val, proto->memory_allocated);
+}
+
 static inline void
-sk_memory_allocated_add(struct sock *sk, int amt)
+sk_memory_allocated_add(const struct sock *sk, int val)
 {
-       int local_reserve;
+       struct proto *proto = sk->sk_prot;
 
-       preempt_disable();
-       local_reserve = __this_cpu_add_return(*sk->sk_prot->per_cpu_fw_alloc, amt);
-       if (local_reserve >= READ_ONCE(sysctl_mem_pcpu_rsv)) {
-               __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve);
-               atomic_long_add(local_reserve, sk->sk_prot->memory_allocated);
-       }
-       preempt_enable();
+       val = this_cpu_add_return(*proto->per_cpu_fw_alloc, val);
+
+       if (unlikely(val >= READ_ONCE(sysctl_mem_pcpu_rsv)))
+               proto_memory_pcpu_drain(proto);
 }
 
 static inline void
-sk_memory_allocated_sub(struct sock *sk, int amt)
+sk_memory_allocated_sub(const struct sock *sk, int val)
 {
-       int local_reserve;
+       struct proto *proto = sk->sk_prot;
 
-       preempt_disable();
-       local_reserve = __this_cpu_sub_return(*sk->sk_prot->per_cpu_fw_alloc, amt);
-       if (local_reserve <= -READ_ONCE(sysctl_mem_pcpu_rsv)) {
-               __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve);
-               atomic_long_add(local_reserve, sk->sk_prot->memory_allocated);
-       }
-       preempt_enable();
+       val = this_cpu_sub_return(*proto->per_cpu_fw_alloc, val);
+
+       if (unlikely(val <= -READ_ONCE(sysctl_mem_pcpu_rsv)))
+               proto_memory_pcpu_drain(proto);
 }
 
 #define SK_ALLOC_PERCPU_COUNTER_BATCH 16
index 340ad43971e4711d8091a6397bb5cf3c3c4ef0fd..33f657d3c0510a0bd9e9899bc2530f9d035ce366 100644 (file)
@@ -111,7 +111,8 @@ struct tls_strparser {
        u32 stopped : 1;
        u32 copy_mode : 1;
        u32 mixed_decrypted : 1;
-       u32 msg_ready : 1;
+
+       bool msg_ready;
 
        struct strp_msg stm;
 
index 558e158c98d01075b7614b754a256124c3700a84..9169efb2f43aa9151131410496d3de24af1f1ccd 100644 (file)
@@ -103,7 +103,7 @@ again:
                        s->ax25_dev = NULL;
                        if (sk->sk_socket) {
                                netdev_put(ax25_dev->dev,
-                                          &ax25_dev->dev_tracker);
+                                          &s->dev_tracker);
                                ax25_dev_put(ax25_dev);
                        }
                        ax25_cb_del(s);
index 3ad74f76983b2426ffda03ac038daea0ea34662a..05346250f7195be3e01b11a0a671193f30316c5e 100644 (file)
@@ -1263,7 +1263,7 @@ u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
 
 struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
                                u8 dst_type, bool dst_resolved, u8 sec_level,
-                               u16 conn_timeout, u8 role)
+                               u16 conn_timeout, u8 role, u8 phy, u8 sec_phy)
 {
        struct hci_conn *conn;
        struct smp_irk *irk;
@@ -1326,6 +1326,8 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
        conn->dst_type = dst_type;
        conn->sec_level = BT_SECURITY_LOW;
        conn->conn_timeout = conn_timeout;
+       conn->le_adv_phy = phy;
+       conn->le_adv_sec_phy = sec_phy;
 
        err = hci_connect_le_sync(hdev, conn);
        if (err) {
@@ -2273,7 +2275,7 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
                le = hci_connect_le(hdev, dst, dst_type, false,
                                    BT_SECURITY_LOW,
                                    HCI_LE_CONN_TIMEOUT,
-                                   HCI_ROLE_SLAVE);
+                                   HCI_ROLE_SLAVE, 0, 0);
        else
                le = hci_connect_le_scan(hdev, dst, dst_type,
                                         BT_SECURITY_LOW,
index a8b8cfebe0180cce2fb661e8e5f21a79bf7a7656..4a27e4a17a67449ffd8a37cb057357e20881667c 100644 (file)
@@ -3218,7 +3218,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
                        if (key) {
                                set_bit(HCI_CONN_ENCRYPT, &conn->flags);
 
-                               if (!(hdev->commands[20] & 0x10)) {
+                               if (!read_key_size_capable(hdev)) {
                                        conn->enc_key_size = HCI_LINK_KEY_SIZE;
                                } else {
                                        cp.handle = cpu_to_le16(conn->handle);
@@ -3666,8 +3666,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
                 * controller really supports it. If it doesn't, assume
                 * the default size (16).
                 */
-               if (!(hdev->commands[20] & 0x10) ||
-                   test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks)) {
+               if (!read_key_size_capable(hdev)) {
                        conn->enc_key_size = HCI_LINK_KEY_SIZE;
                        goto notify;
                }
@@ -6038,7 +6037,7 @@ static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data,
 static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
                                              bdaddr_t *addr,
                                              u8 addr_type, bool addr_resolved,
-                                             u8 adv_type)
+                                             u8 adv_type, u8 phy, u8 sec_phy)
 {
        struct hci_conn *conn;
        struct hci_conn_params *params;
@@ -6093,7 +6092,7 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
 
        conn = hci_connect_le(hdev, addr, addr_type, addr_resolved,
                              BT_SECURITY_LOW, hdev->def_le_autoconnect_timeout,
-                             HCI_ROLE_MASTER);
+                             HCI_ROLE_MASTER, phy, sec_phy);
        if (!IS_ERR(conn)) {
                /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
                 * by higher layer that tried to connect, if no then
@@ -6128,8 +6127,9 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
 
 static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
                               u8 bdaddr_type, bdaddr_t *direct_addr,
-                              u8 direct_addr_type, s8 rssi, u8 *data, u8 len,
-                              bool ext_adv, bool ctl_time, u64 instant)
+                              u8 direct_addr_type, u8 phy, u8 sec_phy, s8 rssi,
+                              u8 *data, u8 len, bool ext_adv, bool ctl_time,
+                              u64 instant)
 {
        struct discovery_state *d = &hdev->discovery;
        struct smp_irk *irk;
@@ -6217,7 +6217,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
         * for advertising reports) and is already verified to be RPA above.
         */
        conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, bdaddr_resolved,
-                                    type);
+                                    type, phy, sec_phy);
        if (!ext_adv && conn && type == LE_ADV_IND &&
            len <= max_adv_len(hdev)) {
                /* Store report for later inclusion by
@@ -6363,7 +6363,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data,
                if (info->length <= max_adv_len(hdev)) {
                        rssi = info->data[info->length];
                        process_adv_report(hdev, info->type, &info->bdaddr,
-                                          info->bdaddr_type, NULL, 0, rssi,
+                                          info->bdaddr_type, NULL, 0,
+                                          HCI_ADV_PHY_1M, 0, rssi,
                                           info->data, info->length, false,
                                           false, instant);
                } else {
@@ -6448,6 +6449,8 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
                if (legacy_evt_type != LE_ADV_INVALID) {
                        process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
                                           info->bdaddr_type, NULL, 0,
+                                          info->primary_phy,
+                                          info->secondary_phy,
                                           info->rssi, info->data, info->length,
                                           !(evt_type & LE_EXT_ADV_LEGACY_PDU),
                                           false, instant);
@@ -6730,8 +6733,8 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data,
 
                process_adv_report(hdev, info->type, &info->bdaddr,
                                   info->bdaddr_type, &info->direct_addr,
-                                  info->direct_addr_type, info->rssi, NULL, 0,
-                                  false, false, instant);
+                                  info->direct_addr_type, HCI_ADV_PHY_1M, 0,
+                                  info->rssi, NULL, 0, false, false, instant);
        }
 
        hci_dev_unlock(hdev);
index c5d8799046ccffbf798e6f47ffaef3dddcb364ca..4c707eb64e6f63d8e2ea85a7ac12a31060dcf7e4 100644 (file)
@@ -6346,7 +6346,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
 
        plen = sizeof(*cp);
 
-       if (scan_1m(hdev)) {
+       if (scan_1m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_1M ||
+                             conn->le_adv_sec_phy == HCI_ADV_PHY_1M)) {
                cp->phys |= LE_SCAN_PHY_1M;
                set_ext_conn_params(conn, p);
 
@@ -6354,7 +6355,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
                plen += sizeof(*p);
        }
 
-       if (scan_2m(hdev)) {
+       if (scan_2m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_2M ||
+                             conn->le_adv_sec_phy == HCI_ADV_PHY_2M)) {
                cp->phys |= LE_SCAN_PHY_2M;
                set_ext_conn_params(conn, p);
 
@@ -6362,7 +6364,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
                plen += sizeof(*p);
        }
 
-       if (scan_coded(hdev)) {
+       if (scan_coded(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_CODED ||
+                                conn->le_adv_sec_phy == HCI_ADV_PHY_CODED)) {
                cp->phys |= LE_SCAN_PHY_CODED;
                set_ext_conn_params(conn, p);
 
index dc089740879363dd0d6d973dcdb4fc05cfc7070a..84fc70862d78aeef25d6ca9e6df7fb468338852e 100644 (file)
@@ -7018,7 +7018,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
                if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
                        hcon = hci_connect_le(hdev, dst, dst_type, false,
                                              chan->sec_level, timeout,
-                                             HCI_ROLE_SLAVE);
+                                             HCI_ROLE_SLAVE, 0, 0);
                else
                        hcon = hci_connect_le_scan(hdev, dst, dst_type,
                                                   chan->sec_level, timeout,
index e7d810b23082f5ffd8ea4b506366b2684f2e1ece..5cc83f906c123ffa7349d26a41c310005920aca5 100644 (file)
@@ -439,7 +439,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
        struct l2cap_options opts;
        struct l2cap_conninfo cinfo;
-       int len, err = 0;
+       int err = 0;
+       size_t len;
        u32 opt;
 
        BT_DBG("sk %p", sk);
@@ -486,7 +487,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
 
                BT_DBG("mode 0x%2.2x", chan->mode);
 
-               len = min_t(unsigned int, len, sizeof(opts));
+               len = min(len, sizeof(opts));
                if (copy_to_user(optval, (char *) &opts, len))
                        err = -EFAULT;
 
@@ -536,7 +537,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
                cinfo.hci_handle = chan->conn->hcon->handle;
                memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
 
-               len = min_t(unsigned int, len, sizeof(cinfo));
+               len = min(len, sizeof(cinfo));
                if (copy_to_user(optval, (char *) &cinfo, len))
                        err = -EFAULT;
 
index 32ed6e9245a307483e69ccb1cb1dd8c30c023130..965f621ef865adb607a6ccf71f6b2e7429a10a99 100644 (file)
@@ -2623,7 +2623,11 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
                goto failed;
        }
 
-       err = hci_cmd_sync_queue(hdev, add_uuid_sync, cmd, mgmt_class_complete);
+       /* MGMT_OP_ADD_UUID don't require adapter the UP/Running so use
+        * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
+        */
+       err = hci_cmd_sync_submit(hdev, add_uuid_sync, cmd,
+                                 mgmt_class_complete);
        if (err < 0) {
                mgmt_pending_free(cmd);
                goto failed;
@@ -2717,8 +2721,11 @@ update_class:
                goto unlock;
        }
 
-       err = hci_cmd_sync_queue(hdev, remove_uuid_sync, cmd,
-                                mgmt_class_complete);
+       /* MGMT_OP_REMOVE_UUID don't require adapter the UP/Running so use
+        * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
+        */
+       err = hci_cmd_sync_submit(hdev, remove_uuid_sync, cmd,
+                                 mgmt_class_complete);
        if (err < 0)
                mgmt_pending_free(cmd);
 
@@ -2784,8 +2791,11 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
                goto unlock;
        }
 
-       err = hci_cmd_sync_queue(hdev, set_class_sync, cmd,
-                                mgmt_class_complete);
+       /* MGMT_OP_SET_DEV_CLASS don't require adapter the UP/Running so use
+        * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
+        */
+       err = hci_cmd_sync_submit(hdev, set_class_sync, cmd,
+                                 mgmt_class_complete);
        if (err < 0)
                mgmt_pending_free(cmd);
 
@@ -5475,8 +5485,8 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
                goto unlock;
        }
 
-       err = hci_cmd_sync_queue(hdev, mgmt_remove_adv_monitor_sync, cmd,
-                                mgmt_remove_adv_monitor_complete);
+       err = hci_cmd_sync_submit(hdev, mgmt_remove_adv_monitor_sync, cmd,
+                                 mgmt_remove_adv_monitor_complete);
 
        if (err) {
                mgmt_pending_remove(cmd);
index 368e026f4d15ca4711737af941ad30c7b48b827f..5d03c5440b06f843e654ddb0e3d3f83d4dd0cfd9 100644 (file)
@@ -964,7 +964,8 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
        struct sock *sk = sock->sk;
        struct sco_options opts;
        struct sco_conninfo cinfo;
-       int len, err = 0;
+       int err = 0;
+       size_t len;
 
        BT_DBG("sk %p", sk);
 
@@ -986,7 +987,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
 
                BT_DBG("mtu %u", opts.mtu);
 
-               len = min_t(unsigned int, len, sizeof(opts));
+               len = min(len, sizeof(opts));
                if (copy_to_user(optval, (char *)&opts, len))
                        err = -EFAULT;
 
@@ -1004,7 +1005,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
                cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
                memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
 
-               len = min_t(unsigned int, len, sizeof(cinfo));
+               len = min(len, sizeof(cinfo));
                if (copy_to_user(optval, (char *)&cinfo, len))
                        err = -EFAULT;
 
index 2cf4fc756263992eefe6a3580410766fea0c2c1f..f17dbac7d82843091f9131acc68a5a9132fa2eda 100644 (file)
@@ -667,7 +667,7 @@ void br_ifinfo_notify(int event, const struct net_bridge *br,
 {
        u32 filter = RTEXT_FILTER_BRVLAN_COMPRESSED;
 
-       return br_info_notify(event, br, port, filter);
+       br_info_notify(event, br, port, filter);
 }
 
 /*
index 2edc8b796a4e7326aa44128a0618e15b9aa817de..049c3adeb85044ac78e5adf7dcfb389d21e75652 100644 (file)
@@ -164,17 +164,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
        eth = (struct ethhdr *)skb->data;
        skb_pull_inline(skb, ETH_HLEN);
 
-       if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
-                                             dev->dev_addr))) {
-               if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
-                       if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
-                               skb->pkt_type = PACKET_BROADCAST;
-                       else
-                               skb->pkt_type = PACKET_MULTICAST;
-               } else {
-                       skb->pkt_type = PACKET_OTHERHOST;
-               }
-       }
+       eth_skb_pkt_type(skb, dev);
 
        /*
         * Some variants of DSA tagging don't have an ethertype field
index e63a3bf99617627e17669f9b3aaee1cbbf178ebf..437e782b9663bb59acb900c0558137ddd401cd02 100644 (file)
@@ -92,6 +92,7 @@
 #include <net/inet_common.h>
 #include <net/ip_fib.h>
 #include <net/l3mdev.h>
+#include <net/addrconf.h>
 
 /*
  *     Build xmit assembly blocks
@@ -1032,6 +1033,8 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
        struct icmp_ext_hdr *ext_hdr, _ext_hdr;
        struct icmp_ext_echo_iio *iio, _iio;
        struct net *net = dev_net(skb->dev);
+       struct inet6_dev *in6_dev;
+       struct in_device *in_dev;
        struct net_device *dev;
        char buff[IFNAMSIZ];
        u16 ident_len;
@@ -1115,10 +1118,15 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
        /* Fill bits in reply message */
        if (dev->flags & IFF_UP)
                status |= ICMP_EXT_ECHOREPLY_ACTIVE;
-       if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list)
+
+       in_dev = __in_dev_get_rcu(dev);
+       if (in_dev && rcu_access_pointer(in_dev->ifa_list))
                status |= ICMP_EXT_ECHOREPLY_IPV4;
-       if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list))
+
+       in6_dev = __in6_dev_get(dev);
+       if (in6_dev && !list_empty(&in6_dev->addr_list))
                status |= ICMP_EXT_ECHOREPLY_IPV6;
+
        dev_put(dev);
        icmphdr->un.echo.sequence |= htons(status);
        return true;
index d36ace160d426f6224f8e692f3b438ae863bb9b9..b814fdab19f710d066d323970be6ce57a3b583c5 100644 (file)
@@ -2166,6 +2166,9 @@ int ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        int err = -EINVAL;
        u32 tag = 0;
 
+       if (!in_dev)
+               return -EINVAL;
+
        if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))
                goto martian_source;
 
index 3afeeb68e8a7e2a30ce9c4d92dcc8b150314b669..781b67a525719a42f21b713eb424427670d7afb2 100644 (file)
@@ -1068,6 +1068,7 @@ void tcp_ao_connect_init(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_ao_info *ao_info;
+       struct hlist_node *next;
        union tcp_ao_addr *addr;
        struct tcp_ao_key *key;
        int family, l3index;
@@ -1090,7 +1091,7 @@ void tcp_ao_connect_init(struct sock *sk)
        l3index = l3mdev_master_ifindex_by_index(sock_net(sk),
                                                 sk->sk_bound_dev_if);
 
-       hlist_for_each_entry_rcu(key, &ao_info->head, node) {
+       hlist_for_each_entry_safe(key, next, &ao_info->head, node) {
                if (!tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1))
                        continue;
 
index c02bf011d4a6f487b2c69e48e5032068eed3debc..420905be5f30c944ff360b349ae29d66104e0286 100644 (file)
@@ -1123,16 +1123,17 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        if (msg->msg_controllen) {
                err = udp_cmsg_send(sk, msg, &ipc.gso_size);
-               if (err > 0)
+               if (err > 0) {
                        err = ip_cmsg_send(sk, msg, &ipc,
                                           sk->sk_family == AF_INET6);
+                       connected = 0;
+               }
                if (unlikely(err < 0)) {
                        kfree(ipc.opt);
                        return err;
                }
                if (ipc.opt)
                        free = 1;
-               connected = 0;
        }
        if (!ipc.opt) {
                struct ip_options_rcu *inet_opt;
index 8b1dd7f512491d806e4d0a9fc5297a255dafd5a4..1a4cccdd40c9ca44675cea5f5c2a08724ccb2d75 100644 (file)
@@ -1474,9 +1474,11 @@ do_udp_sendmsg:
                ipc6.opt = opt;
 
                err = udp_cmsg_send(sk, msg, &ipc6.gso_size);
-               if (err > 0)
+               if (err > 0) {
                        err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, fl6,
                                                    &ipc6);
+                       connected = false;
+               }
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
@@ -1488,7 +1490,6 @@ do_udp_sendmsg:
                }
                if (!(opt->opt_nflen|opt->opt_flen))
                        opt = NULL;
-               connected = false;
        }
        if (!opt) {
                opt = txopt_get(np);
index 80e4b9784131d149c6acf27f79be0b0c16edec85..ccacaed32817aed59240034f85753c47a353501a 100644 (file)
@@ -797,6 +797,7 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_chanctx_conf *conf;
        struct ieee80211_chanctx *curr_ctx = NULL;
+       bool new_idle;
        int ret = 0;
 
        if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
@@ -829,8 +830,6 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
 out:
        rcu_assign_pointer(link->conf->chanctx_conf, conf);
 
-       sdata->vif.cfg.idle = !conf;
-
        if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
                ieee80211_recalc_chanctx_chantype(local, curr_ctx);
                ieee80211_recalc_smps_chanctx(local, curr_ctx);
@@ -843,9 +842,27 @@ out:
                ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL);
        }
 
-       if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
-           sdata->vif.type != NL80211_IFTYPE_MONITOR)
-               ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
+       if (conf) {
+               new_idle = false;
+       } else {
+               struct ieee80211_link_data *tmp;
+
+               new_idle = true;
+               for_each_sdata_link(local, tmp) {
+                       if (rcu_access_pointer(tmp->conf->chanctx_conf)) {
+                               new_idle = false;
+                               break;
+                       }
+               }
+       }
+
+       if (new_idle != sdata->vif.cfg.idle) {
+               sdata->vif.cfg.idle = new_idle;
+
+               if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
+                   sdata->vif.type != NL80211_IFTYPE_MONITOR)
+                       ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
+       }
 
        ieee80211_check_fast_xmit_iface(sdata);
 
index 32475da98d739cbe66d200f6bd8e8b0542f3cb04..cbc9b5e40cb35e81fb80dd55016c3afc8c31deb7 100644 (file)
@@ -747,6 +747,9 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
                              struct sk_buff *skb, u32 ctrl_flags)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+       struct ieee80211_mesh_fast_tx_key key = {
+               .type = MESH_FAST_TX_TYPE_LOCAL
+       };
        struct ieee80211_mesh_fast_tx *entry;
        struct ieee80211s_hdr *meshhdr;
        u8 sa[ETH_ALEN] __aligned(2);
@@ -782,7 +785,10 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
                        return false;
        }
 
-       entry = mesh_fast_tx_get(sdata, skb->data);
+       ether_addr_copy(key.addr, skb->data);
+       if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr))
+               key.type = MESH_FAST_TX_TYPE_PROXIED;
+       entry = mesh_fast_tx_get(sdata, &key);
        if (!entry)
                return false;
 
index d913ce7ba72ef897fb6857f55df3fb20bc871b5e..3f9664e4e00c6c2e51faaa43d1a23860a6d22e4c 100644 (file)
@@ -134,10 +134,39 @@ struct mesh_path {
 #define MESH_FAST_TX_CACHE_THRESHOLD_SIZE      384
 #define MESH_FAST_TX_CACHE_TIMEOUT             8000 /* msecs */
 
+/**
+ * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type
+ *
+ * @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA
+ * @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged)
+ * @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point
+ * @NUM_MESH_FAST_TX_TYPE: number of entry types
+ */
+enum ieee80211_mesh_fast_tx_type {
+       MESH_FAST_TX_TYPE_LOCAL,
+       MESH_FAST_TX_TYPE_PROXIED,
+       MESH_FAST_TX_TYPE_FORWARDED,
+
+       /* must be last */
+       NUM_MESH_FAST_TX_TYPE
+};
+
+
+/**
+ * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key
+ *
+ * @addr: The Ethernet DA for this entry
+ * @type: cache entry type
+ */
+struct ieee80211_mesh_fast_tx_key {
+       u8 addr[ETH_ALEN] __aligned(2);
+       u16 type;
+};
+
 /**
  * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
  * @rhash: rhashtable pointer
- * @addr_key: The Ethernet DA which is the key for this entry
+ * @key: the lookup key for this cache entry
  * @fast_tx: base fast_tx data
  * @hdr: cached mesh and rfc1042 headers
  * @hdrlen: length of mesh + rfc1042
@@ -148,7 +177,7 @@ struct mesh_path {
  */
 struct ieee80211_mesh_fast_tx {
        struct rhash_head rhash;
-       u8 addr_key[ETH_ALEN] __aligned(2);
+       struct ieee80211_mesh_fast_tx_key key;
 
        struct ieee80211_fast_tx fast_tx;
        u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
@@ -334,7 +363,8 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
 
 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
 struct ieee80211_mesh_fast_tx *
-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_mesh_fast_tx_key *key);
 bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
                              struct sk_buff *skb, u32 ctrl_flags);
 void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
index 91b55d6a68b9739f9d22786bf403c801fc34d864..a6b62169f08483c5aa481f4f8f59f67fa56a4ef7 100644 (file)
@@ -37,8 +37,8 @@ static const struct rhashtable_params mesh_rht_params = {
 static const struct rhashtable_params fast_tx_rht_params = {
        .nelem_hint = 10,
        .automatic_shrinking = true,
-       .key_len = ETH_ALEN,
-       .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
+       .key_len = sizeof_field(struct ieee80211_mesh_fast_tx, key),
+       .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key),
        .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
        .hashfn = mesh_table_hash,
 };
@@ -431,20 +431,21 @@ static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache,
 }
 
 struct ieee80211_mesh_fast_tx *
-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_mesh_fast_tx_key *key)
 {
        struct ieee80211_mesh_fast_tx *entry;
        struct mesh_tx_cache *cache;
 
        cache = &sdata->u.mesh.tx_cache;
-       entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
+       entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
        if (!entry)
                return NULL;
 
        if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
            mpath_expired(entry->mpath)) {
                spin_lock_bh(&cache->walk_lock);
-               entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
+               entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
                if (entry)
                    mesh_fast_tx_entry_free(cache, entry);
                spin_unlock_bh(&cache->walk_lock);
@@ -489,18 +490,24 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
        if (!sta)
                return;
 
+       build.key.type = MESH_FAST_TX_TYPE_LOCAL;
        if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
                /* This is required to keep the mppath alive */
                mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
                if (!mppath)
                        return;
                build.mppath = mppath;
+               if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
+                       build.key.type = MESH_FAST_TX_TYPE_PROXIED;
        } else if (ieee80211_has_a4(hdr->frame_control)) {
                mppath = mpath;
        } else {
                return;
        }
 
+       if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
+               build.key.type = MESH_FAST_TX_TYPE_FORWARDED;
+
        /* rate limit, in case fast xmit can't be enabled */
        if (mppath->fast_tx_check == jiffies)
                return;
@@ -547,7 +554,7 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
                }
        }
 
-       memcpy(build.addr_key, mppath->dst, ETH_ALEN);
+       memcpy(build.key.addr, mppath->dst, ETH_ALEN);
        build.timestamp = jiffies;
        build.fast_tx.band = info->band;
        build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
@@ -646,12 +653,18 @@ void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
                             const u8 *addr)
 {
        struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
+       struct ieee80211_mesh_fast_tx_key key = {};
        struct ieee80211_mesh_fast_tx *entry;
+       int i;
 
+       ether_addr_copy(key.addr, addr);
        spin_lock_bh(&cache->walk_lock);
-       entry = rhashtable_lookup_fast(&cache->rht, addr, fast_tx_rht_params);
-       if (entry)
-               mesh_fast_tx_entry_free(cache, entry);
+       for (i = 0; i < NUM_MESH_FAST_TX_TYPE; i++) {
+               key.type = i;
+               entry = rhashtable_lookup_fast(&cache->rht, &key, fast_tx_rht_params);
+               if (entry)
+                       mesh_fast_tx_entry_free(cache, entry);
+       }
        spin_unlock_bh(&cache->walk_lock);
 }
 
index 96b70006b7fc0b11b12f423fb74ec32a030d91af..3bbb216a0fc8ce58138420d13008b2240e260a77 100644 (file)
@@ -616,7 +616,6 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
                .from_ap = true,
                .start = ies->data,
                .len = ies->len,
-               .mode = conn->mode,
        };
        struct ieee802_11_elems *elems;
        struct ieee80211_supported_band *sband;
@@ -625,6 +624,7 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
        int ret;
 
 again:
+       parse_params.mode = conn->mode;
        elems = ieee802_11_parse_elems_full(&parse_params);
        if (!elems)
                return ERR_PTR(-ENOMEM);
@@ -632,15 +632,21 @@ again:
        ap_mode = ieee80211_determine_ap_chan(sdata, channel, bss->vht_cap_info,
                                              elems, false, conn, &ap_chandef);
 
-       mlme_link_id_dbg(sdata, link_id, "determined AP %pM to be %s\n",
-                        cbss->bssid, ieee80211_conn_mode_str(ap_mode));
-
        /* this should be impossible since parsing depends on our mode */
        if (WARN_ON(ap_mode > conn->mode)) {
                ret = -EINVAL;
                goto free;
        }
 
+       if (conn->mode != ap_mode) {
+               conn->mode = ap_mode;
+               kfree(elems);
+               goto again;
+       }
+
+       mlme_link_id_dbg(sdata, link_id, "determined AP %pM to be %s\n",
+                        cbss->bssid, ieee80211_conn_mode_str(ap_mode));
+
        sband = sdata->local->hw.wiphy->bands[channel->band];
 
        switch (channel->band) {
@@ -691,7 +697,6 @@ again:
                break;
        }
 
-       conn->mode = ap_mode;
        chanreq->oper = ap_chandef;
 
        /* wider-bandwidth OFDMA is only done in EHT */
@@ -753,8 +758,10 @@ again:
        }
 
        /* the mode can only decrease, so this must terminate */
-       if (ap_mode != conn->mode)
+       if (ap_mode != conn->mode) {
+               kfree(elems);
                goto again;
+       }
 
        mlme_link_id_dbg(sdata, link_id,
                         "connecting with %s mode, max bandwidth %d MHz\n",
@@ -5812,7 +5819,7 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
                 */
                if (control &
                    IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT)
-                       link_removal_timeout[link_id] = le16_to_cpu(*(__le16 *)pos);
+                       link_removal_timeout[link_id] = get_unaligned_le16(pos);
        }
 
        removed_links &= sdata->vif.valid_links;
@@ -5837,8 +5844,11 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
                        continue;
                }
 
-               link_delay = link_conf->beacon_int *
-                       link_removal_timeout[link_id];
+               if (link_removal_timeout[link_id] < 1)
+                       link_delay = 0;
+               else
+                       link_delay = link_conf->beacon_int *
+                               (link_removal_timeout[link_id] - 1);
 
                if (!delay)
                        delay = link_delay;
@@ -6193,7 +6203,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
                        link->u.mgd.dtim_period = elems->dtim_period;
                link->u.mgd.have_beacon = true;
                ifmgd->assoc_data->need_beacon = false;
-               if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
+               if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY) &&
+                   !ieee80211_is_s1g_beacon(hdr->frame_control)) {
                        link->conf->sync_tsf =
                                le64_to_cpu(mgmt->u.beacon.timestamp);
                        link->conf->sync_device_ts =
index 23404b275457a74868cd935653bc1a6192ec4cb5..4dc1def695486567b486fdada893557752f8df43 100644 (file)
@@ -877,6 +877,7 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_supported_band *sband;
+       u32 mask = ~0;
 
        rate_control_fill_sta_table(sta, info, dest, max_rates);
 
@@ -889,9 +890,12 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
        if (ieee80211_is_tx_data(skb))
                rate_control_apply_mask(sdata, sta, sband, dest, max_rates);
 
+       if (!(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX))
+               mask = sdata->rc_rateidx_mask[info->band];
+
        if (dest[0].idx < 0)
                __rate_control_send_low(&sdata->local->hw, sband, sta, info,
-                                       sdata->rc_rateidx_mask[info->band]);
+                                       mask);
 
        if (sta)
                rate_fixup_ratelist(vif, sband, info, dest, max_rates);
index c1f8501384056d3ebbb9ba7ddbd5c659c579d582..6e24864f9a40ba1b8d689263cf905cc0ff5d3d69 100644 (file)
@@ -2763,7 +2763,10 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
                               struct sk_buff *skb, int hdrlen)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-       struct ieee80211_mesh_fast_tx *entry = NULL;
+       struct ieee80211_mesh_fast_tx_key key = {
+               .type = MESH_FAST_TX_TYPE_FORWARDED
+       };
+       struct ieee80211_mesh_fast_tx *entry;
        struct ieee80211s_hdr *mesh_hdr;
        struct tid_ampdu_tx *tid_tx;
        struct sta_info *sta;
@@ -2772,9 +2775,13 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
 
        mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
        if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
-               entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
+               ether_addr_copy(key.addr, mesh_hdr->eaddr1);
        else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
-               entry = mesh_fast_tx_get(sdata, skb->data);
+               ether_addr_copy(key.addr, skb->data);
+       else
+               return false;
+
+       entry = mesh_fast_tx_get(sdata, &key);
        if (!entry)
                return false;
 
@@ -3780,6 +3787,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_PROTECTED_EHT:
+               if (len < offsetofend(typeof(*mgmt),
+                                     u.action.u.ttlm_req.action_code))
+                       break;
+
                switch (mgmt->u.action.u.ttlm_req.action_code) {
                case WLAN_PROTECTED_EHT_ACTION_TTLM_REQ:
                        if (sdata->vif.type != NL80211_IFTYPE_STATION)
index 0429e59ba387c931f42ae1e74255a7deb5ebf5d6..73850312580f7054c60550dd5a2486583ab48f0a 100644 (file)
@@ -648,6 +648,7 @@ static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata,
                                cpu_to_le16(IEEE80211_SN_TO_SEQ(sn));
                }
                IEEE80211_SKB_CB(skb)->flags |= tx_flags;
+               IEEE80211_SKB_CB(skb)->control.flags |= IEEE80211_TX_CTRL_SCAN_TX;
                ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
        }
 }
index 6bf223e6cd1a54aa432ef0bd41da48cd9316ffc5..cfd0a62d0152bd28f32fbb022cdbd094defefca4 100644 (file)
@@ -698,11 +698,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
        txrc.bss_conf = &tx->sdata->vif.bss_conf;
        txrc.skb = tx->skb;
        txrc.reported_rate.idx = -1;
-       txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
 
-       if (tx->sdata->rc_has_mcs_mask[info->band])
-               txrc.rate_idx_mcs_mask =
-                       tx->sdata->rc_rateidx_mcs_mask[info->band];
+       if (unlikely(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX)) {
+               txrc.rate_idx_mask = ~0;
+       } else {
+               txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
+
+               if (tx->sdata->rc_has_mcs_mask[info->band])
+                       txrc.rate_idx_mcs_mask =
+                               tx->sdata->rc_rateidx_mcs_mask[info->band];
+       }
 
        txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
                    tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
index a0921adc31a9ffe7db09d18e7ae54213a79a8fd7..1e689c71412716e04f417cdb62d9fb56b730a1ab 100644 (file)
@@ -126,7 +126,8 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
        if (sctph->source != cp->vport || payload_csum ||
            skb->ip_summed == CHECKSUM_PARTIAL) {
                sctph->source = cp->vport;
-               sctp_nat_csum(skb, sctph, sctphoff);
+               if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb))
+                       sctp_nat_csum(skb, sctph, sctphoff);
        } else {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        }
@@ -174,7 +175,8 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
            (skb->ip_summed == CHECKSUM_PARTIAL &&
             !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CRC))) {
                sctph->dest = cp->dport;
-               sctp_nat_csum(skb, sctph, sctphoff);
+               if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb))
+                       sctp_nat_csum(skb, sctph, sctphoff);
        } else if (skb->ip_summed != CHECKSUM_PARTIAL) {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        }
index 274b6f7e6bb57e4f270262ef923ebf8d7f1cf02c..d170758a1eb5d08929cc4cd8e8acd350e793524e 100644 (file)
@@ -338,7 +338,9 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,
                return;
 
        if (n > 1) {
-               nf_unregister_net_hook(ctx->net, &found->ops);
+               if (!(ctx->chain->table->flags & NFT_TABLE_F_DORMANT))
+                       nf_unregister_net_hook(ctx->net, &found->ops);
+
                list_del_rcu(&found->list);
                kfree_rcu(found, rcu);
                return;
index 74b63cdb59923a95dd03a9c2c540af702564873a..2928c142a2ddb3a0d9b1937fdb4ddd37322b3f45 100644 (file)
@@ -1593,9 +1593,9 @@ static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
        for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) {
                struct hlist_head *head = &info->limits[i];
                struct ovs_ct_limit *ct_limit;
+               struct hlist_node *next;
 
-               hlist_for_each_entry_rcu(ct_limit, head, hlist_node,
-                                        lockdep_ovsl_is_held())
+               hlist_for_each_entry_safe(ct_limit, next, head, hlist_node)
                        kfree_rcu(ct_limit, rcu);
        }
        kfree(info->limits);
index 762f424ff2d59c51ba176bc9dff81b499542fb5c..e5e47452308ab713032d58eedbff68bee9dc3a8d 100644 (file)
@@ -215,7 +215,7 @@ static inline struct sk_buff *tls_strp_msg(struct tls_sw_context_rx *ctx)
 
 static inline bool tls_strp_msg_ready(struct tls_sw_context_rx *ctx)
 {
-       return ctx->strp.msg_ready;
+       return READ_ONCE(ctx->strp.msg_ready);
 }
 
 static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx)
index ca1e0e198ceb452fac72dd48f22ea0a1dcddee6b..5df08d848b5c9c9cf36e21a78c7bc59f38a8f22b 100644 (file)
@@ -360,7 +360,7 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
        if (strp->stm.full_len && strp->stm.full_len == skb->len) {
                desc->count = 0;
 
-               strp->msg_ready = 1;
+               WRITE_ONCE(strp->msg_ready, 1);
                tls_rx_msg_ready(strp);
        }
 
@@ -528,7 +528,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
        if (!tls_strp_check_queue_ok(strp))
                return tls_strp_read_copy(strp, false);
 
-       strp->msg_ready = 1;
+       WRITE_ONCE(strp->msg_ready, 1);
        tls_rx_msg_ready(strp);
 
        return 0;
@@ -580,7 +580,7 @@ void tls_strp_msg_done(struct tls_strparser *strp)
        else
                tls_strp_flush_anchor_copy(strp);
 
-       strp->msg_ready = 0;
+       WRITE_ONCE(strp->msg_ready, 0);
        memset(&strp->stm, 0, sizeof(strp->stm));
 
        tls_strp_check_rcv(strp);
index 6433a414acf8624a1d98727f4e309b7c040710b9..0104be9d4704563791b1c1558fcbf166649fee25 100644 (file)
@@ -299,7 +299,7 @@ static void __unix_gc(struct work_struct *work)
                        __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
 
                        if (sk->sk_state == TCP_LISTEN) {
-                               unix_state_lock(sk);
+                               unix_state_lock_nested(sk, U_LOCK_GC_LISTENER);
                                unix_state_unlock(sk);
                        }
                }
index b4edba6b0b7ba0bf3200c7ce966a3e286a6fdf24..30ff9a47081348d1b14d1db520aeedf9c9ffdd09 100644 (file)
@@ -14030,6 +14030,8 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
 error:
        for (i = 0; i < new_coalesce.n_rules; i++) {
                tmp_rule = &new_coalesce.rules[i];
+               if (!tmp_rule)
+                       continue;
                for (j = 0; j < tmp_rule->n_patterns; j++)
                        kfree(tmp_rule->patterns[j].mask);
                kfree(tmp_rule->patterns);
index cbbf347c6b2e099802b135266ca7fae59bd467f9..df013c98b80dfb0e06a86a78415e51d79cd76693 100644 (file)
@@ -1758,7 +1758,7 @@ TRACE_EVENT(rdev_return_void_tx_rx,
 
 DECLARE_EVENT_CLASS(tx_rx_evt,
        TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
-       TP_ARGS(wiphy, rx, tx),
+       TP_ARGS(wiphy, tx, rx),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                __field(u32, tx)
@@ -1775,7 +1775,7 @@ DECLARE_EVENT_CLASS(tx_rx_evt,
 
 DEFINE_EVENT(tx_rx_evt, rdev_set_antenna,
        TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
-       TP_ARGS(wiphy, rx, tx)
+       TP_ARGS(wiphy, tx, rx)
 );
 
 DECLARE_EVENT_CLASS(wiphy_netdev_id_evt,
index 5fa7957f6e0f56646249c278b7434f300754df77..25810e18b0a73272f42ff3a8d9335ee79699b6a0 100644 (file)
@@ -182,6 +182,7 @@ class NlMsg:
             self.done = 1
             extack_off = 20
         elif self.nl_type == Netlink.NLMSG_DONE:
+            self.error = struct.unpack("i", self.raw[0:4])[0]
             self.done = 1
             extack_off = 4