Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
authorJakub Kicinski <kuba@kernel.org>
Fri, 10 Jun 2022 22:55:32 +0000 (15:55 -0700)
committerJakub Kicinski <kuba@kernel.org>
Fri, 10 Jun 2022 22:55:32 +0000 (15:55 -0700)
No conflicts.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
193 files changed:
MAINTAINERS
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_netlink.c
drivers/net/bonding/bond_options.c
drivers/net/dsa/microchip/ksz8.h
drivers/net/eql.c
drivers/net/ethernet/altera/altera_utils.h
drivers/net/ethernet/cadence/macb_ptp.c
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
drivers/net/ethernet/intel/ice/ice_gnss.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_virtchnl.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/netronome/nfp/nfpcore/crc32.h
drivers/net/ipvlan/ipvlan.h
drivers/net/ipvlan/ipvlan_core.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/macsec.c
drivers/net/macvlan.c
drivers/net/netconsole.c
drivers/net/team/team.c
drivers/net/usb/usbnet.c
drivers/net/vmxnet3/Makefile
drivers/net/vmxnet3/upt1_defs.h
drivers/net/vmxnet3/vmxnet3_defs.h
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_ethtool.c
drivers/net/vmxnet3/vmxnet3_int.h
drivers/net/vrf.c
drivers/net/vxlan/vxlan_core.c
drivers/net/wan/farsync.h
drivers/net/wireguard/receive.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/microchip/wilc1000/cfg80211.c
drivers/net/wireless/microchip/wilc1000/fw.h
drivers/net/wireless/microchip/wilc1000/hif.c
drivers/net/wireless/microchip/wilc1000/hif.h
drivers/net/wireless/microchip/wilc1000/netdev.c
drivers/net/wireless/microchip/wilc1000/netdev.h
drivers/net/wireless/microchip/wilc1000/spi.c
drivers/net/wireless/microchip/wilc1000/wlan.c
drivers/net/wireless/microchip/wilc1000/wlan.h
drivers/net/wireless/microchip/wilc1000/wlan_if.h
drivers/net/wireless/ray_cs.c
drivers/net/wireless/realtek/rtlwifi/debug.c
drivers/net/wireless/realtek/rtw88/debug.c
drivers/net/wireless/realtek/rtw88/main.c
drivers/net/wireless/realtek/rtw88/rtw8723d.c
drivers/net/wireless/realtek/rtw88/rtw8723d.h
drivers/net/wireless/realtek/rtw88/rtw8723de.c
drivers/net/wireless/realtek/rtw88/rtw8723de.h [deleted file]
drivers/net/wireless/realtek/rtw88/rtw8821c.c
drivers/net/wireless/realtek/rtw88/rtw8821c.h
drivers/net/wireless/realtek/rtw88/rtw8821ce.c
drivers/net/wireless/realtek/rtw88/rtw8821ce.h [deleted file]
drivers/net/wireless/realtek/rtw88/rtw8822b.c
drivers/net/wireless/realtek/rtw88/rtw8822b.h
drivers/net/wireless/realtek/rtw88/rtw8822be.c
drivers/net/wireless/realtek/rtw88/rtw8822be.h [deleted file]
drivers/net/wireless/realtek/rtw88/rtw8822c.c
drivers/net/wireless/realtek/rtw88/rtw8822c.h
drivers/net/wireless/realtek/rtw88/rtw8822ce.c
drivers/net/wireless/realtek/rtw88/rtw8822ce.h [deleted file]
drivers/net/wireless/realtek/rtw89/cam.c
drivers/net/wireless/realtek/rtw89/cam.h
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/debug.c
drivers/net/wireless/realtek/rtw89/debug.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/mac.c
drivers/net/wireless/realtek/rtw89/mac.h
drivers/net/wireless/realtek/rtw89/mac80211.c
drivers/net/wireless/realtek/rtw89/pci.c
drivers/net/wireless/realtek/rtw89/pci.h
drivers/net/wireless/realtek/rtw89/phy.c
drivers/net/wireless/realtek/rtw89/phy.h
drivers/net/wireless/realtek/rtw89/rtw8852c.c
drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h
drivers/net/wireless/realtek/rtw89/sar.c
drivers/net/wireless/silabs/wfx/fwio.c
drivers/net/wireless/st/cw1200/bh.c
drivers/net/wireless/virt_wifi.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netback/rx.c
drivers/ptp/ptp_ocp.c
include/linux/ieee80211.h
include/linux/if_macvlan.h
include/linux/if_team.h
include/linux/if_vlan.h
include/linux/netdevice.h
include/linux/skbuff.h
include/net/bond_options.h
include/net/dropreason.h [new file with mode: 0644]
include/net/ip_tunnels.h
include/net/mac80211.h
include/net/sock.h
include/net/xfrm.h
include/trace/events/skb.h
include/uapi/linux/nl80211.h
net/6lowpan/nhc.c
net/6lowpan/nhc.h
net/6lowpan/nhc_dest.c
net/6lowpan/nhc_fragment.c
net/6lowpan/nhc_ghc_ext_dest.c
net/6lowpan/nhc_ghc_ext_frag.c
net/6lowpan/nhc_ghc_ext_hop.c
net/6lowpan/nhc_ghc_ext_route.c
net/6lowpan/nhc_ghc_icmpv6.c
net/6lowpan/nhc_ghc_udp.c
net/6lowpan/nhc_hop.c
net/6lowpan/nhc_ipv6.c
net/6lowpan/nhc_mobility.c
net/6lowpan/nhc_routing.c
net/6lowpan/nhc_udp.c
net/8021q/vlan_core.c
net/8021q/vlan_dev.c
net/ax25/af_ax25.c
net/ax25/ax25_dev.c
net/bridge/br_if.c
net/bridge/br_netlink.c
net/bridge/br_vlan.c
net/core/.gitignore [new file with mode: 0644]
net/core/Makefile
net/core/dev.c
net/core/dev_ioctl.c
net/core/devlink.c
net/core/drop_monitor.c
net/core/dst.c
net/core/failover.c
net/core/link_watch.c
net/core/neighbour.c
net/core/net-sysfs.c
net/core/netpoll.c
net/core/pktgen.c
net/core/skbuff.c
net/core/sock.c
net/core/stream.c
net/dsa/slave.c
net/ethtool/ioctl.c
net/ethtool/netlink.c
net/ethtool/netlink.h
net/ipv4/af_inet.c
net/ipv4/devinet.c
net/ipv4/fib_semantics.c
net/ipv4/ipmr.c
net/ipv4/route.c
net/ipv4/xfrm4_policy.c
net/ipv6/addrconf.c
net/ipv6/addrconf_core.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/ip6mr.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/xfrm6_policy.c
net/llc/af_llc.c
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/main.c
net/mac80211/mesh_hwmp.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wpa.c
net/mac80211/wpa.h
net/openvswitch/vport-netdev.c
net/packet/af_packet.c
net/sched/act_mirred.c
net/sched/sch_api.c
net/sched/sch_generic.c
net/smc/smc_pnet.c
net/switchdev/switchdev.c
net/tipc/bearer.c
net/unix/af_unix.c
net/xfrm/xfrm_device.c

index 96158b3..05fcbea 100644 (file)
@@ -171,7 +171,6 @@ F:  drivers/scsi/53c700*
 
 6LOWPAN GENERIC (BTLE/IEEE 802.15.4)
 M:     Alexander Aring <alex.aring@gmail.com>
-M:     Jukka Rissanen <jukka.rissanen@linux.intel.com>
 L:     linux-bluetooth@vger.kernel.org
 L:     linux-wpan@vger.kernel.org
 S:     Maintained
index f85372a..3d42718 100644 (file)
@@ -6218,45 +6218,33 @@ int bond_create(struct net *net, const char *name)
 {
        struct net_device *bond_dev;
        struct bonding *bond;
-       struct alb_bond_info *bond_info;
-       int res;
+       int res = -ENOMEM;
 
        rtnl_lock();
 
        bond_dev = alloc_netdev_mq(sizeof(struct bonding),
                                   name ? name : "bond%d", NET_NAME_UNKNOWN,
                                   bond_setup, tx_queues);
-       if (!bond_dev) {
-               pr_err("%s: eek! can't alloc netdev!\n", name);
-               rtnl_unlock();
-               return -ENOMEM;
-       }
+       if (!bond_dev)
+               goto out;
 
-       /*
-        * Initialize rx_hashtbl_used_head to RLB_NULL_INDEX.
-        * It is set to 0 by default which is wrong.
-        */
        bond = netdev_priv(bond_dev);
-       bond_info = &(BOND_ALB_INFO(bond));
-       bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
-
        dev_net_set(bond_dev, net);
        bond_dev->rtnl_link_ops = &bond_link_ops;
 
        res = register_netdevice(bond_dev);
        if (res < 0) {
                free_netdev(bond_dev);
-               rtnl_unlock();
-
-               return res;
+               goto out;
        }
 
        netif_carrier_off(bond_dev);
 
        bond_work_init_all(bond);
 
+out:
        rtnl_unlock();
-       return 0;
+       return res;
 }
 
 static int __net_init bond_net_init(struct net *net)
index 6f404f9..5a6f444 100644 (file)
@@ -151,7 +151,8 @@ static int bond_slave_changelink(struct net_device *bond_dev,
                snprintf(queue_id_str, sizeof(queue_id_str), "%s:%u\n",
                         slave_dev->name, queue_id);
                bond_opt_initstr(&newval, queue_id_str);
-               err = __bond_opt_set(bond, BOND_OPT_QUEUE_ID, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_QUEUE_ID, &newval,
+                                    data[IFLA_BOND_SLAVE_QUEUE_ID], extack);
                if (err)
                        return err;
        }
@@ -175,7 +176,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int mode = nla_get_u8(data[IFLA_BOND_MODE]);
 
                bond_opt_initval(&newval, mode);
-               err = __bond_opt_set(bond, BOND_OPT_MODE, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_MODE, &newval,
+                                    data[IFLA_BOND_MODE], extack);
                if (err)
                        return err;
        }
@@ -192,7 +194,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        active_slave = slave_dev->name;
                }
                bond_opt_initstr(&newval, active_slave);
-               err = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval,
+                                    data[IFLA_BOND_ACTIVE_SLAVE], extack);
                if (err)
                        return err;
        }
@@ -200,7 +203,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);
 
                bond_opt_initval(&newval, miimon);
-               err = __bond_opt_set(bond, BOND_OPT_MIIMON, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_MIIMON, &newval,
+                                    data[IFLA_BOND_MIIMON], extack);
                if (err)
                        return err;
        }
@@ -208,7 +212,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int updelay = nla_get_u32(data[IFLA_BOND_UPDELAY]);
 
                bond_opt_initval(&newval, updelay);
-               err = __bond_opt_set(bond, BOND_OPT_UPDELAY, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_UPDELAY, &newval,
+                                    data[IFLA_BOND_UPDELAY], extack);
                if (err)
                        return err;
        }
@@ -216,7 +221,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int downdelay = nla_get_u32(data[IFLA_BOND_DOWNDELAY]);
 
                bond_opt_initval(&newval, downdelay);
-               err = __bond_opt_set(bond, BOND_OPT_DOWNDELAY, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_DOWNDELAY, &newval,
+                                    data[IFLA_BOND_DOWNDELAY], extack);
                if (err)
                        return err;
        }
@@ -224,7 +230,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int delay = nla_get_u32(data[IFLA_BOND_PEER_NOTIF_DELAY]);
 
                bond_opt_initval(&newval, delay);
-               err = __bond_opt_set(bond, BOND_OPT_PEER_NOTIF_DELAY, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_PEER_NOTIF_DELAY, &newval,
+                                    data[IFLA_BOND_PEER_NOTIF_DELAY], extack);
                if (err)
                        return err;
        }
@@ -232,7 +239,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);
 
                bond_opt_initval(&newval, use_carrier);
-               err = __bond_opt_set(bond, BOND_OPT_USE_CARRIER, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_USE_CARRIER, &newval,
+                                    data[IFLA_BOND_USE_CARRIER], extack);
                if (err)
                        return err;
        }
@@ -240,12 +248,14 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);
 
                if (arp_interval && miimon) {
-                       netdev_err(bond->dev, "ARP monitoring cannot be used with MII monitoring\n");
+                       NL_SET_ERR_MSG_ATTR(extack, data[IFLA_BOND_ARP_INTERVAL],
+                                           "ARP monitoring cannot be used with MII monitoring");
                        return -EINVAL;
                }
 
                bond_opt_initval(&newval, arp_interval);
-               err = __bond_opt_set(bond, BOND_OPT_ARP_INTERVAL, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_ARP_INTERVAL, &newval,
+                                    data[IFLA_BOND_ARP_INTERVAL], extack);
                if (err)
                        return err;
        }
@@ -264,7 +274,9 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
 
                        bond_opt_initval(&newval, (__force u64)target);
                        err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
-                                            &newval);
+                                            &newval,
+                                            data[IFLA_BOND_ARP_IP_TARGET],
+                                            extack);
                        if (err)
                                break;
                        i++;
@@ -292,7 +304,9 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
 
                        bond_opt_initextra(&newval, &addr6, sizeof(addr6));
                        err = __bond_opt_set(bond, BOND_OPT_NS_TARGETS,
-                                            &newval);
+                                            &newval,
+                                            data[IFLA_BOND_NS_IP6_TARGET],
+                                            extack);
                        if (err)
                                break;
                        i++;
@@ -307,12 +321,14 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]);
 
                if (arp_validate && miimon) {
-                       netdev_err(bond->dev, "ARP validating cannot be used with MII monitoring\n");
+                       NL_SET_ERR_MSG_ATTR(extack, data[IFLA_BOND_ARP_INTERVAL],
+                                           "ARP validating cannot be used with MII monitoring");
                        return -EINVAL;
                }
 
                bond_opt_initval(&newval, arp_validate);
-               err = __bond_opt_set(bond, BOND_OPT_ARP_VALIDATE, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_ARP_VALIDATE, &newval,
+                                    data[IFLA_BOND_ARP_VALIDATE], extack);
                if (err)
                        return err;
        }
@@ -321,7 +337,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u32(data[IFLA_BOND_ARP_ALL_TARGETS]);
 
                bond_opt_initval(&newval, arp_all_targets);
-               err = __bond_opt_set(bond, BOND_OPT_ARP_ALL_TARGETS, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_ARP_ALL_TARGETS, &newval,
+                                    data[IFLA_BOND_ARP_ALL_TARGETS], extack);
                if (err)
                        return err;
        }
@@ -335,7 +352,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        primary = dev->name;
 
                bond_opt_initstr(&newval, primary);
-               err = __bond_opt_set(bond, BOND_OPT_PRIMARY, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_PRIMARY, &newval,
+                                    data[IFLA_BOND_PRIMARY], extack);
                if (err)
                        return err;
        }
@@ -344,7 +362,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u8(data[IFLA_BOND_PRIMARY_RESELECT]);
 
                bond_opt_initval(&newval, primary_reselect);
-               err = __bond_opt_set(bond, BOND_OPT_PRIMARY_RESELECT, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_PRIMARY_RESELECT, &newval,
+                                    data[IFLA_BOND_PRIMARY_RESELECT], extack);
                if (err)
                        return err;
        }
@@ -353,7 +372,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u8(data[IFLA_BOND_FAIL_OVER_MAC]);
 
                bond_opt_initval(&newval, fail_over_mac);
-               err = __bond_opt_set(bond, BOND_OPT_FAIL_OVER_MAC, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_FAIL_OVER_MAC, &newval,
+                                    data[IFLA_BOND_FAIL_OVER_MAC], extack);
                if (err)
                        return err;
        }
@@ -362,7 +382,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u8(data[IFLA_BOND_XMIT_HASH_POLICY]);
 
                bond_opt_initval(&newval, xmit_hash_policy);
-               err = __bond_opt_set(bond, BOND_OPT_XMIT_HASH, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_XMIT_HASH, &newval,
+                                    data[IFLA_BOND_XMIT_HASH_POLICY], extack);
                if (err)
                        return err;
        }
@@ -371,7 +392,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u32(data[IFLA_BOND_RESEND_IGMP]);
 
                bond_opt_initval(&newval, resend_igmp);
-               err = __bond_opt_set(bond, BOND_OPT_RESEND_IGMP, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_RESEND_IGMP, &newval,
+                                    data[IFLA_BOND_RESEND_IGMP], extack);
                if (err)
                        return err;
        }
@@ -380,7 +402,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u8(data[IFLA_BOND_NUM_PEER_NOTIF]);
 
                bond_opt_initval(&newval, num_peer_notif);
-               err = __bond_opt_set(bond, BOND_OPT_NUM_PEER_NOTIF, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_NUM_PEER_NOTIF, &newval,
+                                    data[IFLA_BOND_NUM_PEER_NOTIF], extack);
                if (err)
                        return err;
        }
@@ -389,7 +412,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u8(data[IFLA_BOND_ALL_SLAVES_ACTIVE]);
 
                bond_opt_initval(&newval, all_slaves_active);
-               err = __bond_opt_set(bond, BOND_OPT_ALL_SLAVES_ACTIVE, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_ALL_SLAVES_ACTIVE, &newval,
+                                    data[IFLA_BOND_ALL_SLAVES_ACTIVE], extack);
                if (err)
                        return err;
        }
@@ -398,7 +422,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u32(data[IFLA_BOND_MIN_LINKS]);
 
                bond_opt_initval(&newval, min_links);
-               err = __bond_opt_set(bond, BOND_OPT_MINLINKS, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_MINLINKS, &newval,
+                                    data[IFLA_BOND_MIN_LINKS], extack);
                if (err)
                        return err;
        }
@@ -407,7 +432,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u32(data[IFLA_BOND_LP_INTERVAL]);
 
                bond_opt_initval(&newval, lp_interval);
-               err = __bond_opt_set(bond, BOND_OPT_LP_INTERVAL, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_LP_INTERVAL, &newval,
+                                    data[IFLA_BOND_LP_INTERVAL], extack);
                if (err)
                        return err;
        }
@@ -416,7 +442,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u32(data[IFLA_BOND_PACKETS_PER_SLAVE]);
 
                bond_opt_initval(&newval, packets_per_slave);
-               err = __bond_opt_set(bond, BOND_OPT_PACKETS_PER_SLAVE, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_PACKETS_PER_SLAVE, &newval,
+                                    data[IFLA_BOND_PACKETS_PER_SLAVE], extack);
                if (err)
                        return err;
        }
@@ -425,7 +452,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int lacp_active = nla_get_u8(data[IFLA_BOND_AD_LACP_ACTIVE]);
 
                bond_opt_initval(&newval, lacp_active);
-               err = __bond_opt_set(bond, BOND_OPT_LACP_ACTIVE, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_LACP_ACTIVE, &newval,
+                                    data[IFLA_BOND_AD_LACP_ACTIVE], extack);
                if (err)
                        return err;
        }
@@ -435,7 +463,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u8(data[IFLA_BOND_AD_LACP_RATE]);
 
                bond_opt_initval(&newval, lacp_rate);
-               err = __bond_opt_set(bond, BOND_OPT_LACP_RATE, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_LACP_RATE, &newval,
+                                    data[IFLA_BOND_AD_LACP_RATE], extack);
                if (err)
                        return err;
        }
@@ -444,7 +473,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u8(data[IFLA_BOND_AD_SELECT]);
 
                bond_opt_initval(&newval, ad_select);
-               err = __bond_opt_set(bond, BOND_OPT_AD_SELECT, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_AD_SELECT, &newval,
+                                    data[IFLA_BOND_AD_SELECT], extack);
                if (err)
                        return err;
        }
@@ -453,7 +483,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u16(data[IFLA_BOND_AD_ACTOR_SYS_PRIO]);
 
                bond_opt_initval(&newval, actor_sys_prio);
-               err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYS_PRIO, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYS_PRIO, &newval,
+                                    data[IFLA_BOND_AD_ACTOR_SYS_PRIO], extack);
                if (err)
                        return err;
        }
@@ -462,7 +493,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                        nla_get_u16(data[IFLA_BOND_AD_USER_PORT_KEY]);
 
                bond_opt_initval(&newval, port_key);
-               err = __bond_opt_set(bond, BOND_OPT_AD_USER_PORT_KEY, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_AD_USER_PORT_KEY, &newval,
+                                    data[IFLA_BOND_AD_USER_PORT_KEY], extack);
                if (err)
                        return err;
        }
@@ -472,7 +504,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
 
                bond_opt_initval(&newval,
                                 nla_get_u64(data[IFLA_BOND_AD_ACTOR_SYSTEM]));
-               err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYSTEM, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_AD_ACTOR_SYSTEM, &newval,
+                                    data[IFLA_BOND_AD_ACTOR_SYSTEM], extack);
                if (err)
                        return err;
        }
@@ -480,7 +513,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int dynamic_lb = nla_get_u8(data[IFLA_BOND_TLB_DYNAMIC_LB]);
 
                bond_opt_initval(&newval, dynamic_lb);
-               err = __bond_opt_set(bond, BOND_OPT_TLB_DYNAMIC_LB, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_TLB_DYNAMIC_LB, &newval,
+                                    data[IFLA_BOND_TLB_DYNAMIC_LB], extack);
                if (err)
                        return err;
        }
@@ -489,7 +523,8 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
                int missed_max = nla_get_u8(data[IFLA_BOND_MISSED_MAX]);
 
                bond_opt_initval(&newval, missed_max);
-               err = __bond_opt_set(bond, BOND_OPT_MISSED_MAX, &newval);
+               err = __bond_opt_set(bond, BOND_OPT_MISSED_MAX, &newval,
+                                    data[IFLA_BOND_MISSED_MAX], extack);
                if (err)
                        return err;
        }
index 1f8323a..96eef19 100644 (file)
@@ -632,27 +632,35 @@ static int bond_opt_check_deps(struct bonding *bond,
 }
 
 static void bond_opt_dep_print(struct bonding *bond,
-                              const struct bond_option *opt)
+                              const struct bond_option *opt,
+                              struct nlattr *bad_attr,
+                              struct netlink_ext_ack *extack)
 {
        const struct bond_opt_value *modeval;
        struct bond_params *params;
 
        params = &bond->params;
        modeval = bond_opt_get_val(BOND_OPT_MODE, params->mode);
-       if (test_bit(params->mode, &opt->unsuppmodes))
+       if (test_bit(params->mode, &opt->unsuppmodes)) {
                netdev_err(bond->dev, "option %s: mode dependency failed, not supported in mode %s(%llu)\n",
                           opt->name, modeval->string, modeval->value);
+               NL_SET_ERR_MSG_ATTR(extack, bad_attr,
+                                   "option not supported in mode");
+       }
 }
 
 static void bond_opt_error_interpret(struct bonding *bond,
                                     const struct bond_option *opt,
-                                    int error, const struct bond_opt_value *val)
+                                    int error, const struct bond_opt_value *val,
+                                    struct nlattr *bad_attr,
+                                    struct netlink_ext_ack *extack)
 {
        const struct bond_opt_value *minval, *maxval;
        char *p;
 
        switch (error) {
        case -EINVAL:
+               NL_SET_ERR_MSG_ATTR(extack, bad_attr, "invalid option value");
                if (val) {
                        if (val->string) {
                                /* sometimes RAWVAL opts may have new lines */
@@ -674,13 +682,17 @@ static void bond_opt_error_interpret(struct bonding *bond,
                           opt->name, minval ? minval->value : 0, maxval->value);
                break;
        case -EACCES:
-               bond_opt_dep_print(bond, opt);
+               bond_opt_dep_print(bond, opt, bad_attr, extack);
                break;
        case -ENOTEMPTY:
+               NL_SET_ERR_MSG_ATTR(extack, bad_attr,
+                                   "unable to set option because the bond device has slaves");
                netdev_err(bond->dev, "option %s: unable to set because the bond device has slaves\n",
                           opt->name);
                break;
        case -EBUSY:
+               NL_SET_ERR_MSG_ATTR(extack, bad_attr,
+                                   "unable to set option because the bond is up");
                netdev_err(bond->dev, "option %s: unable to set because the bond device is up\n",
                           opt->name);
                break;
@@ -691,6 +703,8 @@ static void bond_opt_error_interpret(struct bonding *bond,
                                *p = '\0';
                        netdev_err(bond->dev, "option %s: interface %s does not exist!\n",
                                   opt->name, val->string);
+                       NL_SET_ERR_MSG_ATTR(extack, bad_attr,
+                                           "interface does not exist");
                }
                break;
        default:
@@ -703,13 +717,17 @@ static void bond_opt_error_interpret(struct bonding *bond,
  * @bond: target bond device
  * @option: option to set
  * @val: value to set it to
+ * @bad_attr: netlink attribue that caused the error
+ * @extack: extended netlink error structure, used when an error message
+ *          needs to be returned to the caller via netlink
  *
  * This function is used to change the bond's option value, it can be
  * used for both enabling/changing an option and for disabling it. RTNL lock
  * must be obtained before calling this function.
  */
 int __bond_opt_set(struct bonding *bond,
-                  unsigned int option, struct bond_opt_value *val)
+                  unsigned int option, struct bond_opt_value *val,
+                  struct nlattr *bad_attr, struct netlink_ext_ack *extack)
 {
        const struct bond_opt_value *retval = NULL;
        const struct bond_option *opt;
@@ -731,7 +749,7 @@ int __bond_opt_set(struct bonding *bond,
        ret = opt->set(bond, retval);
 out:
        if (ret)
-               bond_opt_error_interpret(bond, opt, ret, val);
+               bond_opt_error_interpret(bond, opt, ret, val, bad_attr, extack);
 
        return ret;
 }
@@ -753,7 +771,7 @@ int __bond_opt_set_notify(struct bonding *bond,
 
        ASSERT_RTNL();
 
-       ret = __bond_opt_set(bond, option, val);
+       ret = __bond_opt_set(bond, option, val, NULL, NULL);
 
        if (!ret && (bond->dev->reg_state == NETREG_REGISTERED))
                call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev);
index 03da369..cae76f5 100644 (file)
@@ -7,7 +7,8 @@
 
 #ifndef __KSZ8XXX_H
 #define __KSZ8XXX_H
-#include <linux/kernel.h>
+
+#include <linux/types.h>
 
 enum ksz_regs {
        REG_IND_CTRL_0,
index 557ca8f..ca3e470 100644 (file)
@@ -225,7 +225,7 @@ static void eql_kill_one_slave(slave_queue_t *queue, slave_t *slave)
        list_del(&slave->list);
        queue->num_slaves--;
        slave->dev->flags &= ~IFF_SLAVE;
-       dev_put_track(slave->dev, &slave->dev_tracker);
+       netdev_put(slave->dev, &slave->dev_tracker);
        kfree(slave);
 }
 
@@ -399,7 +399,7 @@ static int __eql_insert_slave(slave_queue_t *queue, slave_t *slave)
                if (duplicate_slave)
                        eql_kill_one_slave(queue, duplicate_slave);
 
-               dev_hold_track(slave->dev, &slave->dev_tracker, GFP_ATOMIC);
+               netdev_hold(slave->dev, &slave->dev_tracker, GFP_ATOMIC);
                list_add(&slave->list, &queue->all_slaves);
                queue->num_slaves++;
                slave->dev->flags |= IFF_SLAVE;
index b7d772f..3c2e32f 100644 (file)
@@ -3,11 +3,12 @@
  * Copyright (C) 2014 Altera Corporation. All rights reserved
  */
 
-#include <linux/kernel.h>
-
 #ifndef __ALTERA_UTILS_H__
 #define __ALTERA_UTILS_H__
 
+#include <linux/compiler.h>
+#include <linux/types.h>
+
 void tse_set_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask);
 void tse_clear_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask);
 int tse_bit_is_set(void __iomem *ioaddr, size_t offs, u32 bit_mask);
index 9559c16..e6cb20a 100644 (file)
@@ -434,7 +434,7 @@ int gem_get_hwtst(struct net_device *dev, struct ifreq *rq)
                return 0;
 }
 
-static int gem_ptp_set_one_step_sync(struct macb *bp, u8 enable)
+static void gem_ptp_set_one_step_sync(struct macb *bp, u8 enable)
 {
        u32 reg_val;
 
@@ -444,8 +444,6 @@ static int gem_ptp_set_one_step_sync(struct macb *bp, u8 enable)
                macb_writel(bp, NCR, reg_val | MACB_BIT(OSSMODE));
        else
                macb_writel(bp, NCR, reg_val & ~MACB_BIT(OSSMODE));
-
-       return 0;
 }
 
 int gem_set_hwtst(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -468,8 +466,7 @@ int gem_set_hwtst(struct net_device *dev, struct ifreq *ifr, int cmd)
        case HWTSTAMP_TX_OFF:
                break;
        case HWTSTAMP_TX_ONESTEP_SYNC:
-               if (gem_ptp_set_one_step_sync(bp, 1) != 0)
-                       return -ERANGE;
+               gem_ptp_set_one_step_sync(bp, 1);
                tx_bd_control = TSTAMP_ALL_FRAMES;
                break;
        case HWTSTAMP_TX_ON:
index 18558a0..57f4ec4 100644 (file)
@@ -565,6 +565,7 @@ struct i40e_pf {
 #define I40E_FLAG_DISABLE_FW_LLDP              BIT(24)
 #define I40E_FLAG_RS_FEC                       BIT(25)
 #define I40E_FLAG_BASE_R_FEC                   BIT(26)
+#define I40E_FLAG_VF_VLAN_PRUNING              BIT(27)
 /* TOTAL_PORT_SHUTDOWN
  * Allows to physically disable the link on the NIC's port.
  * If enabled, (after link down request from the OS)
index 610f00c..c65e9e2 100644 (file)
@@ -457,6 +457,8 @@ static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = {
        I40E_PRIV_FLAG("disable-fw-lldp", I40E_FLAG_DISABLE_FW_LLDP, 0),
        I40E_PRIV_FLAG("rs-fec", I40E_FLAG_RS_FEC, 0),
        I40E_PRIV_FLAG("base-r-fec", I40E_FLAG_BASE_R_FEC, 0),
+       I40E_PRIV_FLAG("vf-vlan-pruning",
+                      I40E_FLAG_VF_VLAN_PRUNING, 0),
 };
 
 #define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gstrings_priv_flags)
@@ -5285,6 +5287,13 @@ flags_complete:
                return -EOPNOTSUPP;
        }
 
+       if ((changed_flags & I40E_FLAG_VF_VLAN_PRUNING) &&
+           pf->num_alloc_vfs) {
+               dev_warn(&pf->pdev->dev,
+                        "Changing vf-vlan-pruning flag while VF(s) are active is not supported\n");
+               return -EOPNOTSUPP;
+       }
+
        if ((changed_flags & new_flags &
             I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED) &&
            (new_flags & I40E_FLAG_MFP_ENABLED))
index 332a608..1599ac5 100644 (file)
@@ -1368,6 +1368,114 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
        return 0;
 }
 
+/**
+ * i40e_get_vf_new_vlan - Get new vlan id on a vf
+ * @vsi: the vsi to configure
+ * @new_mac: new mac filter to be added
+ * @f: existing mac filter, replaced with new_mac->f if new_mac is not NULL
+ * @vlan_filters: the number of active VLAN filters
+ * @trusted: flag if the VF is trusted
+ *
+ * Get new VLAN id based on current VLAN filters, trust, PVID
+ * and vf-vlan-prune-disable flag.
+ *
+ * Returns the value of the new vlan filter or
+ * the old value if no new filter is needed.
+ */
+static s16 i40e_get_vf_new_vlan(struct i40e_vsi *vsi,
+                               struct i40e_new_mac_filter *new_mac,
+                               struct i40e_mac_filter *f,
+                               int vlan_filters,
+                               bool trusted)
+{
+       s16 pvid = le16_to_cpu(vsi->info.pvid);
+       struct i40e_pf *pf = vsi->back;
+       bool is_any;
+
+       if (new_mac)
+               f = new_mac->f;
+
+       if (pvid && f->vlan != pvid)
+               return pvid;
+
+       is_any = (trusted ||
+                 !(pf->flags & I40E_FLAG_VF_VLAN_PRUNING));
+
+       if ((vlan_filters && f->vlan == I40E_VLAN_ANY) ||
+           (!is_any && !vlan_filters && f->vlan == I40E_VLAN_ANY) ||
+           (is_any && !vlan_filters && f->vlan == 0)) {
+               if (is_any)
+                       return I40E_VLAN_ANY;
+               else
+                       return 0;
+       }
+
+       return f->vlan;
+}
+
+/**
+ * i40e_correct_vf_mac_vlan_filters - Correct non-VLAN VF filters if necessary
+ * @vsi: the vsi to configure
+ * @tmp_add_list: list of filters ready to be added
+ * @tmp_del_list: list of filters ready to be deleted
+ * @vlan_filters: the number of active VLAN filters
+ * @trusted: flag if the VF is trusted
+ *
+ * Correct VF VLAN filters based on current VLAN filters, trust, PVID
+ * and vf-vlan-prune-disable flag.
+ *
+ * In case of memory allocation failure return -ENOMEM. Otherwise, return 0.
+ *
+ * This function is only expected to be called from within
+ * i40e_sync_vsi_filters.
+ *
+ * NOTE: This function expects to be called while under the
+ * mac_filter_hash_lock
+ */
+static int i40e_correct_vf_mac_vlan_filters(struct i40e_vsi *vsi,
+                                           struct hlist_head *tmp_add_list,
+                                           struct hlist_head *tmp_del_list,
+                                           int vlan_filters,
+                                           bool trusted)
+{
+       struct i40e_mac_filter *f, *add_head;
+       struct i40e_new_mac_filter *new_mac;
+       struct hlist_node *h;
+       int bkt, new_vlan;
+
+       hlist_for_each_entry(new_mac, tmp_add_list, hlist) {
+               new_mac->f->vlan = i40e_get_vf_new_vlan(vsi, new_mac, NULL,
+                                                       vlan_filters, trusted);
+       }
+
+       hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+               new_vlan = i40e_get_vf_new_vlan(vsi, NULL, f, vlan_filters,
+                                               trusted);
+               if (new_vlan != f->vlan) {
+                       add_head = i40e_add_filter(vsi, f->macaddr, new_vlan);
+                       if (!add_head)
+                               return -ENOMEM;
+                       /* Create a temporary i40e_new_mac_filter */
+                       new_mac = kzalloc(sizeof(*new_mac), GFP_ATOMIC);
+                       if (!new_mac)
+                               return -ENOMEM;
+                       new_mac->f = add_head;
+                       new_mac->state = add_head->state;
+
+                       /* Add the new filter to the tmp list */
+                       hlist_add_head(&new_mac->hlist, tmp_add_list);
+
+                       /* Put the original filter into the delete list */
+                       f->state = I40E_FILTER_REMOVE;
+                       hash_del(&f->hlist);
+                       hlist_add_head(&f->hlist, tmp_del_list);
+               }
+       }
+
+       vsi->has_vlan_filter = !!vlan_filters;
+       return 0;
+}
+
 /**
  * i40e_rm_default_mac_filter - Remove the default MAC filter set by NVM
  * @vsi: the PF Main VSI - inappropriate for any other VSI
@@ -2423,10 +2531,14 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                                vlan_filters++;
                }
 
-               retval = i40e_correct_mac_vlan_filters(vsi,
-                                                      &tmp_add_list,
-                                                      &tmp_del_list,
-                                                      vlan_filters);
+               if (vsi->type != I40E_VSI_SRIOV)
+                       retval = i40e_correct_mac_vlan_filters
+                               (vsi, &tmp_add_list, &tmp_del_list,
+                                vlan_filters);
+               else
+                       retval = i40e_correct_vf_mac_vlan_filters
+                               (vsi, &tmp_add_list, &tmp_del_list,
+                                vlan_filters, pf->vf[vsi->vf_id].trusted);
 
                hlist_for_each_entry(new, &tmp_add_list, hlist)
                        netdev_hw_addr_refcnt(new->f, vsi->netdev, 1);
@@ -2855,8 +2967,21 @@ int i40e_add_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)
        int bkt;
 
        hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
-               if (f->state == I40E_FILTER_REMOVE)
+               /* If we're asked to add a filter that has been marked for
+                * removal, it is safe to simply restore it to active state.
+                * __i40e_del_filter will have simply deleted any filters which
+                * were previously marked NEW or FAILED, so if it is currently
+                * marked REMOVE it must have previously been ACTIVE. Since we
+                * haven't yet run the sync filters task, just restore this
+                * filter to the ACTIVE state so that the sync task leaves it
+                * in place.
+                */
+               if (f->state == I40E_FILTER_REMOVE && f->vlan == vid) {
+                       f->state = I40E_FILTER_ACTIVE;
+                       continue;
+               } else if (f->state == I40E_FILTER_REMOVE) {
                        continue;
+               }
                add_f = i40e_add_filter(vsi, f->macaddr, vid);
                if (!add_f) {
                        dev_info(&vsi->back->pdev->dev,
index 2606e8f..9949469 100644 (file)
@@ -4349,6 +4349,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
                /* duplicate request, so just return success */
                goto error_pvid;
 
+       i40e_vlan_stripping_enable(vsi);
        i40e_vc_reset_vf(vf, true);
        /* During reset the VF got a new VSI, so refresh a pointer. */
        vsi = pf->vsi[vf->lan_vsi_idx];
@@ -4364,7 +4365,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
         * MAC addresses deleted.
         */
        if ((!(vlan_id || qos) ||
-           vlanprio != le16_to_cpu(vsi->info.pvid)) &&
+            vlanprio != le16_to_cpu(vsi->info.pvid)) &&
            vsi->info.pvid) {
                ret = i40e_add_vlan_all_mac(vsi, I40E_VLAN_ANY);
                if (ret) {
@@ -4727,6 +4728,11 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)
                goto out;
 
        vf->trusted = setting;
+
+       /* request PF to sync mac/vlan filters for the VF */
+       set_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state);
+       pf->vsi[vf->lan_vsi_idx]->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
+
        i40e_vc_reset_vf(vf, true);
        dev_info(&pf->pdev->dev, "VF %u is now %strusted\n",
                 vf_id, setting ? "" : "un");
index 49aed3e..fda1198 100644 (file)
@@ -146,7 +146,8 @@ struct iavf_mac_filter {
                u8 remove:1;        /* filter needs to be removed */
                u8 add:1;           /* filter needs to be added */
                u8 is_primary:1;    /* filter is a default VF MAC */
-               u8 padding:4;
+               u8 add_handled:1;   /* received response for filter add */
+               u8 padding:3;
        };
 };
 
@@ -248,6 +249,7 @@ struct iavf_adapter {
        struct work_struct adminq_task;
        struct delayed_work client_task;
        wait_queue_head_t down_waitqueue;
+       wait_queue_head_t vc_waitqueue;
        struct iavf_q_vector *q_vectors;
        struct list_head vlan_filter_list;
        struct list_head mac_filter_list;
@@ -292,6 +294,7 @@ struct iavf_adapter {
 #define IAVF_FLAG_QUEUES_DISABLED              BIT(17)
 #define IAVF_FLAG_SETUP_NETDEV_FEATURES                BIT(18)
 #define IAVF_FLAG_REINIT_MSIX_NEEDED           BIT(20)
+#define IAVF_FLAG_INITIAL_MAC_SET              BIT(23)
 /* duplicates for common code */
 #define IAVF_FLAG_DCB_ENABLED                  0
        /* flags for admin queue service task */
@@ -559,6 +562,8 @@ void iavf_enable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid);
 void iavf_disable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid);
 void iavf_enable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid);
 void iavf_disable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid);
+int iavf_replace_primary_mac(struct iavf_adapter *adapter,
+                            const u8 *new_mac);
 void
 iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
                               netdev_features_t prev_features,
index 7dfcf78..95772e1 100644 (file)
@@ -983,6 +983,7 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
 
                list_add_tail(&f->list, &adapter->mac_filter_list);
                f->add = true;
+               f->add_handled = false;
                f->is_new_mac = true;
                f->is_primary = false;
                adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
@@ -994,47 +995,132 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
 }
 
 /**
- * iavf_set_mac - NDO callback to set port mac address
- * @netdev: network interface device structure
- * @p: pointer to an address structure
+ * iavf_replace_primary_mac - Replace current primary address
+ * @adapter: board private structure
+ * @new_mac: new MAC address to be applied
  *
- * Returns 0 on success, negative on failure
+ * Replace current dev_addr and send request to PF for removal of previous
+ * primary MAC address filter and addition of new primary MAC filter.
+ * Return 0 for success, -ENOMEM for failure.
+ *
+ * Do not call this with mac_vlan_list_lock!
  **/
-static int iavf_set_mac(struct net_device *netdev, void *p)
+int iavf_replace_primary_mac(struct iavf_adapter *adapter,
+                            const u8 *new_mac)
 {
-       struct iavf_adapter *adapter = netdev_priv(netdev);
        struct iavf_hw *hw = &adapter->hw;
        struct iavf_mac_filter *f;
-       struct sockaddr *addr = p;
-
-       if (!is_valid_ether_addr(addr->sa_data))
-               return -EADDRNOTAVAIL;
-
-       if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
-               return 0;
 
        spin_lock_bh(&adapter->mac_vlan_list_lock);
 
+       list_for_each_entry(f, &adapter->mac_filter_list, list) {
+               f->is_primary = false;
+       }
+
        f = iavf_find_filter(adapter, hw->mac.addr);
        if (f) {
                f->remove = true;
-               f->is_primary = true;
                adapter->aq_required |= IAVF_FLAG_AQ_DEL_MAC_FILTER;
        }
 
-       f = iavf_add_filter(adapter, addr->sa_data);
+       f = iavf_add_filter(adapter, new_mac);
+
        if (f) {
+               /* Always send the request to add if changing primary MAC
+                * even if filter is already present on the list
+                */
                f->is_primary = true;
-               ether_addr_copy(hw->mac.addr, addr->sa_data);
+               f->add = true;
+               adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
+               ether_addr_copy(hw->mac.addr, new_mac);
        }
 
        spin_unlock_bh(&adapter->mac_vlan_list_lock);
 
        /* schedule the watchdog task to immediately process the request */
-       if (f)
+       if (f) {
                queue_work(iavf_wq, &adapter->watchdog_task.work);
+               return 0;
+       }
+       return -ENOMEM;
+}
+
+/**
+ * iavf_is_mac_set_handled - wait for a response to set MAC from PF
+ * @netdev: network interface device structure
+ * @macaddr: MAC address to set
+ *
+ * Returns true on success, false on failure
+ */
+static bool iavf_is_mac_set_handled(struct net_device *netdev,
+                                   const u8 *macaddr)
+{
+       struct iavf_adapter *adapter = netdev_priv(netdev);
+       struct iavf_mac_filter *f;
+       bool ret = false;
+
+       spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+       f = iavf_find_filter(adapter, macaddr);
+
+       if (!f || (!f->add && f->add_handled))
+               ret = true;
+
+       spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+       return ret;
+}
+
+/**
+ * iavf_set_mac - NDO callback to set port MAC address
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int iavf_set_mac(struct net_device *netdev, void *p)
+{
+       struct iavf_adapter *adapter = netdev_priv(netdev);
+       struct sockaddr *addr = p;
+       bool handle_mac = iavf_is_mac_set_handled(netdev, addr->sa_data);
+       int ret;
 
-       return (f == NULL) ? -ENOMEM : 0;
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       ret = iavf_replace_primary_mac(adapter, addr->sa_data);
+
+       if (ret)
+               return ret;
+
+       /* If this is an initial set MAC during VF spawn do not wait */
+       if (adapter->flags & IAVF_FLAG_INITIAL_MAC_SET) {
+               adapter->flags &= ~IAVF_FLAG_INITIAL_MAC_SET;
+               return 0;
+       }
+
+       if (handle_mac)
+               goto done;
+
+       ret = wait_event_interruptible_timeout(adapter->vc_waitqueue, false, msecs_to_jiffies(2500));
+
+       /* If ret < 0 then it means wait was interrupted.
+        * If ret == 0 then it means we got a timeout.
+        * else it means we got response for set MAC from PF,
+        * check if netdev MAC was updated to requested MAC,
+        * if yes then set MAC succeeded otherwise it failed return -EACCES
+        */
+       if (ret < 0)
+               return ret;
+
+       if (!ret)
+               return -EAGAIN;
+
+done:
+       if (!ether_addr_equal(netdev->dev_addr, addr->sa_data))
+               return -EACCES;
+
+       return 0;
 }
 
 /**
@@ -2451,6 +2537,8 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
                ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr);
        }
 
+       adapter->flags |= IAVF_FLAG_INITIAL_MAC_SET;
+
        adapter->tx_desc_count = IAVF_DEFAULT_TXD;
        adapter->rx_desc_count = IAVF_DEFAULT_RXD;
        err = iavf_init_interrupt_scheme(adapter);
@@ -4681,6 +4769,9 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* Setup the wait queue for indicating transition to down status */
        init_waitqueue_head(&adapter->down_waitqueue);
 
+       /* Setup the wait queue for indicating virtchannel events */
+       init_waitqueue_head(&adapter->vc_waitqueue);
+
        return 0;
 
 err_ioremap:
index 782450d..e2b4ba9 100644 (file)
@@ -598,6 +598,8 @@ static void iavf_mac_add_ok(struct iavf_adapter *adapter)
        spin_lock_bh(&adapter->mac_vlan_list_lock);
        list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
                f->is_new_mac = false;
+               if (!f->add && !f->add_handled)
+                       f->add_handled = true;
        }
        spin_unlock_bh(&adapter->mac_vlan_list_lock);
 }
@@ -618,6 +620,9 @@ static void iavf_mac_add_reject(struct iavf_adapter *adapter)
                if (f->remove && ether_addr_equal(f->macaddr, netdev->dev_addr))
                        f->remove = false;
 
+               if (!f->add && !f->add_handled)
+                       f->add_handled = true;
+
                if (f->is_new_mac) {
                        list_del(&f->list);
                        kfree(f);
@@ -1932,6 +1937,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                        iavf_mac_add_reject(adapter);
                        /* restore administratively set MAC address */
                        ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
+                       wake_up(&adapter->vc_waitqueue);
                        break;
                case VIRTCHNL_OP_DEL_VLAN:
                        dev_err(&adapter->pdev->dev, "Failed to delete VLAN filter, error %s\n",
@@ -2091,7 +2097,13 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                if (!v_retval)
                        iavf_mac_add_ok(adapter);
                if (!ether_addr_equal(netdev->dev_addr, adapter->hw.mac.addr))
-                       eth_hw_addr_set(netdev, adapter->hw.mac.addr);
+                       if (!ether_addr_equal(netdev->dev_addr,
+                                             adapter->hw.mac.addr)) {
+                               netif_addr_lock_bh(netdev);
+                               eth_hw_addr_set(netdev, adapter->hw.mac.addr);
+                               netif_addr_unlock_bh(netdev);
+                       }
+               wake_up(&adapter->vc_waitqueue);
                break;
        case VIRTCHNL_OP_GET_STATS: {
                struct iavf_eth_stats *stats =
@@ -2121,10 +2133,11 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                        /* restore current mac address */
                        ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
                } else {
+                       netif_addr_lock_bh(netdev);
                        /* refresh current mac address if changed */
-                       eth_hw_addr_set(netdev, adapter->hw.mac.addr);
                        ether_addr_copy(netdev->perm_addr,
                                        adapter->hw.mac.addr);
+                       netif_addr_unlock_bh(netdev);
                }
                spin_lock_bh(&adapter->mac_vlan_list_lock);
                iavf_add_filter(adapter, adapter->hw.mac.addr);
@@ -2160,6 +2173,10 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                }
                fallthrough;
        case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS: {
+               struct iavf_mac_filter *f;
+               bool was_mac_changed;
+               u64 aq_required = 0;
+
                if (v_opcode == VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS)
                        memcpy(&adapter->vlan_v2_caps, msg,
                               min_t(u16, msglen,
@@ -2167,6 +2184,46 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
 
                iavf_process_config(adapter);
                adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
+               was_mac_changed = !ether_addr_equal(netdev->dev_addr,
+                                                   adapter->hw.mac.addr);
+
+               spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+               /* re-add all MAC filters */
+               list_for_each_entry(f, &adapter->mac_filter_list, list) {
+                       if (was_mac_changed &&
+                           ether_addr_equal(netdev->dev_addr, f->macaddr))
+                               ether_addr_copy(f->macaddr,
+                                               adapter->hw.mac.addr);
+
+                       f->is_new_mac = true;
+                       f->add = true;
+                       f->add_handled = false;
+                       f->remove = false;
+               }
+
+               /* re-add all VLAN filters */
+               if (VLAN_FILTERING_ALLOWED(adapter)) {
+                       struct iavf_vlan_filter *vlf;
+
+                       if (!list_empty(&adapter->vlan_filter_list)) {
+                               list_for_each_entry(vlf,
+                                                   &adapter->vlan_filter_list,
+                                                   list)
+                                       vlf->add = true;
+
+                               aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;
+                       }
+               }
+
+               spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+               netif_addr_lock_bh(netdev);
+               eth_hw_addr_set(netdev, adapter->hw.mac.addr);
+               netif_addr_unlock_bh(netdev);
+
+               adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER |
+                       aq_required;
                }
                break;
        case VIRTCHNL_OP_ENABLE_QUEUES:
index 5d10c4f..ead6d50 100644 (file)
@@ -852,7 +852,7 @@ ice_create_init_fdir_rule(struct ice_pf *pf, enum ice_fltr_ptype flow)
        if (!seg)
                return -ENOMEM;
 
-       tun_seg = devm_kcalloc(dev, sizeof(*seg), ICE_FD_HW_SEG_MAX,
+       tun_seg = devm_kcalloc(dev, ICE_FD_HW_SEG_MAX, sizeof(*tun_seg),
                               GFP_KERNEL);
        if (!tun_seg) {
                devm_kfree(dev, seg);
@@ -1214,7 +1214,7 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
        if (!seg)
                return -ENOMEM;
 
-       tun_seg = devm_kcalloc(dev, sizeof(*seg), ICE_FD_HW_SEG_MAX,
+       tun_seg = devm_kcalloc(dev, ICE_FD_HW_SEG_MAX, sizeof(*tun_seg),
                               GFP_KERNEL);
        if (!tun_seg) {
                devm_kfree(dev, seg);
index 57586a2..c6d755f 100644 (file)
@@ -17,13 +17,13 @@ static void ice_gnss_read(struct kthread_work *work)
        struct gnss_serial *gnss = container_of(work, struct gnss_serial,
                                                read_work.work);
        struct ice_aqc_link_topo_addr link_topo;
-       u8 i2c_params, bytes_read;
+       unsigned int i, bytes_read, data_len;
        struct tty_port *port;
        struct ice_pf *pf;
        struct ice_hw *hw;
        __be16 data_len_b;
        char *buf = NULL;
-       u16 i, data_len;
+       u8 i2c_params;
        int err = 0;
 
        pf = gnss->back;
@@ -65,7 +65,7 @@ static void ice_gnss_read(struct kthread_work *work)
                mdelay(10);
        }
 
-       data_len = min(data_len, (u16)PAGE_SIZE);
+       data_len = min_t(typeof(data_len), data_len, PAGE_SIZE);
        data_len = tty_buffer_request_room(port, data_len);
        if (!data_len) {
                err = -ENOMEM;
@@ -74,9 +74,10 @@ static void ice_gnss_read(struct kthread_work *work)
 
        /* Read received data */
        for (i = 0; i < data_len; i += bytes_read) {
-               u16 bytes_left = data_len - i;
+               unsigned int bytes_left = data_len - i;
 
-               bytes_read = min_t(typeof(bytes_left), bytes_left, ICE_MAX_I2C_DATA_SIZE);
+               bytes_read = min_t(typeof(bytes_left), bytes_left,
+                                  ICE_MAX_I2C_DATA_SIZE);
 
                err = ice_aq_read_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
                                      cpu_to_le16(ICE_GNSS_UBX_EMPTY_DATA),
index 454e01a..5a1e8b9 100644 (file)
@@ -887,6 +887,9 @@ static void ice_set_dflt_vsi_ctx(struct ice_hw *hw, struct ice_vsi_ctx *ctxt)
                        (ICE_AQ_VSI_OUTER_TAG_VLAN_8100 <<
                         ICE_AQ_VSI_OUTER_TAG_TYPE_S) &
                        ICE_AQ_VSI_OUTER_TAG_TYPE_M;
+               ctxt->info.outer_vlan_flags |=
+                       FIELD_PREP(ICE_AQ_VSI_OUTER_VLAN_EMODE_M,
+                                  ICE_AQ_VSI_OUTER_VLAN_EMODE_NOTHING);
        }
        /* Have 1:1 UP mapping for both ingress/egress tables */
        table |= ICE_UP_TABLE_TRANSLATE(0, 0);
index 1d9b84c..99cb382 100644 (file)
@@ -359,6 +359,54 @@ static u16 ice_vc_get_max_frame_size(struct ice_vf *vf)
        return max_frame_size;
 }
 
+/**
+ * ice_vc_get_vlan_caps
+ * @hw: pointer to the hw
+ * @vf: pointer to the VF info
+ * @vsi: pointer to the VSI
+ * @driver_caps: current driver caps
+ *
+ * Return 0 if there is no VLAN caps supported, or VLAN caps value
+ */
+static u32
+ice_vc_get_vlan_caps(struct ice_hw *hw, struct ice_vf *vf, struct ice_vsi *vsi,
+                    u32 driver_caps)
+{
+       if (ice_is_eswitch_mode_switchdev(vf->pf))
+               /* In switchdev setting VLAN from VF isn't supported */
+               return 0;
+
+       if (driver_caps & VIRTCHNL_VF_OFFLOAD_VLAN_V2) {
+               /* VLAN offloads based on current device configuration */
+               return VIRTCHNL_VF_OFFLOAD_VLAN_V2;
+       } else if (driver_caps & VIRTCHNL_VF_OFFLOAD_VLAN) {
+               /* allow VF to negotiate VIRTCHNL_VF_OFFLOAD explicitly for
+                * these two conditions, which amounts to guest VLAN filtering
+                * and offloads being based on the inner VLAN or the
+                * inner/single VLAN respectively and don't allow VF to
+                * negotiate VIRTCHNL_VF_OFFLOAD in any other cases
+                */
+               if (ice_is_dvm_ena(hw) && ice_vf_is_port_vlan_ena(vf)) {
+                       return VIRTCHNL_VF_OFFLOAD_VLAN;
+               } else if (!ice_is_dvm_ena(hw) &&
+                          !ice_vf_is_port_vlan_ena(vf)) {
+                       /* configure backward compatible support for VFs that
+                        * only support VIRTCHNL_VF_OFFLOAD_VLAN, the PF is
+                        * configured in SVM, and no port VLAN is configured
+                        */
+                       ice_vf_vsi_cfg_svm_legacy_vlan_mode(vsi);
+                       return VIRTCHNL_VF_OFFLOAD_VLAN;
+               } else if (ice_is_dvm_ena(hw)) {
+                       /* configure software offloaded VLAN support when DVM
+                        * is enabled, but no port VLAN is enabled
+                        */
+                       ice_vf_vsi_cfg_dvm_legacy_vlan_mode(vsi);
+               }
+       }
+
+       return 0;
+}
+
 /**
  * ice_vc_get_vf_res_msg
  * @vf: pointer to the VF info
@@ -402,33 +450,8 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
                goto err;
        }
 
-       if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_VLAN_V2) {
-               /* VLAN offloads based on current device configuration */
-               vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_VLAN_V2;
-       } else if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_VLAN) {
-               /* allow VF to negotiate VIRTCHNL_VF_OFFLOAD explicitly for
-                * these two conditions, which amounts to guest VLAN filtering
-                * and offloads being based on the inner VLAN or the
-                * inner/single VLAN respectively and don't allow VF to
-                * negotiate VIRTCHNL_VF_OFFLOAD in any other cases
-                */
-               if (ice_is_dvm_ena(hw) && ice_vf_is_port_vlan_ena(vf)) {
-                       vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_VLAN;
-               } else if (!ice_is_dvm_ena(hw) &&
-                          !ice_vf_is_port_vlan_ena(vf)) {
-                       vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_VLAN;
-                       /* configure backward compatible support for VFs that
-                        * only support VIRTCHNL_VF_OFFLOAD_VLAN, the PF is
-                        * configured in SVM, and no port VLAN is configured
-                        */
-                       ice_vf_vsi_cfg_svm_legacy_vlan_mode(vsi);
-               } else if (ice_is_dvm_ena(hw)) {
-                       /* configure software offloaded VLAN support when DVM
-                        * is enabled, but no port VLAN is enabled
-                        */
-                       ice_vf_vsi_cfg_dvm_legacy_vlan_mode(vsi);
-               }
-       }
+       vfres->vf_cap_flags |= ice_vc_get_vlan_caps(hw, vf, vsi,
+                                                   vf->driver_caps);
 
        if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
                vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_PF;
@@ -3529,42 +3552,6 @@ ice_vc_repr_del_mac(struct ice_vf __always_unused *vf, u8 __always_unused *msg)
                                     VIRTCHNL_STATUS_SUCCESS, NULL, 0);
 }
 
-static int ice_vc_repr_add_vlan(struct ice_vf *vf, u8 __always_unused *msg)
-{
-       dev_dbg(ice_pf_to_dev(vf->pf),
-               "Can't add VLAN in switchdev mode for VF %d\n", vf->vf_id);
-       return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_VLAN,
-                                    VIRTCHNL_STATUS_SUCCESS, NULL, 0);
-}
-
-static int ice_vc_repr_del_vlan(struct ice_vf *vf, u8 __always_unused *msg)
-{
-       dev_dbg(ice_pf_to_dev(vf->pf),
-               "Can't delete VLAN in switchdev mode for VF %d\n", vf->vf_id);
-       return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_VLAN,
-                                    VIRTCHNL_STATUS_SUCCESS, NULL, 0);
-}
-
-static int ice_vc_repr_ena_vlan_stripping(struct ice_vf *vf)
-{
-       dev_dbg(ice_pf_to_dev(vf->pf),
-               "Can't enable VLAN stripping in switchdev mode for VF %d\n",
-               vf->vf_id);
-       return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
-                                    VIRTCHNL_STATUS_ERR_NOT_SUPPORTED,
-                                    NULL, 0);
-}
-
-static int ice_vc_repr_dis_vlan_stripping(struct ice_vf *vf)
-{
-       dev_dbg(ice_pf_to_dev(vf->pf),
-               "Can't disable VLAN stripping in switchdev mode for VF %d\n",
-               vf->vf_id);
-       return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
-                                    VIRTCHNL_STATUS_ERR_NOT_SUPPORTED,
-                                    NULL, 0);
-}
-
 static int
 ice_vc_repr_cfg_promiscuous_mode(struct ice_vf *vf, u8 __always_unused *msg)
 {
@@ -3591,10 +3578,10 @@ static const struct ice_virtchnl_ops ice_virtchnl_repr_ops = {
        .config_rss_lut = ice_vc_config_rss_lut,
        .get_stats_msg = ice_vc_get_stats_msg,
        .cfg_promiscuous_mode_msg = ice_vc_repr_cfg_promiscuous_mode,
-       .add_vlan_msg = ice_vc_repr_add_vlan,
-       .remove_vlan_msg = ice_vc_repr_del_vlan,
-       .ena_vlan_stripping = ice_vc_repr_ena_vlan_stripping,
-       .dis_vlan_stripping = ice_vc_repr_dis_vlan_stripping,
+       .add_vlan_msg = ice_vc_add_vlan_msg,
+       .remove_vlan_msg = ice_vc_remove_vlan_msg,
+       .ena_vlan_stripping = ice_vc_ena_vlan_stripping,
+       .dis_vlan_stripping = ice_vc_dis_vlan_stripping,
        .handle_rss_cfg_msg = ice_vc_handle_rss_cfg,
        .add_fdir_fltr_msg = ice_vc_add_fdir_fltr,
        .del_fdir_fltr_msg = ice_vc_del_fdir_fltr,
index 59c9a10..6beb3d4 100644 (file)
@@ -1444,8 +1444,8 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
        int done = 0, bytes = 0;
 
        while (done < budget) {
+               unsigned int pktlen, *rxdcsum;
                struct net_device *netdev;
-               unsigned int pktlen;
                dma_addr_t dma_addr;
                u32 hash, reason;
                int mac = 0;
@@ -1512,7 +1512,13 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
                pktlen = RX_DMA_GET_PLEN0(trxd.rxd2);
                skb->dev = netdev;
                skb_put(skb, pktlen);
-               if (trxd.rxd4 & eth->soc->txrx.rx_dma_l4_valid)
+
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+                       rxdcsum = &trxd.rxd3;
+               else
+                       rxdcsum = &trxd.rxd4;
+
+               if (*rxdcsum & eth->soc->txrx.rx_dma_l4_valid)
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                else
                        skb_checksum_none_assert(skb);
@@ -3761,6 +3767,7 @@ static const struct mtk_soc_data mt7986_data = {
                .txd_size = sizeof(struct mtk_tx_dma_v2),
                .rxd_size = sizeof(struct mtk_rx_dma_v2),
                .rx_irq_done_mask = MTK_RX_DONE_INT_V2,
+               .rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
                .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
                .dma_len_offset = 8,
        },
index afab6f0..6ad43c7 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef NFP_CRC32_H
 #define NFP_CRC32_H
 
-#include <linux/kernel.h>
 #include <linux/crc32.h>
 
 /**
index 3837c89..de94921 100644 (file)
@@ -47,11 +47,11 @@ typedef enum {
 } ipvl_hdr_type;
 
 struct ipvl_pcpu_stats {
-       u64                     rx_pkts;
-       u64                     rx_bytes;
-       u64                     rx_mcast;
-       u64                     tx_pkts;
-       u64                     tx_bytes;
+       u64_stats_t             rx_pkts;
+       u64_stats_t             rx_bytes;
+       u64_stats_t             rx_mcast;
+       u64_stats_t             tx_pkts;
+       u64_stats_t             tx_bytes;
        struct u64_stats_sync   syncp;
        u32                     rx_errs;
        u32                     tx_drps;
index 6ffb274..dfeb5b3 100644 (file)
@@ -19,10 +19,10 @@ void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
 
                pcptr = this_cpu_ptr(ipvlan->pcpu_stats);
                u64_stats_update_begin(&pcptr->syncp);
-               pcptr->rx_pkts++;
-               pcptr->rx_bytes += len;
+               u64_stats_inc(&pcptr->rx_pkts);
+               u64_stats_add(&pcptr->rx_bytes, len);
                if (mcast)
-                       pcptr->rx_mcast++;
+                       u64_stats_inc(&pcptr->rx_mcast);
                u64_stats_update_end(&pcptr->syncp);
        } else {
                this_cpu_inc(ipvlan->pcpu_stats->rx_errs);
index aa28a29..49ba8a5 100644 (file)
@@ -224,8 +224,8 @@ static netdev_tx_t ipvlan_start_xmit(struct sk_buff *skb,
                pcptr = this_cpu_ptr(ipvlan->pcpu_stats);
 
                u64_stats_update_begin(&pcptr->syncp);
-               pcptr->tx_pkts++;
-               pcptr->tx_bytes += skblen;
+               u64_stats_inc(&pcptr->tx_pkts);
+               u64_stats_add(&pcptr->tx_bytes, skblen);
                u64_stats_update_end(&pcptr->syncp);
        } else {
                this_cpu_inc(ipvlan->pcpu_stats->tx_drps);
@@ -300,11 +300,11 @@ static void ipvlan_get_stats64(struct net_device *dev,
                        pcptr = per_cpu_ptr(ipvlan->pcpu_stats, idx);
                        do {
                                strt= u64_stats_fetch_begin_irq(&pcptr->syncp);
-                               rx_pkts = pcptr->rx_pkts;
-                               rx_bytes = pcptr->rx_bytes;
-                               rx_mcast = pcptr->rx_mcast;
-                               tx_pkts = pcptr->tx_pkts;
-                               tx_bytes = pcptr->tx_bytes;
+                               rx_pkts = u64_stats_read(&pcptr->rx_pkts);
+                               rx_bytes = u64_stats_read(&pcptr->rx_bytes);
+                               rx_mcast = u64_stats_read(&pcptr->rx_mcast);
+                               tx_pkts = u64_stats_read(&pcptr->tx_pkts);
+                               tx_bytes = u64_stats_read(&pcptr->tx_bytes);
                        } while (u64_stats_fetch_retry_irq(&pcptr->syncp,
                                                           strt));
 
@@ -315,8 +315,8 @@ static void ipvlan_get_stats64(struct net_device *dev,
                        s->tx_bytes += tx_bytes;
 
                        /* u32 values are updated without syncp protection. */
-                       rx_errs += pcptr->rx_errs;
-                       tx_drps += pcptr->tx_drps;
+                       rx_errs += READ_ONCE(pcptr->rx_errs);
+                       tx_drps += READ_ONCE(pcptr->tx_drps);
                }
                s->rx_errors = rx_errs;
                s->rx_dropped = rx_errs;
index 817577e..c881e1b 100644 (file)
@@ -523,8 +523,8 @@ static void count_tx(struct net_device *dev, int ret, int len)
                struct pcpu_sw_netstats *stats = this_cpu_ptr(dev->tstats);
 
                u64_stats_update_begin(&stats->syncp);
-               stats->tx_packets++;
-               stats->tx_bytes += len;
+               u64_stats_inc(&stats->tx_packets);
+               u64_stats_add(&stats->tx_bytes, len);
                u64_stats_update_end(&stats->syncp);
        }
 }
@@ -825,8 +825,8 @@ static void count_rx(struct net_device *dev, int len)
        struct pcpu_sw_netstats *stats = this_cpu_ptr(dev->tstats);
 
        u64_stats_update_begin(&stats->syncp);
-       stats->rx_packets++;
-       stats->rx_bytes += len;
+       u64_stats_inc(&stats->rx_packets);
+       u64_stats_add(&stats->rx_bytes, len);
        u64_stats_update_end(&stats->syncp);
 }
 
@@ -3462,7 +3462,7 @@ static int macsec_dev_init(struct net_device *dev)
                memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
 
        /* Get macsec's reference to real_dev */
-       dev_hold_track(real_dev, &macsec->dev_tracker, GFP_KERNEL);
+       netdev_hold(real_dev, &macsec->dev_tracker, GFP_KERNEL);
 
        return 0;
 }
@@ -3710,7 +3710,7 @@ static void macsec_free_netdev(struct net_device *dev)
        free_percpu(macsec->secy.tx_sc.stats);
 
        /* Get rid of the macsec's reference to real_dev */
-       dev_put_track(macsec->real_dev, &macsec->dev_tracker);
+       netdev_put(macsec->real_dev, &macsec->dev_tracker);
 }
 
 static void macsec_setup(struct net_device *dev)
index eff75be..1080d6e 100644 (file)
@@ -575,8 +575,8 @@ static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
 
                pcpu_stats = this_cpu_ptr(vlan->pcpu_stats);
                u64_stats_update_begin(&pcpu_stats->syncp);
-               pcpu_stats->tx_packets++;
-               pcpu_stats->tx_bytes += len;
+               u64_stats_inc(&pcpu_stats->tx_packets);
+               u64_stats_add(&pcpu_stats->tx_bytes, len);
                u64_stats_update_end(&pcpu_stats->syncp);
        } else {
                this_cpu_inc(vlan->pcpu_stats->tx_dropped);
@@ -915,7 +915,7 @@ static int macvlan_init(struct net_device *dev)
        port->count += 1;
 
        /* Get macvlan's reference to lowerdev */
-       dev_hold_track(lowerdev, &vlan->dev_tracker, GFP_KERNEL);
+       netdev_hold(lowerdev, &vlan->dev_tracker, GFP_KERNEL);
 
        return 0;
 }
@@ -949,11 +949,11 @@ static void macvlan_dev_get_stats64(struct net_device *dev,
                        p = per_cpu_ptr(vlan->pcpu_stats, i);
                        do {
                                start = u64_stats_fetch_begin_irq(&p->syncp);
-                               rx_packets      = p->rx_packets;
-                               rx_bytes        = p->rx_bytes;
-                               rx_multicast    = p->rx_multicast;
-                               tx_packets      = p->tx_packets;
-                               tx_bytes        = p->tx_bytes;
+                               rx_packets      = u64_stats_read(&p->rx_packets);
+                               rx_bytes        = u64_stats_read(&p->rx_bytes);
+                               rx_multicast    = u64_stats_read(&p->rx_multicast);
+                               tx_packets      = u64_stats_read(&p->tx_packets);
+                               tx_bytes        = u64_stats_read(&p->tx_bytes);
                        } while (u64_stats_fetch_retry_irq(&p->syncp, start));
 
                        stats->rx_packets       += rx_packets;
@@ -964,8 +964,8 @@ static void macvlan_dev_get_stats64(struct net_device *dev,
                        /* rx_errors & tx_dropped are u32, updated
                         * without syncp protection.
                         */
-                       rx_errors       += p->rx_errors;
-                       tx_dropped      += p->tx_dropped;
+                       rx_errors       += READ_ONCE(p->rx_errors);
+                       tx_dropped      += READ_ONCE(p->tx_dropped);
                }
                stats->rx_errors        = rx_errors;
                stats->rx_dropped       = rx_errors;
@@ -1185,7 +1185,7 @@ static void macvlan_dev_free(struct net_device *dev)
        struct macvlan_dev *vlan = netdev_priv(dev);
 
        /* Get rid of the macvlan's reference to lowerdev */
-       dev_put_track(vlan->lowerdev, &vlan->dev_tracker);
+       netdev_put(vlan->lowerdev, &vlan->dev_tracker);
 }
 
 void macvlan_common_setup(struct net_device *dev)
index ab8cd55..ddac61d 100644 (file)
@@ -721,7 +721,7 @@ restart:
                                __netpoll_cleanup(&nt->np);
 
                                spin_lock_irqsave(&target_list_lock, flags);
-                               dev_put_track(nt->np.dev, &nt->np.dev_tracker);
+                               netdev_put(nt->np.dev, &nt->np.dev_tracker);
                                nt->np.dev = NULL;
                                nt->enabled = false;
                                stopped = true;
index b07dde6..aac133a 100644 (file)
@@ -749,10 +749,10 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb)
 
                pcpu_stats = this_cpu_ptr(team->pcpu_stats);
                u64_stats_update_begin(&pcpu_stats->syncp);
-               pcpu_stats->rx_packets++;
-               pcpu_stats->rx_bytes += skb->len;
+               u64_stats_inc(&pcpu_stats->rx_packets);
+               u64_stats_add(&pcpu_stats->rx_bytes, skb->len);
                if (skb->pkt_type == PACKET_MULTICAST)
-                       pcpu_stats->rx_multicast++;
+                       u64_stats_inc(&pcpu_stats->rx_multicast);
                u64_stats_update_end(&pcpu_stats->syncp);
 
                skb->dev = team->dev;
@@ -1720,8 +1720,8 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
 
                pcpu_stats = this_cpu_ptr(team->pcpu_stats);
                u64_stats_update_begin(&pcpu_stats->syncp);
-               pcpu_stats->tx_packets++;
-               pcpu_stats->tx_bytes += len;
+               u64_stats_inc(&pcpu_stats->tx_packets);
+               u64_stats_add(&pcpu_stats->tx_bytes, len);
                u64_stats_update_end(&pcpu_stats->syncp);
        } else {
                this_cpu_inc(team->pcpu_stats->tx_dropped);
@@ -1854,11 +1854,11 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
                p = per_cpu_ptr(team->pcpu_stats, i);
                do {
                        start = u64_stats_fetch_begin_irq(&p->syncp);
-                       rx_packets      = p->rx_packets;
-                       rx_bytes        = p->rx_bytes;
-                       rx_multicast    = p->rx_multicast;
-                       tx_packets      = p->tx_packets;
-                       tx_bytes        = p->tx_bytes;
+                       rx_packets      = u64_stats_read(&p->rx_packets);
+                       rx_bytes        = u64_stats_read(&p->rx_bytes);
+                       rx_multicast    = u64_stats_read(&p->rx_multicast);
+                       tx_packets      = u64_stats_read(&p->tx_packets);
+                       tx_bytes        = u64_stats_read(&p->tx_bytes);
                } while (u64_stats_fetch_retry_irq(&p->syncp, start));
 
                stats->rx_packets       += rx_packets;
@@ -1870,9 +1870,9 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
                 * rx_dropped, tx_dropped & rx_nohandler are u32,
                 * updated without syncp protection.
                 */
-               rx_dropped      += p->rx_dropped;
-               tx_dropped      += p->tx_dropped;
-               rx_nohandler    += p->rx_nohandler;
+               rx_dropped      += READ_ONCE(p->rx_dropped);
+               tx_dropped      += READ_ONCE(p->tx_dropped);
+               rx_nohandler    += READ_ONCE(p->rx_nohandler);
        }
        stats->rx_dropped       = rx_dropped;
        stats->tx_dropped       = tx_dropped;
index 1cb6dab..dc79811 100644 (file)
@@ -337,8 +337,8 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
                skb->protocol = eth_type_trans (skb, dev->net);
 
        flags = u64_stats_update_begin_irqsave(&stats64->syncp);
-       stats64->rx_packets++;
-       stats64->rx_bytes += skb->len;
+       u64_stats_inc(&stats64->rx_packets);
+       u64_stats_add(&stats64->rx_bytes, skb->len);
        u64_stats_update_end_irqrestore(&stats64->syncp, flags);
 
        netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n",
@@ -1258,8 +1258,8 @@ static void tx_complete (struct urb *urb)
                unsigned long flags;
 
                flags = u64_stats_update_begin_irqsave(&stats64->syncp);
-               stats64->tx_packets += entry->packets;
-               stats64->tx_bytes += entry->length;
+               u64_stats_add(&stats64->tx_packets, entry->packets);
+               u64_stats_add(&stats64->tx_bytes, entry->length);
                u64_stats_update_end_irqrestore(&stats64->syncp, flags);
        } else {
                dev->net->stats.tx_errors++;
index 7a38925..a666a88 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Linux driver for VMware's vmxnet3 ethernet NIC.
 #
-# Copyright (C) 2007-2021, VMware, Inc. All Rights Reserved.
+# Copyright (C) 2007-2022, VMware, Inc. All Rights Reserved.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by the
index f9f3a23..41c0660 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Linux driver for VMware's vmxnet3 ethernet NIC.
  *
- * Copyright (C) 2008-2021, VMware, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2022, VMware, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
index 74d4e8b..41d6767 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Linux driver for VMware's vmxnet3 ethernet NIC.
  *
- * Copyright (C) 2008-2021, VMware, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2022, VMware, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -40,7 +40,13 @@ enum {
        VMXNET3_REG_MACL        = 0x28, /* MAC Address Low */
        VMXNET3_REG_MACH        = 0x30, /* MAC Address High */
        VMXNET3_REG_ICR         = 0x38, /* Interrupt Cause Register */
-       VMXNET3_REG_ECR         = 0x40  /* Event Cause Register */
+       VMXNET3_REG_ECR         = 0x40, /* Event Cause Register */
+       VMXNET3_REG_DCR         = 0x48, /* Device capability register,
+                                        * from 0x48 to 0x80
+                                        */
+       VMXNET3_REG_PTCR        = 0x88, /* Passthru capbility register
+                                        * from 0x88 to 0xb0
+                                        */
 };
 
 /* BAR 0 */
@@ -51,8 +57,18 @@ enum {
        VMXNET3_REG_RXPROD2     = 0xA00  /* Rx Producer Index for ring 2 */
 };
 
-#define VMXNET3_PT_REG_SIZE     4096   /* BAR 0 */
-#define VMXNET3_VD_REG_SIZE     4096   /* BAR 1 */
+/* For Large PT BAR, the following offset to DB register */
+enum {
+       VMXNET3_REG_LB_TXPROD   = 0x1000, /* Tx Producer Index */
+       VMXNET3_REG_LB_RXPROD   = 0x1400, /* Rx Producer Index for ring 1 */
+       VMXNET3_REG_LB_RXPROD2  = 0x1800, /* Rx Producer Index for ring 2 */
+};
+
+#define VMXNET3_PT_REG_SIZE         4096               /* BAR 0 */
+#define VMXNET3_LARGE_PT_REG_SIZE   8192               /* large PT pages */
+#define VMXNET3_VD_REG_SIZE         4096               /* BAR 1 */
+#define VMXNET3_LARGE_BAR0_REG_SIZE (4096 * 4096)      /* LARGE BAR 0 */
+#define VMXNET3_OOB_REG_SIZE        (4094 * 4096)      /* OOB pages */
 
 #define VMXNET3_REG_ALIGN       8      /* All registers are 8-byte aligned. */
 #define VMXNET3_REG_ALIGN_MASK  0x7
@@ -83,6 +99,9 @@ enum {
        VMXNET3_CMD_SET_COALESCE,
        VMXNET3_CMD_REGISTER_MEMREGS,
        VMXNET3_CMD_SET_RSS_FIELDS,
+       VMXNET3_CMD_RESERVED4,
+       VMXNET3_CMD_RESERVED5,
+       VMXNET3_CMD_SET_RING_BUFFER_SIZE,
 
        VMXNET3_CMD_FIRST_GET = 0xF00D0000,
        VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET,
@@ -101,6 +120,9 @@ enum {
        VMXNET3_CMD_GET_RESERVED2,
        VMXNET3_CMD_GET_RESERVED3,
        VMXNET3_CMD_GET_MAX_QUEUES_CONF,
+       VMXNET3_CMD_GET_RESERVED4,
+       VMXNET3_CMD_GET_MAX_CAPABILITIES,
+       VMXNET3_CMD_GET_DCR0_REG,
 };
 
 /*
@@ -126,17 +148,17 @@ struct Vmxnet3_TxDesc {
 
 #ifdef __BIG_ENDIAN_BITFIELD
        u32 msscof:14;  /* MSS, checksum offset, flags */
-       u32 ext1:1;
+       u32 ext1:1;     /* set to 1 to indicate inner csum/tso, vmxnet3 v7 */
        u32 dtype:1;    /* descriptor type */
-       u32 oco:1;
+       u32 oco:1;      /* Outer csum offload */
        u32 gen:1;      /* generation bit */
        u32 len:14;
 #else
        u32 len:14;
        u32 gen:1;      /* generation bit */
-       u32 oco:1;
+       u32 oco:1;      /* Outer csum offload */
        u32 dtype:1;    /* descriptor type */
-       u32 ext1:1;
+       u32 ext1:1;     /* set to 1 to indicate inner csum/tso, vmxnet3 v7 */
        u32 msscof:14;  /* MSS, checksum offset, flags */
 #endif  /* __BIG_ENDIAN_BITFIELD */
 
@@ -240,11 +262,13 @@ struct Vmxnet3_RxCompDesc {
        u32             rqID:10;      /* rx queue/ring ID */
        u32             sop:1;        /* Start of Packet */
        u32             eop:1;        /* End of Packet */
-       u32             ext1:2;
+       u32             ext1:2;       /* bit 0: indicating v4/v6/.. is for inner header */
+                                     /* bit 1: indicating rssType is based on inner header */
        u32             rxdIdx:12;    /* Index of the RxDesc */
 #else
        u32             rxdIdx:12;    /* Index of the RxDesc */
-       u32             ext1:2;
+       u32             ext1:2;       /* bit 0: indicating v4/v6/.. is for inner header */
+                                     /* bit 1: indicating rssType is based on inner header */
        u32             eop:1;        /* End of Packet */
        u32             sop:1;        /* Start of Packet */
        u32             rqID:10;      /* rx queue/ring ID */
@@ -378,6 +402,8 @@ union Vmxnet3_GenericDesc {
 
 /* max # of tx descs for a non-tso pkt */
 #define VMXNET3_MAX_TXD_PER_PKT 16
+/* max # of tx descs for a tso pkt */
+#define VMXNET3_MAX_TSO_TXD_PER_PKT 24
 
 /* Max size of a single rx buffer */
 #define VMXNET3_MAX_RX_BUF_SIZE  ((1 << 14) - 1)
@@ -724,6 +750,13 @@ enum Vmxnet3_RSSField {
        VMXNET3_RSS_FIELDS_ESPIP6 = 0x0020,
 };
 
+struct Vmxnet3_RingBufferSize {
+       __le16             ring1BufSizeType0;
+       __le16             ring1BufSizeType1;
+       __le16             ring2BufSizeType1;
+       __le16             pad;
+};
+
 /* If the command data <= 16 bytes, use the shared memory directly.
  * otherwise, use variable length configuration descriptor.
  */
@@ -731,6 +764,7 @@ union Vmxnet3_CmdInfo {
        struct Vmxnet3_VariableLenConfDesc      varConf;
        struct Vmxnet3_SetPolling               setPolling;
        enum   Vmxnet3_RSSField                 setRssFields;
+       struct Vmxnet3_RingBufferSize           ringBufSize;
        __le64                                  data[2];
 };
 
@@ -801,4 +835,30 @@ struct Vmxnet3_DriverShared {
 #define VMXNET3_LINK_UP         (10000 << 16 | 1)    /* 10 Gbps, up */
 #define VMXNET3_LINK_DOWN       0
 
+#define VMXNET3_DCR_ERROR                          31   /* error when bit 31 of DCR is set */
+#define VMXNET3_CAP_UDP_RSS                        0    /* bit 0 of DCR 0 */
+#define VMXNET3_CAP_ESP_RSS_IPV4                   1    /* bit 1 of DCR 0 */
+#define VMXNET3_CAP_GENEVE_CHECKSUM_OFFLOAD        2    /* bit 2 of DCR 0 */
+#define VMXNET3_CAP_GENEVE_TSO                     3    /* bit 3 of DCR 0 */
+#define VMXNET3_CAP_VXLAN_CHECKSUM_OFFLOAD         4    /* bit 4 of DCR 0 */
+#define VMXNET3_CAP_VXLAN_TSO                      5    /* bit 5 of DCR 0 */
+#define VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD  6    /* bit 6 of DCR 0 */
+#define VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD   7    /* bit 7 of DCR 0 */
+#define VMXNET3_CAP_PKT_STEERING_IPV4              8    /* bit 8 of DCR 0 */
+#define VMXNET3_CAP_VERSION_4_MAX                  VMXNET3_CAP_PKT_STEERING_IPV4
+#define VMXNET3_CAP_ESP_RSS_IPV6                   9    /* bit 9 of DCR 0 */
+#define VMXNET3_CAP_VERSION_5_MAX                  VMXNET3_CAP_ESP_RSS_IPV6
+#define VMXNET3_CAP_ESP_OVER_UDP_RSS               10   /* bit 10 of DCR 0 */
+#define VMXNET3_CAP_INNER_RSS                      11   /* bit 11 of DCR 0 */
+#define VMXNET3_CAP_INNER_ESP_RSS                  12   /* bit 12 of DCR 0 */
+#define VMXNET3_CAP_CRC32_HASH_FUNC                13   /* bit 13 of DCR 0 */
+#define VMXNET3_CAP_VERSION_6_MAX                  VMXNET3_CAP_CRC32_HASH_FUNC
+#define VMXNET3_CAP_OAM_FILTER                     14   /* bit 14 of DCR 0 */
+#define VMXNET3_CAP_ESP_QS                         15   /* bit 15 of DCR 0 */
+#define VMXNET3_CAP_LARGE_BAR                      16   /* bit 16 of DCR 0 */
+#define VMXNET3_CAP_OOORX_COMP                     17   /* bit 17 of DCR 0 */
+#define VMXNET3_CAP_VERSION_7_MAX                  18
+/* when new capability is introduced, update VMXNET3_CAP_MAX */
+#define VMXNET3_CAP_MAX                            VMXNET3_CAP_VERSION_7_MAX
+
 #endif /* _VMXNET3_DEFS_H_ */
index 93e8d11..1565e18 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Linux driver for VMware's vmxnet3 ethernet NIC.
  *
- * Copyright (C) 2008-2021, VMware, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2022, VMware, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -130,6 +130,20 @@ vmxnet3_tq_stop(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
        netif_stop_subqueue(adapter->netdev, (tq - adapter->tx_queue));
 }
 
+/* Check if capability is supported by UPT device or
+ * UPT is even requested
+ */
+bool
+vmxnet3_check_ptcapability(u32 cap_supported, u32 cap)
+{
+       if (cap_supported & (1UL << VMXNET3_DCR_ERROR) ||
+           cap_supported & (1UL << cap)) {
+               return true;
+       }
+
+       return false;
+}
+
 
 /*
  * Check the link state. This may start or stop the tx queue.
@@ -571,6 +585,7 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
 
                rbi = rbi_base + ring->next2fill;
                gd = ring->base + ring->next2fill;
+               rbi->comp_state = VMXNET3_RXD_COMP_PENDING;
 
                if (rbi->buf_type == VMXNET3_RX_BUF_SKB) {
                        if (rbi->skb == NULL) {
@@ -630,8 +645,10 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
 
                /* Fill the last buffer but dont mark it ready, or else the
                 * device will think that the queue is full */
-               if (num_allocated == num_to_alloc)
+               if (num_allocated == num_to_alloc) {
+                       rbi->comp_state = VMXNET3_RXD_COMP_DONE;
                        break;
+               }
 
                gd->dword[2] |= cpu_to_le32(ring->gen << VMXNET3_RXD_GEN_SHIFT);
                num_allocated++;
@@ -1044,6 +1061,23 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
                        }
                        tq->stats.copy_skb_header++;
                }
+               if (unlikely(count > VMXNET3_MAX_TSO_TXD_PER_PKT)) {
+                       /* tso pkts must not use more than
+                        * VMXNET3_MAX_TSO_TXD_PER_PKT entries
+                        */
+                       if (skb_linearize(skb) != 0) {
+                               tq->stats.drop_too_many_frags++;
+                               goto drop_pkt;
+                       }
+                       tq->stats.linearized++;
+
+                       /* recalculate the # of descriptors to use */
+                       count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+                       if (unlikely(count > VMXNET3_MAX_TSO_TXD_PER_PKT)) {
+                               tq->stats.drop_too_many_frags++;
+                               goto drop_pkt;
+                       }
+               }
                if (skb->encapsulation) {
                        vmxnet3_prepare_inner_tso(skb, &ctx);
                } else {
@@ -1127,7 +1161,12 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
        if (ctx.mss) {
                if (VMXNET3_VERSION_GE_4(adapter) && skb->encapsulation) {
                        gdesc->txd.hlen = ctx.l4_offset + ctx.l4_hdr_size;
-                       gdesc->txd.om = VMXNET3_OM_ENCAP;
+                       if (VMXNET3_VERSION_GE_7(adapter)) {
+                               gdesc->txd.om = VMXNET3_OM_TSO;
+                               gdesc->txd.ext1 = 1;
+                       } else {
+                               gdesc->txd.om = VMXNET3_OM_ENCAP;
+                       }
                        gdesc->txd.msscof = ctx.mss;
 
                        if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)
@@ -1144,8 +1183,15 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
                            skb->encapsulation) {
                                gdesc->txd.hlen = ctx.l4_offset +
                                                  ctx.l4_hdr_size;
-                               gdesc->txd.om = VMXNET3_OM_ENCAP;
-                               gdesc->txd.msscof = 0;          /* Reserved */
+                               if (VMXNET3_VERSION_GE_7(adapter)) {
+                                       gdesc->txd.om = VMXNET3_OM_CSUM;
+                                       gdesc->txd.msscof = ctx.l4_offset +
+                                                           skb->csum_offset;
+                                       gdesc->txd.ext1 = 1;
+                               } else {
+                                       gdesc->txd.om = VMXNET3_OM_ENCAP;
+                                       gdesc->txd.msscof = 0;          /* Reserved */
+                               }
                        } else {
                                gdesc->txd.hlen = ctx.l4_offset;
                                gdesc->txd.om = VMXNET3_OM_CSUM;
@@ -1193,7 +1239,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
        if (tx_num_deferred >= le32_to_cpu(tq->shared->txThreshold)) {
                tq->shared->txNumDeferred = 0;
                VMXNET3_WRITE_BAR0_REG(adapter,
-                                      VMXNET3_REG_TXPROD + tq->qid * 8,
+                                      adapter->tx_prod_offset + tq->qid * 8,
                                       tq->tx_ring.next2fill);
        }
 
@@ -1345,14 +1391,15 @@ static int
 vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
                       struct vmxnet3_adapter *adapter, int quota)
 {
-       static const u32 rxprod_reg[2] = {
-               VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2
+       u32 rxprod_reg[2] = {
+               adapter->rx_prod_offset, adapter->rx_prod2_offset
        };
        u32 num_pkts = 0;
        bool skip_page_frags = false;
        struct Vmxnet3_RxCompDesc *rcd;
        struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
        u16 segCnt = 0, mss = 0;
+       int comp_offset, fill_offset;
 #ifdef __BIG_ENDIAN_BITFIELD
        struct Vmxnet3_RxDesc rxCmdDesc;
        struct Vmxnet3_RxCompDesc rxComp;
@@ -1625,9 +1672,15 @@ not_lro:
 
 rcd_done:
                /* device may have skipped some rx descs */
-               ring->next2comp = idx;
-               num_to_alloc = vmxnet3_cmd_ring_desc_avail(ring);
                ring = rq->rx_ring + ring_idx;
+               rbi->comp_state = VMXNET3_RXD_COMP_DONE;
+
+               comp_offset = vmxnet3_cmd_ring_desc_avail(ring);
+               fill_offset = (idx > ring->next2fill ? 0 : ring->size) +
+                             idx - ring->next2fill - 1;
+               if (!ring->isOutOfOrder || fill_offset >= comp_offset)
+                       ring->next2comp = idx;
+               num_to_alloc = vmxnet3_cmd_ring_desc_avail(ring);
 
                /* Ensure that the writes to rxd->gen bits will be observed
                 * after all other writes to rxd objects.
@@ -1635,18 +1688,38 @@ rcd_done:
                dma_wmb();
 
                while (num_to_alloc) {
-                       vmxnet3_getRxDesc(rxd, &ring->base[ring->next2fill].rxd,
-                                         &rxCmdDesc);
-                       BUG_ON(!rxd->addr);
+                       rbi = rq->buf_info[ring_idx] + ring->next2fill;
+                       if (!(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_OOORX_COMP)))
+                               goto refill_buf;
+                       if (ring_idx == 0) {
+                               /* ring0 Type1 buffers can get skipped; re-fill them */
+                               if (rbi->buf_type != VMXNET3_RX_BUF_SKB)
+                                       goto refill_buf;
+                       }
+                       if (rbi->comp_state == VMXNET3_RXD_COMP_DONE) {
+refill_buf:
+                               vmxnet3_getRxDesc(rxd, &ring->base[ring->next2fill].rxd,
+                                                 &rxCmdDesc);
+                               WARN_ON(!rxd->addr);
+
+                               /* Recv desc is ready to be used by the device */
+                               rxd->gen = ring->gen;
+                               vmxnet3_cmd_ring_adv_next2fill(ring);
+                               rbi->comp_state = VMXNET3_RXD_COMP_PENDING;
+                               num_to_alloc--;
+                       } else {
+                               /* rx completion hasn't occurred */
+                               ring->isOutOfOrder = 1;
+                               break;
+                       }
+               }
 
-                       /* Recv desc is ready to be used by the device */
-                       rxd->gen = ring->gen;
-                       vmxnet3_cmd_ring_adv_next2fill(ring);
-                       num_to_alloc--;
+               if (num_to_alloc == 0) {
+                       ring->isOutOfOrder = 0;
                }
 
                /* if needed, update the register */
-               if (unlikely(rq->shared->updateRxProd)) {
+               if (unlikely(rq->shared->updateRxProd) && (ring->next2fill & 0xf) == 0) {
                        VMXNET3_WRITE_BAR0_REG(adapter,
                                               rxprod_reg[ring_idx] + rq->qid * 8,
                                               ring->next2fill);
@@ -1810,6 +1883,7 @@ vmxnet3_rq_init(struct vmxnet3_rx_queue *rq,
                memset(rq->rx_ring[i].base, 0, rq->rx_ring[i].size *
                       sizeof(struct Vmxnet3_RxDesc));
                rq->rx_ring[i].gen = VMXNET3_INIT_GEN;
+               rq->rx_ring[i].isOutOfOrder = 0;
        }
        if (vmxnet3_rq_alloc_rx_buf(rq, 0, rq->rx_ring[0].size - 1,
                                    adapter) == 0) {
@@ -2000,8 +2074,17 @@ vmxnet3_poll_rx_only(struct napi_struct *napi, int budget)
        rxd_done = vmxnet3_rq_rx_complete(rq, adapter, budget);
 
        if (rxd_done < budget) {
+               struct Vmxnet3_RxCompDesc *rcd;
+#ifdef __BIG_ENDIAN_BITFIELD
+               struct Vmxnet3_RxCompDesc rxComp;
+#endif
                napi_complete_done(napi, rxd_done);
                vmxnet3_enable_intr(adapter, rq->comp_ring.intr_idx);
+               /* after unmasking the interrupt, check if any descriptors were completed */
+               vmxnet3_getRxComp(rcd, &rq->comp_ring.base[rq->comp_ring.next2proc].rcd,
+                                 &rxComp);
+               if (rcd->gen == rq->comp_ring.gen && napi_reschedule(napi))
+                       vmxnet3_disable_intr(adapter, rq->comp_ring.intr_idx);
        }
        return rxd_done;
 }
@@ -2626,6 +2709,23 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
        /* the rest are already zeroed */
 }
 
+static void
+vmxnet3_init_bufsize(struct vmxnet3_adapter *adapter)
+{
+       struct Vmxnet3_DriverShared *shared = adapter->shared;
+       union Vmxnet3_CmdInfo *cmdInfo = &shared->cu.cmdInfo;
+       unsigned long flags;
+
+       if (!VMXNET3_VERSION_GE_7(adapter))
+               return;
+
+       cmdInfo->ringBufSize = adapter->ringBufSize;
+       spin_lock_irqsave(&adapter->cmd_lock, flags);
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                              VMXNET3_CMD_SET_RING_BUFFER_SIZE);
+       spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+}
+
 static void
 vmxnet3_init_coalesce(struct vmxnet3_adapter *adapter)
 {
@@ -2671,6 +2771,36 @@ vmxnet3_init_rssfields(struct vmxnet3_adapter *adapter)
                adapter->rss_fields =
                        VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
        } else {
+               if (VMXNET3_VERSION_GE_7(adapter)) {
+                       if ((adapter->rss_fields & VMXNET3_RSS_FIELDS_UDPIP4 ||
+                            adapter->rss_fields & VMXNET3_RSS_FIELDS_UDPIP6) &&
+                           vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                                      VMXNET3_CAP_UDP_RSS)) {
+                               adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_UDP_RSS;
+                       } else {
+                               adapter->dev_caps[0] &= ~(1UL << VMXNET3_CAP_UDP_RSS);
+                       }
+
+                       if ((adapter->rss_fields & VMXNET3_RSS_FIELDS_ESPIP4) &&
+                           vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                                      VMXNET3_CAP_ESP_RSS_IPV4)) {
+                               adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_ESP_RSS_IPV4;
+                       } else {
+                               adapter->dev_caps[0] &= ~(1UL << VMXNET3_CAP_ESP_RSS_IPV4);
+                       }
+
+                       if ((adapter->rss_fields & VMXNET3_RSS_FIELDS_ESPIP6) &&
+                           vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                                      VMXNET3_CAP_ESP_RSS_IPV6)) {
+                               adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_ESP_RSS_IPV6;
+                       } else {
+                               adapter->dev_caps[0] &= ~(1UL << VMXNET3_CAP_ESP_RSS_IPV6);
+                       }
+
+                       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DCR, adapter->dev_caps[0]);
+                       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_DCR0_REG);
+                       adapter->dev_caps[0] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+               }
                cmdInfo->setRssFields = adapter->rss_fields;
                VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
                                       VMXNET3_CMD_SET_RSS_FIELDS);
@@ -2734,14 +2864,15 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
                goto activate_err;
        }
 
+       vmxnet3_init_bufsize(adapter);
        vmxnet3_init_coalesce(adapter);
        vmxnet3_init_rssfields(adapter);
 
        for (i = 0; i < adapter->num_rx_queues; i++) {
                VMXNET3_WRITE_BAR0_REG(adapter,
-                               VMXNET3_REG_RXPROD + i * VMXNET3_REG_ALIGN,
+                               adapter->rx_prod_offset + i * VMXNET3_REG_ALIGN,
                                adapter->rx_queue[i].rx_ring[0].next2fill);
-               VMXNET3_WRITE_BAR0_REG(adapter, (VMXNET3_REG_RXPROD2 +
+               VMXNET3_WRITE_BAR0_REG(adapter, (adapter->rx_prod2_offset +
                                (i * VMXNET3_REG_ALIGN)),
                                adapter->rx_queue[i].rx_ring[1].next2fill);
        }
@@ -2907,19 +3038,29 @@ static void
 vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter)
 {
        size_t sz, i, ring0_size, ring1_size, comp_size;
-       if (adapter->netdev->mtu <= VMXNET3_MAX_SKB_BUF_SIZE -
-                                   VMXNET3_MAX_ETH_HDR_SIZE) {
-               adapter->skb_buf_size = adapter->netdev->mtu +
-                                       VMXNET3_MAX_ETH_HDR_SIZE;
-               if (adapter->skb_buf_size < VMXNET3_MIN_T0_BUF_SIZE)
-                       adapter->skb_buf_size = VMXNET3_MIN_T0_BUF_SIZE;
-
-               adapter->rx_buf_per_pkt = 1;
+       /* With version7 ring1 will have only T0 buffers */
+       if (!VMXNET3_VERSION_GE_7(adapter)) {
+               if (adapter->netdev->mtu <= VMXNET3_MAX_SKB_BUF_SIZE -
+                                           VMXNET3_MAX_ETH_HDR_SIZE) {
+                       adapter->skb_buf_size = adapter->netdev->mtu +
+                                               VMXNET3_MAX_ETH_HDR_SIZE;
+                       if (adapter->skb_buf_size < VMXNET3_MIN_T0_BUF_SIZE)
+                               adapter->skb_buf_size = VMXNET3_MIN_T0_BUF_SIZE;
+
+                       adapter->rx_buf_per_pkt = 1;
+               } else {
+                       adapter->skb_buf_size = VMXNET3_MAX_SKB_BUF_SIZE;
+                       sz = adapter->netdev->mtu - VMXNET3_MAX_SKB_BUF_SIZE +
+                                                   VMXNET3_MAX_ETH_HDR_SIZE;
+                       adapter->rx_buf_per_pkt = 1 + (sz + PAGE_SIZE - 1) / PAGE_SIZE;
+               }
        } else {
-               adapter->skb_buf_size = VMXNET3_MAX_SKB_BUF_SIZE;
-               sz = adapter->netdev->mtu - VMXNET3_MAX_SKB_BUF_SIZE +
-                                           VMXNET3_MAX_ETH_HDR_SIZE;
-               adapter->rx_buf_per_pkt = 1 + (sz + PAGE_SIZE - 1) / PAGE_SIZE;
+               adapter->skb_buf_size = min((int)adapter->netdev->mtu + VMXNET3_MAX_ETH_HDR_SIZE,
+                                           VMXNET3_MAX_SKB_BUF_SIZE);
+               adapter->rx_buf_per_pkt = 1;
+               adapter->ringBufSize.ring1BufSizeType0 = cpu_to_le16(adapter->skb_buf_size);
+               adapter->ringBufSize.ring1BufSizeType1 = 0;
+               adapter->ringBufSize.ring2BufSizeType1 = cpu_to_le16(PAGE_SIZE);
        }
 
        /*
@@ -2935,6 +3076,11 @@ vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter)
        ring1_size = (ring1_size + sz - 1) / sz * sz;
        ring1_size = min_t(u32, ring1_size, VMXNET3_RX_RING2_MAX_SIZE /
                           sz * sz);
+       /* For v7 and later, keep ring size power of 2 for UPT */
+       if (VMXNET3_VERSION_GE_7(adapter)) {
+               ring0_size = rounddown_pow_of_two(ring0_size);
+               ring1_size = rounddown_pow_of_two(ring1_size);
+       }
        comp_size = ring0_size + ring1_size;
 
        for (i = 0; i < adapter->num_rx_queues; i++) {
@@ -3185,6 +3331,47 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter)
                        NETIF_F_GSO_UDP_TUNNEL_CSUM;
        }
 
+       if (VMXNET3_VERSION_GE_7(adapter)) {
+               unsigned long flags;
+
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_GENEVE_CHECKSUM_OFFLOAD)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_GENEVE_CHECKSUM_OFFLOAD;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_VXLAN_CHECKSUM_OFFLOAD)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_VXLAN_CHECKSUM_OFFLOAD;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_GENEVE_TSO)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_GENEVE_TSO;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_VXLAN_TSO)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_VXLAN_TSO;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD;
+               }
+
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DCR, adapter->dev_caps[0]);
+               spin_lock_irqsave(&adapter->cmd_lock, flags);
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_DCR0_REG);
+               adapter->dev_caps[0] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
+               if (!(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD)) &&
+                   !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD))) {
+                       netdev->hw_enc_features &= ~NETIF_F_GSO_UDP_TUNNEL_CSUM;
+                       netdev->features &= ~NETIF_F_GSO_UDP_TUNNEL_CSUM;
+               }
+       }
+
        netdev->vlan_features = netdev->hw_features &
                                ~(NETIF_F_HW_VLAN_CTAG_TX |
                                  NETIF_F_HW_VLAN_CTAG_RX);
@@ -3472,7 +3659,12 @@ vmxnet3_probe_device(struct pci_dev *pdev,
                goto err_alloc_pci;
 
        ver = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_VRRS);
-       if (ver & (1 << VMXNET3_REV_6)) {
+       if (ver & (1 << VMXNET3_REV_7)) {
+               VMXNET3_WRITE_BAR1_REG(adapter,
+                                      VMXNET3_REG_VRRS,
+                                      1 << VMXNET3_REV_7);
+               adapter->version = VMXNET3_REV_7 + 1;
+       } else if (ver & (1 << VMXNET3_REV_6)) {
                VMXNET3_WRITE_BAR1_REG(adapter,
                                       VMXNET3_REG_VRRS,
                                       1 << VMXNET3_REV_6);
@@ -3520,6 +3712,39 @@ vmxnet3_probe_device(struct pci_dev *pdev,
                goto err_ver;
        }
 
+       if (VMXNET3_VERSION_GE_7(adapter)) {
+               adapter->devcap_supported[0] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_DCR);
+               adapter->ptcap_supported[0] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_PTCR);
+               if (adapter->devcap_supported[0] & (1UL << VMXNET3_CAP_LARGE_BAR)) {
+                       adapter->dev_caps[0] = adapter->devcap_supported[0] &
+                                                       (1UL << VMXNET3_CAP_LARGE_BAR);
+               }
+               if (!(adapter->ptcap_supported[0] & (1UL << VMXNET3_DCR_ERROR)) &&
+                   adapter->ptcap_supported[0] & (1UL << VMXNET3_CAP_OOORX_COMP) &&
+                   adapter->devcap_supported[0] & (1UL << VMXNET3_CAP_OOORX_COMP)) {
+                       adapter->dev_caps[0] |= adapter->devcap_supported[0] &
+                                               (1UL << VMXNET3_CAP_OOORX_COMP);
+               }
+               if (adapter->dev_caps[0])
+                       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DCR, adapter->dev_caps[0]);
+
+               spin_lock_irqsave(&adapter->cmd_lock, flags);
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_DCR0_REG);
+               adapter->dev_caps[0] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       }
+
+       if (VMXNET3_VERSION_GE_7(adapter) &&
+           adapter->dev_caps[0] & (1UL << VMXNET3_CAP_LARGE_BAR)) {
+               adapter->tx_prod_offset = VMXNET3_REG_LB_TXPROD;
+               adapter->rx_prod_offset = VMXNET3_REG_LB_RXPROD;
+               adapter->rx_prod2_offset = VMXNET3_REG_LB_RXPROD2;
+       } else {
+               adapter->tx_prod_offset = VMXNET3_REG_TXPROD;
+               adapter->rx_prod_offset = VMXNET3_REG_RXPROD;
+               adapter->rx_prod2_offset = VMXNET3_REG_RXPROD2;
+       }
+
        if (VMXNET3_VERSION_GE_6(adapter)) {
                spin_lock_irqsave(&adapter->cmd_lock, flags);
                VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
index 3172d46..ce39932 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Linux driver for VMware's vmxnet3 ethernet NIC.
  *
- * Copyright (C) 2008-2021, VMware, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2022, VMware, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -298,7 +298,7 @@ netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
        return features;
 }
 
-static void vmxnet3_enable_encap_offloads(struct net_device *netdev)
+static void vmxnet3_enable_encap_offloads(struct net_device *netdev, netdev_features_t features)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
@@ -306,8 +306,50 @@ static void vmxnet3_enable_encap_offloads(struct net_device *netdev)
                netdev->hw_enc_features |= NETIF_F_SG | NETIF_F_RXCSUM |
                        NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
                        NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_TSO | NETIF_F_TSO6 |
-                       NETIF_F_LRO | NETIF_F_GSO_UDP_TUNNEL |
-                       NETIF_F_GSO_UDP_TUNNEL_CSUM;
+                       NETIF_F_LRO;
+               if (features & NETIF_F_GSO_UDP_TUNNEL)
+                       netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
+               if (features & NETIF_F_GSO_UDP_TUNNEL_CSUM)
+                       netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
+       }
+       if (VMXNET3_VERSION_GE_7(adapter)) {
+               unsigned long flags;
+
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_GENEVE_CHECKSUM_OFFLOAD)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_GENEVE_CHECKSUM_OFFLOAD;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_VXLAN_CHECKSUM_OFFLOAD)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_VXLAN_CHECKSUM_OFFLOAD;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_GENEVE_TSO)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_GENEVE_TSO;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_VXLAN_TSO)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_VXLAN_TSO;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD;
+               }
+               if (vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                              VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD)) {
+                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD;
+               }
+
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DCR, adapter->dev_caps[0]);
+               spin_lock_irqsave(&adapter->cmd_lock, flags);
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_DCR0_REG);
+               adapter->dev_caps[0] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
+               if (!(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD)) &&
+                   !(adapter->dev_caps[0] & (1UL << VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD))) {
+                       netdev->hw_enc_features &= ~NETIF_F_GSO_UDP_TUNNEL_CSUM;
+               }
        }
 }
 
@@ -322,6 +364,22 @@ static void vmxnet3_disable_encap_offloads(struct net_device *netdev)
                        NETIF_F_LRO | NETIF_F_GSO_UDP_TUNNEL |
                        NETIF_F_GSO_UDP_TUNNEL_CSUM);
        }
+       if (VMXNET3_VERSION_GE_7(adapter)) {
+               unsigned long flags;
+
+               adapter->dev_caps[0] &= ~(1UL << VMXNET3_CAP_GENEVE_CHECKSUM_OFFLOAD |
+                                         1UL << VMXNET3_CAP_VXLAN_CHECKSUM_OFFLOAD  |
+                                         1UL << VMXNET3_CAP_GENEVE_TSO |
+                                         1UL << VMXNET3_CAP_VXLAN_TSO  |
+                                         1UL << VMXNET3_CAP_GENEVE_OUTER_CHECKSUM_OFFLOAD |
+                                         1UL << VMXNET3_CAP_VXLAN_OUTER_CHECKSUM_OFFLOAD);
+
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DCR, adapter->dev_caps[0]);
+               spin_lock_irqsave(&adapter->cmd_lock, flags);
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_DCR0_REG);
+               adapter->dev_caps[0] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+       }
 }
 
 int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
@@ -357,8 +415,8 @@ int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
                        adapter->shared->devRead.misc.uptFeatures &=
                        ~UPT1_F_RXVLAN;
 
-               if ((features & tun_offload_mask) != 0 && !udp_tun_enabled) {
-                       vmxnet3_enable_encap_offloads(netdev);
+               if ((features & tun_offload_mask) != 0) {
+                       vmxnet3_enable_encap_offloads(netdev, features);
                        adapter->shared->devRead.misc.uptFeatures |=
                        UPT1_F_RXINNEROFLD;
                } else if ((features & tun_offload_mask) == 0 &&
@@ -462,7 +520,7 @@ vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p)
        for (i = 0; i < adapter->num_tx_queues; i++) {
                struct vmxnet3_tx_queue *tq = &adapter->tx_queue[i];
 
-               buf[j++] = VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_TXPROD +
+               buf[j++] = VMXNET3_READ_BAR0_REG(adapter, adapter->tx_prod_offset +
                                                 i * VMXNET3_REG_ALIGN);
 
                buf[j++] = VMXNET3_GET_ADDR_LO(tq->tx_ring.basePA);
@@ -490,9 +548,9 @@ vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p)
        for (i = 0; i < adapter->num_rx_queues; i++) {
                struct vmxnet3_rx_queue *rq = &adapter->rx_queue[i];
 
-               buf[j++] =  VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_RXPROD +
+               buf[j++] =  VMXNET3_READ_BAR0_REG(adapter, adapter->rx_prod_offset +
                                                  i * VMXNET3_REG_ALIGN);
-               buf[j++] =  VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_RXPROD2 +
+               buf[j++] =  VMXNET3_READ_BAR0_REG(adapter, adapter->rx_prod2_offset +
                                                  i * VMXNET3_REG_ALIGN);
 
                buf[j++] = VMXNET3_GET_ADDR_LO(rq->rx_ring[0].basePA);
@@ -660,6 +718,13 @@ vmxnet3_set_ringparam(struct net_device *netdev,
        new_rx_ring2_size = min_t(u32, new_rx_ring2_size,
                                  VMXNET3_RX_RING2_MAX_SIZE);
 
+       /* For v7 and later, keep ring size power of 2 for UPT */
+       if (VMXNET3_VERSION_GE_7(adapter)) {
+               new_tx_ring_size = rounddown_pow_of_two(new_tx_ring_size);
+               new_rx_ring_size = rounddown_pow_of_two(new_rx_ring_size);
+               new_rx_ring2_size = rounddown_pow_of_two(new_rx_ring2_size);
+       }
+
        /* rx data ring buffer size has to be a multiple of
         * VMXNET3_RXDATA_DESC_SIZE_ALIGN
         */
@@ -913,6 +978,39 @@ vmxnet3_set_rss_hash_opt(struct net_device *netdev,
                        union Vmxnet3_CmdInfo *cmdInfo = &shared->cu.cmdInfo;
                        unsigned long flags;
 
+                       if (VMXNET3_VERSION_GE_7(adapter)) {
+                               if ((rss_fields & VMXNET3_RSS_FIELDS_UDPIP4 ||
+                                    rss_fields & VMXNET3_RSS_FIELDS_UDPIP6) &&
+                                   vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                                              VMXNET3_CAP_UDP_RSS)) {
+                                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_UDP_RSS;
+                               } else {
+                                       adapter->dev_caps[0] &= ~(1UL << VMXNET3_CAP_UDP_RSS);
+                               }
+                               if ((rss_fields & VMXNET3_RSS_FIELDS_ESPIP4) &&
+                                   vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                                              VMXNET3_CAP_ESP_RSS_IPV4)) {
+                                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_ESP_RSS_IPV4;
+                               } else {
+                                       adapter->dev_caps[0] &= ~(1UL << VMXNET3_CAP_ESP_RSS_IPV4);
+                               }
+                               if ((rss_fields & VMXNET3_RSS_FIELDS_ESPIP6) &&
+                                   vmxnet3_check_ptcapability(adapter->ptcap_supported[0],
+                                                              VMXNET3_CAP_ESP_RSS_IPV6)) {
+                                       adapter->dev_caps[0] |= 1UL << VMXNET3_CAP_ESP_RSS_IPV6;
+                               } else {
+                                       adapter->dev_caps[0] &= ~(1UL << VMXNET3_CAP_ESP_RSS_IPV6);
+                               }
+
+                               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DCR,
+                                                      adapter->dev_caps[0]);
+                               spin_lock_irqsave(&adapter->cmd_lock, flags);
+                               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                                      VMXNET3_CMD_GET_DCR0_REG);
+                               adapter->dev_caps[0] = VMXNET3_READ_BAR1_REG(adapter,
+                                                                            VMXNET3_REG_CMD);
+                               spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+                       }
                        spin_lock_irqsave(&adapter->cmd_lock, flags);
                        cmdInfo->setRssFields = rss_fields;
                        VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
index 7027ff4..3367db2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Linux driver for VMware's vmxnet3 ethernet NIC.
  *
- * Copyright (C) 2008-2021, VMware, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2022, VMware, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.6.0.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.7.0.0-k"
 
 /* Each byte of this 32-bit integer encodes a version number in
  * VMXNET3_DRIVER_VERSION_STRING.
  */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01060000
+#define VMXNET3_DRIVER_VERSION_NUM      0x01070000
 
 #if defined(CONFIG_PCI_MSI)
        /* RSS only makes sense if MSI-X is supported. */
        #define VMXNET3_RSS
 #endif
 
+#define VMXNET3_REV_7          6       /* Vmxnet3 Rev. 7 */
 #define VMXNET3_REV_6          5       /* Vmxnet3 Rev. 6 */
 #define VMXNET3_REV_5          4       /* Vmxnet3 Rev. 5 */
 #define VMXNET3_REV_4          3       /* Vmxnet3 Rev. 4 */
@@ -135,6 +136,7 @@ struct vmxnet3_cmd_ring {
        u32             next2fill;
        u32             next2comp;
        u8              gen;
+       u8              isOutOfOrder;
        dma_addr_t      basePA;
 };
 
@@ -259,9 +261,13 @@ enum vmxnet3_rx_buf_type {
        VMXNET3_RX_BUF_PAGE = 2
 };
 
+#define VMXNET3_RXD_COMP_PENDING        0
+#define VMXNET3_RXD_COMP_DONE           1
+
 struct vmxnet3_rx_buf_info {
        enum vmxnet3_rx_buf_type buf_type;
        u16     len;
+       u8      comp_state;
        union {
                struct sk_buff *skb;
                struct page    *page;
@@ -402,6 +408,13 @@ struct vmxnet3_adapter {
        dma_addr_t pm_conf_pa;
        dma_addr_t rss_conf_pa;
        bool   queuesExtEnabled;
+       struct Vmxnet3_RingBufferSize     ringBufSize;
+       u32    devcap_supported[8];
+       u32    ptcap_supported[8];
+       u32    dev_caps[8];
+       u16    tx_prod_offset;
+       u16    rx_prod_offset;
+       u16    rx_prod2_offset;
 };
 
 #define VMXNET3_WRITE_BAR0_REG(adapter, reg, val)  \
@@ -431,11 +444,13 @@ struct vmxnet3_adapter {
        (adapter->version >= VMXNET3_REV_5 + 1)
 #define VMXNET3_VERSION_GE_6(adapter) \
        (adapter->version >= VMXNET3_REV_6 + 1)
+#define VMXNET3_VERSION_GE_7(adapter) \
+       (adapter->version >= VMXNET3_REV_7 + 1)
 
 /* must be a multiple of VMXNET3_RING_SIZE_ALIGN */
 #define VMXNET3_DEF_TX_RING_SIZE    512
 #define VMXNET3_DEF_RX_RING_SIZE    1024
-#define VMXNET3_DEF_RX_RING2_SIZE   256
+#define VMXNET3_DEF_RX_RING2_SIZE   512
 
 #define VMXNET3_DEF_RXDATA_DESC_SIZE 128
 
@@ -494,6 +509,7 @@ void vmxnet3_set_ethtool_ops(struct net_device *netdev);
 
 void vmxnet3_get_stats64(struct net_device *dev,
                         struct rtnl_link_stats64 *stats);
+bool vmxnet3_check_ptcapability(u32 cap_supported, u32 cap);
 
 extern char vmxnet3_driver_name[];
 #endif
index cfc30ce..40445a1 100644 (file)
@@ -814,8 +814,8 @@ static void vrf_rt6_release(struct net_device *dev, struct net_vrf *vrf)
         */
        if (rt6) {
                dst = &rt6->dst;
-               dev_replace_track(dst->dev, net->loopback_dev,
-                                 &dst->dev_tracker, GFP_KERNEL);
+               netdev_ref_replace(dst->dev, net->loopback_dev,
+                                  &dst->dev_tracker, GFP_KERNEL);
                dst->dev = net->loopback_dev;
                dst_release(dst);
        }
@@ -1061,8 +1061,8 @@ static void vrf_rtable_release(struct net_device *dev, struct net_vrf *vrf)
         */
        if (rth) {
                dst = &rth->dst;
-               dev_replace_track(dst->dev, net->loopback_dev,
-                                 &dst->dev_tracker, GFP_KERNEL);
+               netdev_ref_replace(dst->dev, net->loopback_dev,
+                                  &dst->dev_tracker, GFP_KERNEL);
                dst->dev = net->loopback_dev;
                dst_release(dst);
        }
index 265d4a0..8b0710b 100644 (file)
@@ -2385,15 +2385,15 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
                vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni);
 
        u64_stats_update_begin(&tx_stats->syncp);
-       tx_stats->tx_packets++;
-       tx_stats->tx_bytes += len;
+       u64_stats_inc(&tx_stats->tx_packets);
+       u64_stats_add(&tx_stats->tx_bytes, len);
        u64_stats_update_end(&tx_stats->syncp);
        vxlan_vnifilter_count(src_vxlan, vni, NULL, VXLAN_VNI_STATS_TX, len);
 
        if (__netif_rx(skb) == NET_RX_SUCCESS) {
                u64_stats_update_begin(&rx_stats->syncp);
-               rx_stats->rx_packets++;
-               rx_stats->rx_bytes += len;
+               u64_stats_inc(&rx_stats->rx_packets);
+               u64_stats_add(&rx_stats->rx_bytes, len);
                u64_stats_update_end(&rx_stats->syncp);
                vxlan_vnifilter_count(dst_vxlan, vni, NULL, VXLAN_VNI_STATS_RX,
                                      len);
index 5f43568..63908db 100644 (file)
@@ -43,7 +43,7 @@
  *      This version number is incremented with each official release of the
  *      package and is a simplified number for normal user reference.
  *      Individual files are tracked by the version control system and may
- *      have individual versions (or IDs) that move much faster than the
+ *      have individual versions (or IDs) that move much faster than
  *      the release version as individual updates are tracked.
  */
 #define FST_USER_VERSION        "1.04"
index 7b8df40..7135d51 100644 (file)
 /* Must be called with bh disabled. */
 static void update_rx_stats(struct wg_peer *peer, size_t len)
 {
-       struct pcpu_sw_netstats *tstats =
-               get_cpu_ptr(peer->device->dev->tstats);
-
-       u64_stats_update_begin(&tstats->syncp);
-       ++tstats->rx_packets;
-       tstats->rx_bytes += len;
+       dev_sw_netstats_rx_add(peer->device->dev, len);
        peer->rx_bytes += len;
-       u64_stats_update_end(&tstats->syncp);
-       put_cpu_ptr(tstats);
 }
 
 #define SKB_TYPE_LE32(skb) (((struct message_header *)(skb)->data)->type)
index 2f746eb..bd408d2 100644 (file)
@@ -290,8 +290,7 @@ static inline int hwsim_net_set_netgroup(struct net *net)
 {
        struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id);
 
-       hwsim_net->netgroup = ida_simple_get(&hwsim_netgroup_ida,
-                                            0, 0, GFP_KERNEL);
+       hwsim_net->netgroup = ida_alloc(&hwsim_netgroup_ida, GFP_KERNEL);
        return hwsim_net->netgroup >= 0 ? 0 : -ENOMEM;
 }
 
@@ -4733,7 +4732,7 @@ static void __net_exit hwsim_exit_net(struct net *net)
                                         NULL);
        }
 
-       ida_simple_remove(&hwsim_netgroup_ida, hwsim_net_get_netgroup(net));
+       ida_free(&hwsim_netgroup_ida, hwsim_net_get_netgroup(net));
 }
 
 static struct pernet_operations hwsim_net_ops = {
index 8d8378b..1ac4684 100644 (file)
 static const struct ieee80211_txrx_stypes
        wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = {
        [NL80211_IFTYPE_STATION] = {
-               .tx = 0xffff,
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                       BIT(IEEE80211_STYPE_AUTH >> 4),
                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
-                       BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+                       BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+                       BIT(IEEE80211_STYPE_AUTH >> 4)
        },
        [NL80211_IFTYPE_AP] = {
                .tx = 0xffff,
@@ -305,6 +307,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
        int ret;
        u32 i;
        u8 security = WILC_FW_SEC_NO;
+       enum mfptype mfp_type = WILC_FW_MFP_NONE;
        enum authtype auth_type = WILC_FW_AUTH_ANY;
        u32 cipher_group;
        struct cfg80211_bss *bss;
@@ -313,32 +316,9 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
 
        vif->connecting = true;
 
-       memset(priv->wep_key, 0, sizeof(priv->wep_key));
-       memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len));
-
        cipher_group = sme->crypto.cipher_group;
        if (cipher_group != 0) {
-               if (cipher_group == WLAN_CIPHER_SUITE_WEP40) {
-                       security = WILC_FW_SEC_WEP;
-
-                       priv->wep_key_len[sme->key_idx] = sme->key_len;
-                       memcpy(priv->wep_key[sme->key_idx], sme->key,
-                              sme->key_len);
-
-                       wilc_set_wep_default_keyid(vif, sme->key_idx);
-                       wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len,
-                                                sme->key_idx);
-               } else if (cipher_group == WLAN_CIPHER_SUITE_WEP104) {
-                       security = WILC_FW_SEC_WEP_EXTENDED;
-
-                       priv->wep_key_len[sme->key_idx] = sme->key_len;
-                       memcpy(priv->wep_key[sme->key_idx], sme->key,
-                              sme->key_len);
-
-                       wilc_set_wep_default_keyid(vif, sme->key_idx);
-                       wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len,
-                                                sme->key_idx);
-               } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
+               if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
                        if (cipher_group == WLAN_CIPHER_SUITE_TKIP)
                                security = WILC_FW_SEC_WPA2_TKIP;
                        else
@@ -373,8 +353,14 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
                auth_type = WILC_FW_AUTH_OPEN_SYSTEM;
                break;
 
-       case NL80211_AUTHTYPE_SHARED_KEY:
-               auth_type = WILC_FW_AUTH_SHARED_KEY;
+       case NL80211_AUTHTYPE_SAE:
+               auth_type = WILC_FW_AUTH_SAE;
+               if (sme->ssid_len) {
+                       memcpy(vif->auth.ssid.ssid, sme->ssid, sme->ssid_len);
+                       vif->auth.ssid.ssid_len = sme->ssid_len;
+               }
+               vif->auth.key_mgmt_suite = cpu_to_be32(sme->crypto.akm_suites[0]);
+               ether_addr_copy(vif->auth.bssid, sme->bssid);
                break;
 
        default:
@@ -384,6 +370,10 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
        if (sme->crypto.n_akm_suites) {
                if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X)
                        auth_type = WILC_FW_AUTH_IEEE8021;
+               else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_PSK_SHA256)
+                       auth_type = WILC_FW_AUTH_OPEN_SYSTEM_SHA256;
+               else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X_SHA256)
+                       auth_type = WILC_FW_AUTH_IEE8021X_SHA256;
        }
 
        if (wfi_drv->usr_scan_req.scan_result) {
@@ -427,6 +417,13 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
        wfi_drv->conn_info.arg = priv;
        wfi_drv->conn_info.param = join_params;
 
+       if (sme->mfp == NL80211_MFP_OPTIONAL)
+               mfp_type = WILC_FW_MFP_OPTIONAL;
+       else if (sme->mfp == NL80211_MFP_REQUIRED)
+               mfp_type = WILC_FW_MFP_REQUIRED;
+
+       wfi_drv->conn_info.mfp_type = mfp_type;
+
        ret = wilc_set_join_req(vif, bss->bssid, sme->ie, sme->ie_len);
        if (ret) {
                netdev_err(dev, "wilc_set_join_req(): Error\n");
@@ -487,14 +484,6 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev,
        return ret;
 }
 
-static inline void wilc_wfi_cfg_copy_wep_info(struct wilc_priv *priv,
-                                             u8 key_index,
-                                             struct key_params *params)
-{
-       priv->wep_key_len[key_index] = params->key_len;
-       memcpy(priv->wep_key[key_index], params->key, params->key_len);
-}
-
 static int wilc_wfi_cfg_allocate_wpa_entry(struct wilc_priv *priv, u8 idx)
 {
        if (!priv->wilc_gtk[idx]) {
@@ -514,6 +503,18 @@ static int wilc_wfi_cfg_allocate_wpa_entry(struct wilc_priv *priv, u8 idx)
        return 0;
 }
 
+static int wilc_wfi_cfg_allocate_wpa_igtk_entry(struct wilc_priv *priv, u8 idx)
+{
+       idx -= 4;
+       if (!priv->wilc_igtk[idx]) {
+               priv->wilc_igtk[idx] = kzalloc(sizeof(*priv->wilc_igtk[idx]),
+                                              GFP_KERNEL);
+               if (!priv->wilc_igtk[idx])
+                       return -ENOMEM;
+       }
+       return 0;
+}
+
 static int wilc_wfi_cfg_copy_wpa_info(struct wilc_wfi_key *key_info,
                                      struct key_params *params)
 {
@@ -550,35 +551,9 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
        u8 op_mode;
        struct wilc_vif *vif = netdev_priv(netdev);
        struct wilc_priv *priv = &vif->priv;
+       struct wilc_wfi_key *key;
 
        switch (params->cipher) {
-       case WLAN_CIPHER_SUITE_WEP40:
-       case WLAN_CIPHER_SUITE_WEP104:
-               if (priv->wdev.iftype == NL80211_IFTYPE_AP) {
-                       wilc_wfi_cfg_copy_wep_info(priv, key_index, params);
-
-                       if (params->cipher == WLAN_CIPHER_SUITE_WEP40)
-                               mode = WILC_FW_SEC_WEP;
-                       else
-                               mode = WILC_FW_SEC_WEP_EXTENDED;
-
-                       ret = wilc_add_wep_key_bss_ap(vif, params->key,
-                                                     params->key_len,
-                                                     key_index, mode,
-                                                     WILC_FW_AUTH_OPEN_SYSTEM);
-                       break;
-               }
-               if (memcmp(params->key, priv->wep_key[key_index],
-                          params->key_len)) {
-                       wilc_wfi_cfg_copy_wep_info(priv, key_index, params);
-
-                       ret = wilc_add_wep_key_bss_sta(vif, params->key,
-                                                      params->key_len,
-                                                      key_index);
-               }
-
-               break;
-
        case WLAN_CIPHER_SUITE_TKIP:
        case WLAN_CIPHER_SUITE_CCMP:
                if (priv->wdev.iftype == NL80211_IFTYPE_AP ||
@@ -640,6 +615,26 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                                           key_index);
 
                break;
+       case WLAN_CIPHER_SUITE_AES_CMAC:
+               ret = wilc_wfi_cfg_allocate_wpa_igtk_entry(priv, key_index);
+               if (ret)
+                       return -ENOMEM;
+
+               key = priv->wilc_igtk[key_index - 4];
+               ret = wilc_wfi_cfg_copy_wpa_info(key, params);
+               if (ret)
+                       return -ENOMEM;
+
+               if (priv->wdev.iftype == NL80211_IFTYPE_AP ||
+                   priv->wdev.iftype == NL80211_IFTYPE_P2P_GO)
+                       op_mode = WILC_AP_MODE;
+               else
+                       op_mode = WILC_STATION_MODE;
+
+               ret = wilc_add_igtk(vif, params->key, keylen, params->seq,
+                                   params->seq_len, mac_addr, op_mode,
+                                   key_index);
+               break;
 
        default:
                netdev_err(netdev, "%s: Unsupported cipher\n", __func__);
@@ -657,30 +652,34 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
        struct wilc_vif *vif = netdev_priv(netdev);
        struct wilc_priv *priv = &vif->priv;
 
-       if (priv->wilc_gtk[key_index]) {
-               kfree(priv->wilc_gtk[key_index]->key);
-               priv->wilc_gtk[key_index]->key = NULL;
-               kfree(priv->wilc_gtk[key_index]->seq);
-               priv->wilc_gtk[key_index]->seq = NULL;
-
-               kfree(priv->wilc_gtk[key_index]);
-               priv->wilc_gtk[key_index] = NULL;
-       }
-
-       if (priv->wilc_ptk[key_index]) {
-               kfree(priv->wilc_ptk[key_index]->key);
-               priv->wilc_ptk[key_index]->key = NULL;
-               kfree(priv->wilc_ptk[key_index]->seq);
-               priv->wilc_ptk[key_index]->seq = NULL;
-               kfree(priv->wilc_ptk[key_index]);
-               priv->wilc_ptk[key_index] = NULL;
-       }
-
-       if (key_index <= 3 && priv->wep_key_len[key_index]) {
-               memset(priv->wep_key[key_index], 0,
-                      priv->wep_key_len[key_index]);
-               priv->wep_key_len[key_index] = 0;
-               wilc_remove_wep_key(vif, key_index);
+       if (!pairwise && (key_index == 4 || key_index == 5)) {
+               key_index -= 4;
+               if (priv->wilc_igtk[key_index]) {
+                       kfree(priv->wilc_igtk[key_index]->key);
+                       priv->wilc_igtk[key_index]->key = NULL;
+                       kfree(priv->wilc_igtk[key_index]->seq);
+                       priv->wilc_igtk[key_index]->seq = NULL;
+                       kfree(priv->wilc_igtk[key_index]);
+                       priv->wilc_igtk[key_index] = NULL;
+               }
+       } else {
+               if (priv->wilc_gtk[key_index]) {
+                       kfree(priv->wilc_gtk[key_index]->key);
+                       priv->wilc_gtk[key_index]->key = NULL;
+                       kfree(priv->wilc_gtk[key_index]->seq);
+                       priv->wilc_gtk[key_index]->seq = NULL;
+
+                       kfree(priv->wilc_gtk[key_index]);
+                       priv->wilc_gtk[key_index] = NULL;
+               }
+               if (priv->wilc_ptk[key_index]) {
+                       kfree(priv->wilc_ptk[key_index]->key);
+                       priv->wilc_ptk[key_index]->key = NULL;
+                       kfree(priv->wilc_ptk[key_index]->seq);
+                       priv->wilc_ptk[key_index]->seq = NULL;
+                       kfree(priv->wilc_ptk[key_index]);
+                       priv->wilc_ptk[key_index] = NULL;
+               }
        }
 
        return 0;
@@ -695,11 +694,20 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
        struct  key_params key_params;
 
        if (!pairwise) {
-               key_params.key = priv->wilc_gtk[key_index]->key;
-               key_params.cipher = priv->wilc_gtk[key_index]->cipher;
-               key_params.key_len = priv->wilc_gtk[key_index]->key_len;
-               key_params.seq = priv->wilc_gtk[key_index]->seq;
-               key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;
+               if (key_index == 4 || key_index == 5) {
+                       key_index -= 4;
+                       key_params.key = priv->wilc_igtk[key_index]->key;
+                       key_params.cipher = priv->wilc_igtk[key_index]->cipher;
+                       key_params.key_len = priv->wilc_igtk[key_index]->key_len;
+                       key_params.seq = priv->wilc_igtk[key_index]->seq;
+                       key_params.seq_len = priv->wilc_igtk[key_index]->seq_len;
+               } else {
+                       key_params.key = priv->wilc_gtk[key_index]->key;
+                       key_params.cipher = priv->wilc_gtk[key_index]->cipher;
+                       key_params.key_len = priv->wilc_gtk[key_index]->key_len;
+                       key_params.seq = priv->wilc_gtk[key_index]->seq;
+                       key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;
+               }
        } else {
                key_params.key = priv->wilc_ptk[key_index]->key;
                key_params.cipher = priv->wilc_ptk[key_index]->cipher;
@@ -713,14 +721,19 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
        return 0;
 }
 
+/* wiphy_new_nm() will WARNON if not present */
 static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,
                           u8 key_index, bool unicast, bool multicast)
 {
-       struct wilc_vif *vif = netdev_priv(netdev);
+       return 0;
+}
 
-       wilc_set_wep_default_keyid(vif, key_index);
+static int set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev,
+                               u8 key_index)
+{
+       struct wilc_vif *vif = netdev_priv(netdev);
 
-       return 0;
+       return wilc_set_default_mgmt_key_index(vif, key_index);
 }
 
 static int get_station(struct wiphy *wiphy, struct net_device *dev,
@@ -977,6 +990,18 @@ static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u32 len, u8 sta_ch)
        }
 }
 
+bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size)
+{
+       struct wilc *wl = vif->wilc;
+       struct wilc_priv *priv = &vif->priv;
+       int freq, ret;
+
+       freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ);
+       ret = cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);
+
+       return ret;
+}
+
 void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)
 {
        struct wilc *wl = vif->wilc;
@@ -1162,8 +1187,14 @@ static int mgmt_tx(struct wiphy *wiphy,
                goto out_txq_add_pkt;
        }
 
-       if (!ieee80211_is_public_action((struct ieee80211_hdr *)buf, len))
+       if (!ieee80211_is_public_action((struct ieee80211_hdr *)buf, len)) {
+               if (chan)
+                       wilc_set_mac_chnl_num(vif, chan->hw_value);
+               else
+                       wilc_set_mac_chnl_num(vif, vif->wilc->op_ch);
+
                goto out_set_timeout;
+       }
 
        d = (struct wilc_p2p_pub_act_frame *)(&mgmt->u.action);
        if (d->oui_type != WLAN_OUI_TYPE_WFA_P2P ||
@@ -1230,6 +1261,7 @@ void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy,
        struct wilc_vif *vif = netdev_priv(wdev->netdev);
        u32 presp_bit = BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
        u32 action_bit = BIT(IEEE80211_STYPE_ACTION >> 4);
+       u32 pauth_bit = BIT(IEEE80211_STYPE_AUTH >> 4);
 
        if (wl->initialized) {
                bool prev = vif->mgmt_reg_stypes & presp_bit;
@@ -1243,10 +1275,26 @@ void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy,
 
                if (now != prev)
                        wilc_frame_register(vif, IEEE80211_STYPE_ACTION, now);
+
+               prev = vif->mgmt_reg_stypes & pauth_bit;
+               now = upd->interface_stypes & pauth_bit;
+               if (now != prev)
+                       wilc_frame_register(vif, IEEE80211_STYPE_AUTH, now);
        }
 
        vif->mgmt_reg_stypes =
-               upd->interface_stypes & (presp_bit | action_bit);
+               upd->interface_stypes & (presp_bit | action_bit | pauth_bit);
+}
+
+static int external_auth(struct wiphy *wiphy, struct net_device *dev,
+                        struct cfg80211_external_auth_params *auth)
+{
+       struct wilc_vif *vif = netdev_priv(dev);
+
+       if (auth->status == WLAN_STATUS_SUCCESS)
+               wilc_set_external_auth_param(vif, auth);
+
+       return 0;
 }
 
 static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
@@ -1647,6 +1695,7 @@ static const struct cfg80211_ops wilc_cfg80211_ops = {
        .del_key = del_key,
        .get_key = get_key,
        .set_default_key = set_default_key,
+       .set_default_mgmt_key = set_default_mgmt_key,
        .add_virtual_intf = add_virtual_intf,
        .del_virtual_intf = del_virtual_intf,
        .change_virtual_intf = change_virtual_intf,
@@ -1662,6 +1711,7 @@ static const struct cfg80211_ops wilc_cfg80211_ops = {
        .change_bss = change_bss,
        .set_wiphy_params = set_wiphy_params,
 
+       .external_auth = external_auth,
        .set_pmksa = set_pmksa,
        .del_pmksa = del_pmksa,
        .flush_pmksa = flush_pmksa,
@@ -1804,7 +1854,7 @@ struct wilc *wilc_create_wiphy(struct device *dev)
                                BIT(NL80211_IFTYPE_P2P_GO) |
                                BIT(NL80211_IFTYPE_P2P_CLIENT);
        wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
-
+       wiphy->features |= NL80211_FEATURE_SAE;
        set_wiphy_dev(wiphy, dev);
        wl->wiphy = wiphy;
        ret = wiphy_register(wiphy);
index 1114530..5c5cac4 100644 (file)
@@ -41,21 +41,23 @@ struct wilc_drv_handler {
        u8 mode;
 } __packed;
 
-struct wilc_wep_key {
-       u8 index;
+struct wilc_sta_wpa_ptk {
+       u8 mac_addr[ETH_ALEN];
        u8 key_len;
        u8 key[];
 } __packed;
 
-struct wilc_sta_wpa_ptk {
+struct wilc_ap_wpa_ptk {
        u8 mac_addr[ETH_ALEN];
+       u8 index;
        u8 key_len;
        u8 key[];
 } __packed;
 
-struct wilc_ap_wpa_ptk {
-       u8 mac_addr[ETH_ALEN];
+struct wilc_wpa_igtk {
        u8 index;
+       u8 pn_len;
+       u8 pn[6];
        u8 key_len;
        u8 key[];
 } __packed;
@@ -116,4 +118,13 @@ struct wilc_join_bss_param {
                struct wilc_noa_opp_enable opp_en;
        };
 } __packed;
+
+struct wilc_external_auth_param {
+       u8 action;
+       u8 bssid[ETH_ALEN];
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+       u8 ssid_len;
+       __le32 key_mgmt_suites;
+       __le16 status;
+} __packed;
 #endif
index 71b44cf..4038a25 100644 (file)
@@ -271,12 +271,19 @@ error:
 static int wilc_send_connect_wid(struct wilc_vif *vif)
 {
        int result = 0;
-       struct wid wid_list[4];
+       struct wid wid_list[5];
        u32 wid_cnt = 0;
        struct host_if_drv *hif_drv = vif->hif_drv;
        struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
        struct wilc_join_bss_param *bss_param = conn_attr->param;
 
+
+        wid_list[wid_cnt].id = WID_SET_MFP;
+        wid_list[wid_cnt].type = WID_CHAR;
+        wid_list[wid_cnt].size = sizeof(char);
+        wid_list[wid_cnt].val = (s8 *)&conn_attr->mfp_type;
+        wid_cnt++;
+
        wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
        wid_list[wid_cnt].type = WID_BIN_DATA;
        wid_list[wid_cnt].val = conn_attr->req_ies;
@@ -306,7 +313,10 @@ static int wilc_send_connect_wid(struct wilc_vif *vif)
                netdev_err(vif->ndev, "failed to send config packet\n");
                goto error;
        } else {
-               hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
+                if (conn_attr->auth_type == WILC_FW_AUTH_SAE)
+                        hif_drv->hif_state = HOST_IF_EXTERNAL_AUTH;
+                else
+                        hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
        }
 
        return 0;
@@ -665,7 +675,12 @@ static void handle_rcvd_gnrl_async_info(struct work_struct *work)
                goto free_msg;
        }
 
-       if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
+
+        if (hif_drv->hif_state == HOST_IF_EXTERNAL_AUTH) {
+                cfg80211_external_auth_request(vif->ndev, &vif->auth,
+                                              GFP_KERNEL);
+                hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
+        } else if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
                host_int_parse_assoc_resp_info(vif, mac_info->status);
        } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) {
                if (hif_drv->hif_state == HOST_IF_CONNECTED) {
@@ -710,7 +725,8 @@ int wilc_disconnect(struct wilc_vif *vif)
        }
 
        if (conn_info->conn_result) {
-               if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
+               if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
+                   hif_drv->hif_state == HOST_IF_EXTERNAL_AUTH)
                        del_timer(&hif_drv->connect_timer);
 
                conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0,
@@ -986,6 +1002,31 @@ void wilc_set_wowlan_trigger(struct wilc_vif *vif, bool enabled)
                pr_err("Failed to send wowlan trigger config packet\n");
 }
 
+int wilc_set_external_auth_param(struct wilc_vif *vif,
+                                struct cfg80211_external_auth_params *auth)
+{
+       int ret;
+       struct wid wid;
+       struct wilc_external_auth_param *param;
+
+       wid.id = WID_EXTERNAL_AUTH_PARAM;
+       wid.type = WID_BIN_DATA;
+       wid.size = sizeof(*param);
+       param = kzalloc(sizeof(*param), GFP_KERNEL);
+       if (!param)
+               return -EINVAL;
+
+       wid.val = (u8 *)param;
+       param->action = auth->action;
+       ether_addr_copy(param->bssid, auth->bssid);
+       memcpy(param->ssid, auth->ssid.ssid, auth->ssid.ssid_len);
+       param->ssid_len = auth->ssid.ssid_len;
+       ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+
+       kfree(param);
+       return ret;
+}
+
 static void handle_scan_timer(struct work_struct *work)
 {
        struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -1038,108 +1079,6 @@ static void timer_connect_cb(struct timer_list *t)
                kfree(msg);
 }
 
-int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
-{
-       struct wid wid;
-       int result;
-
-       wid.id = WID_REMOVE_WEP_KEY;
-       wid.type = WID_STR;
-       wid.size = sizeof(char);
-       wid.val = &index;
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
-       if (result)
-               netdev_err(vif->ndev,
-                          "Failed to send remove wep key config packet\n");
-       return result;
-}
-
-int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
-{
-       struct wid wid;
-       int result;
-
-       wid.id = WID_KEY_ID;
-       wid.type = WID_CHAR;
-       wid.size = sizeof(char);
-       wid.val = &index;
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
-       if (result)
-               netdev_err(vif->ndev,
-                          "Failed to send wep default key config packet\n");
-
-       return result;
-}
-
-int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
-                            u8 index)
-{
-       struct wid wid;
-       int result;
-       struct wilc_wep_key *wep_key;
-
-       wid.id = WID_ADD_WEP_KEY;
-       wid.type = WID_STR;
-       wid.size = sizeof(*wep_key) + len;
-       wep_key = kzalloc(wid.size, GFP_KERNEL);
-       if (!wep_key)
-               return -ENOMEM;
-
-       wid.val = (u8 *)wep_key;
-
-       wep_key->index = index;
-       wep_key->key_len = len;
-       memcpy(wep_key->key, key, len);
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
-       if (result)
-               netdev_err(vif->ndev,
-                          "Failed to add wep key config packet\n");
-
-       kfree(wep_key);
-       return result;
-}
-
-int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
-                           u8 index, u8 mode, enum authtype auth_type)
-{
-       struct wid wid_list[3];
-       int result;
-       struct wilc_wep_key *wep_key;
-
-       wid_list[0].id = WID_11I_MODE;
-       wid_list[0].type = WID_CHAR;
-       wid_list[0].size = sizeof(char);
-       wid_list[0].val = &mode;
-
-       wid_list[1].id = WID_AUTH_TYPE;
-       wid_list[1].type = WID_CHAR;
-       wid_list[1].size = sizeof(char);
-       wid_list[1].val = (s8 *)&auth_type;
-
-       wid_list[2].id = WID_WEP_KEY_VALUE;
-       wid_list[2].type = WID_STR;
-       wid_list[2].size = sizeof(*wep_key) + len;
-       wep_key = kzalloc(wid_list[2].size, GFP_KERNEL);
-       if (!wep_key)
-               return -ENOMEM;
-
-       wid_list[2].val = (u8 *)wep_key;
-
-       wep_key->index = index;
-       wep_key->key_len = len;
-       memcpy(wep_key->key, key, len);
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-                                     ARRAY_SIZE(wid_list));
-       if (result)
-               netdev_err(vif->ndev,
-                          "Failed to add wep ap key config packet\n");
-
-       kfree(wep_key);
-       return result;
-}
-
 int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
                 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
                 u8 mode, u8 cipher_mode, u8 index)
@@ -1211,6 +1150,36 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
        return result;
 }
 
+int wilc_add_igtk(struct wilc_vif *vif, const u8 *igtk, u8 igtk_key_len,
+                 const u8 *pn, u8 pn_len, const u8 *mac_addr, u8 mode, u8 index)
+{
+       int result = 0;
+       u8 t_key_len = igtk_key_len;
+       struct wid wid;
+       struct wilc_wpa_igtk *key_buf;
+
+       key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
+       if (!key_buf)
+               return -ENOMEM;
+
+       key_buf->index = index;
+
+       memcpy(&key_buf->pn[0], pn, pn_len);
+       key_buf->pn_len = pn_len;
+
+       memcpy(&key_buf->key[0], igtk, igtk_key_len);
+       key_buf->key_len = t_key_len;
+
+       wid.id = WID_ADD_IGTK;
+       wid.type = WID_STR;
+       wid.size = sizeof(*key_buf) + t_key_len;
+       wid.val = (s8 *)key_buf;
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       kfree(key_buf);
+
+       return result;
+}
+
 int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
                    u8 index, u32 key_rsc_len, const u8 *key_rsc,
                    const u8 *rx_mic, const u8 *tx_mic, u8 mode,
@@ -1749,6 +1718,10 @@ void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
                reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
                break;
 
+        case IEEE80211_STYPE_AUTH:
+                reg_frame.reg_id = WILC_FW_AUTH_REQ_IDX;
+                break;
+
        default:
                break;
        }
@@ -1996,3 +1969,20 @@ int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
 
        return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
 }
+
+int wilc_set_default_mgmt_key_index(struct wilc_vif *vif, u8 index)
+{
+        struct wid wid;
+        int result;
+
+        wid.id = WID_DEFAULT_MGMT_KEY_ID;
+        wid.type = WID_CHAR;
+        wid.size = sizeof(char);
+        wid.val = &index;
+        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+        if (result)
+                netdev_err(vif->ndev,
+                           "Failed to send default mgmt key index\n");
+
+        return result;
+}
index 77616fc..d8dd94d 100644 (file)
@@ -47,6 +47,7 @@ enum host_if_state {
        HOST_IF_WAITING_CONN_RESP       = 3,
        HOST_IF_CONNECTED               = 4,
        HOST_IF_P2P_LISTEN              = 5,
+       HOST_IF_EXTERNAL_AUTH           = 6,
        HOST_IF_FORCE_32BIT             = 0xFFFFFFFF
 };
 
@@ -107,6 +108,7 @@ struct wilc_conn_info {
        u8 bssid[ETH_ALEN];
        u8 security;
        enum authtype auth_type;
+       enum mfptype mfp_type;
        u8 ch;
        u8 *req_ies;
        size_t req_ies_len;
@@ -151,15 +153,12 @@ struct host_if_drv {
 };
 
 struct wilc_vif;
-int wilc_remove_wep_key(struct wilc_vif *vif, u8 index);
-int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index);
-int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
-                            u8 index);
-int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
-                           u8 index, u8 mode, enum authtype auth_type);
 int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
                 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
                 u8 mode, u8 cipher_mode, u8 index);
+int wilc_add_igtk(struct wilc_vif *vif, const u8 *igtk, u8 igtk_key_len,
+                 const u8 *pn, u8 pn_len, const u8 *mac_addr, u8 mode,
+                 u8 index);
 s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
                           u32 *out_val);
 int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
@@ -208,9 +207,12 @@ int wilc_get_vif_idx(struct wilc_vif *vif);
 int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power);
 int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power);
 void wilc_set_wowlan_trigger(struct wilc_vif *vif, bool enabled);
+int wilc_set_external_auth_param(struct wilc_vif *vif,
+                                struct cfg80211_external_auth_params *param);
 void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length);
 void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length);
 void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length);
 void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
                                struct cfg80211_crypto_settings *crypto);
+int wilc_set_default_mgmt_key_index(struct wilc_vif *vif, u8 index);
 #endif
index 3c292e3..fcc4e61 100644 (file)
@@ -835,15 +835,24 @@ void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
        }
 }
 
-void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
+void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size, bool is_auth)
 {
        int srcu_idx;
        struct wilc_vif *vif;
 
        srcu_idx = srcu_read_lock(&wilc->srcu);
        list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+               struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buff;
                u16 type = le16_to_cpup((__le16 *)buff);
                u32 type_bit = BIT(type >> 4);
+               u32 auth_bit = BIT(IEEE80211_STYPE_AUTH >> 4);
+
+               if ((vif->mgmt_reg_stypes & auth_bit &&
+                    ieee80211_is_auth(mgmt->frame_control)) &&
+                   vif->iftype == WILC_STATION_MODE && is_auth) {
+                       wilc_wfi_mgmt_frame_rx(vif, buff, size);
+                       break;
+               }
 
                if (vif->priv.p2p_listen_state &&
                    vif->mgmt_reg_stypes & type_bit)
index a067274..822e65d 100644 (file)
@@ -45,12 +45,6 @@ struct wilc_wfi_key {
        u32 cipher;
 };
 
-struct wilc_wfi_wep_key {
-       u8 *key;
-       u8 key_len;
-       u8 key_idx;
-};
-
 struct sta_info {
        u8 sta_associated_bss[WILC_MAX_NUM_STA][ETH_ALEN];
 };
@@ -63,8 +57,6 @@ struct wilc_wfi_p2p_listen_params {
 };
 
 static const u32 wilc_cipher_suites[] = {
-       WLAN_CIPHER_SUITE_WEP40,
-       WLAN_CIPHER_SUITE_WEP104,
        WLAN_CIPHER_SUITE_TKIP,
        WLAN_CIPHER_SUITE_CCMP,
        WLAN_CIPHER_SUITE_AES_CMAC
@@ -132,13 +124,12 @@ struct wilc_priv {
        struct net_device *dev;
        struct host_if_drv *hif_drv;
        struct wilc_pmkid_attr pmkid_list;
-       u8 wep_key[4][WLAN_KEY_LEN_WEP104];
-       u8 wep_key_len[4];
 
        /* The real interface that the monitor is on */
        struct net_device *real_ndev;
        struct wilc_wfi_key *wilc_gtk[WILC_MAX_NUM_STA];
        struct wilc_wfi_key *wilc_ptk[WILC_MAX_NUM_STA];
+       struct wilc_wfi_key *wilc_igtk[2];
        u8 wilc_groupkey;
 
        /* mutexes */
@@ -195,6 +186,7 @@ struct wilc_vif {
        struct wilc_priv priv;
        struct list_head list;
        struct cfg80211_bss *bss;
+       struct cfg80211_external_auth_params auth;
 };
 
 struct wilc_tx_queue_status {
@@ -288,7 +280,7 @@ struct wilc_wfi_mon_priv {
 void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset);
 void wilc_mac_indicate(struct wilc *wilc);
 void wilc_netdev_cleanup(struct wilc *wilc);
-void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size);
+void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size, bool is_auth);
 void wilc_wlan_set_bssid(struct net_device *wilc_netdev, const u8 *bssid,
                         u8 mode);
 struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
index 18420e9..2ae8dd3 100644 (file)
@@ -191,11 +191,11 @@ static void wilc_wlan_power(struct wilc *wilc, bool on)
                /* assert ENABLE: */
                gpiod_set_value(gpios->enable, 1);
                mdelay(5);
-               /* deassert RESET: */
-               gpiod_set_value(gpios->reset, 0);
-       } else {
                /* assert RESET: */
                gpiod_set_value(gpios->reset, 1);
+       } else {
+               /* deassert RESET: */
+               gpiod_set_value(gpios->reset, 0);
                /* deassert ENABLE: */
                gpiod_set_value(gpios->enable, 0);
        }
index 48441f0..f3f504d 100644 (file)
@@ -968,7 +968,8 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
 
                if (pkt_offset & IS_MANAGMEMENT) {
                        buff_ptr += HOST_HDR_OFFSET;
-                       wilc_wfi_mgmt_rx(wilc, buff_ptr, pkt_len);
+                       wilc_wfi_mgmt_rx(wilc, buff_ptr, pkt_len,
+                                        pkt_offset & IS_MGMT_AUTH_PKT);
                } else {
                        if (!is_cfg_packet) {
                                wilc_frmw_to_host(wilc, buff_ptr, pkt_len,
index eb79781..b45e727 100644 (file)
 #define IS_MANAGMEMENT         0x100
 #define IS_MANAGMEMENT_CALLBACK        0x080
 #define IS_MGMT_STATUS_SUCCES  0x040
+#define IS_MGMT_AUTH_PKT       0x010
 
 #define WILC_WID_TYPE          GENMASK(15, 12)
 #define WILC_VMM_ENTRY_FULL_RETRY      1
@@ -423,6 +424,7 @@ int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc);
 netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev);
 
 void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size);
+bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size);
 void host_wakeup_notify(struct wilc *wilc);
 void host_sleep_notify(struct wilc *wilc);
 void chip_allow_sleep(struct wilc *wilc);
index 6eb7eb4..df2f5a6 100644 (file)
@@ -85,7 +85,16 @@ enum authtype {
        WILC_FW_AUTH_OPEN_SYSTEM = 1,
        WILC_FW_AUTH_SHARED_KEY = 2,
        WILC_FW_AUTH_ANY = 3,
-       WILC_FW_AUTH_IEEE8021 = 5
+       WILC_FW_AUTH_IEEE8021 = 5,
+       WILC_FW_AUTH_SAE = 7,
+       WILC_FW_AUTH_IEE8021X_SHA256 = 9,
+       WILC_FW_AUTH_OPEN_SYSTEM_SHA256 = 13
+};
+
+enum mfptype {
+       WILC_FW_MFP_NONE = 0x0,
+       WILC_FW_MFP_OPTIONAL = 0x1,
+       WILC_FW_MFP_REQUIRED = 0x2
 };
 
 enum site_survey {
@@ -176,7 +185,8 @@ enum {
 
 enum {
        WILC_FW_ACTION_FRM_IDX = 0,
-       WILC_FW_PROBE_REQ_IDX = 1
+       WILC_FW_PROBE_REQ_IDX = 1,
+       WILC_FW_AUTH_REQ_IDX = 2
 };
 
 enum wid_type {
@@ -657,6 +667,9 @@ enum {
        WID_LOG_TERMINAL_SWITCH         = 0x00CD,
        WID_TX_POWER                    = 0x00CE,
        WID_WOWLAN_TRIGGER              = 0X00CF,
+       WID_SET_MFP                     = 0x00D0,
+
+       WID_DEFAULT_MGMT_KEY_ID         = 0x00D2,
        /*  EMAC Short WID list */
        /*  RTS Threshold */
        /*
@@ -746,6 +759,7 @@ enum {
        WID_REMOVE_KEY                  = 0x301E,
        WID_ASSOC_REQ_INFO              = 0x301F,
        WID_ASSOC_RES_INFO              = 0x3020,
+       WID_ADD_IGTK                    = 0x3022,
        WID_MANUFACTURER                = 0x3026, /* Added for CAPI tool */
        WID_MODEL_NAME                  = 0x3027, /* Added for CAPI tool */
        WID_MODEL_NUM                   = 0x3028, /* Added for CAPI tool */
@@ -789,7 +803,7 @@ enum {
        WID_ADD_BEACON                  = 0x408a,
 
        WID_SETUP_MULTICAST_FILTER      = 0x408b,
-
+       WID_EXTERNAL_AUTH_PARAM         = 0x408d,
        /* Miscellaneous WIDs */
        WID_ALL                         = 0x7FFE,
        WID_MAX                         = 0xFFFF
index 87e98ab..1f57a00 100644 (file)
@@ -1643,38 +1643,34 @@ static void authenticate_timeout(struct timer_list *t)
 /*===========================================================================*/
 static int parse_addr(char *in_str, UCHAR *out)
 {
+       int i, k;
        int len;
-       int i, j, k;
-       int status;
 
        if (in_str == NULL)
                return 0;
-       if ((len = strlen(in_str)) < 2)
+       len = strnlen(in_str, ADDRLEN * 2 + 1) - 1;
+       if (len < 1)
                return 0;
        memset(out, 0, ADDRLEN);
 
-       status = 1;
-       j = len - 1;
-       if (j > 12)
-               j = 12;
        i = 5;
 
-       while (j > 0) {
-               if ((k = hex_to_bin(in_str[j--])) != -1)
+       while (len > 0) {
+               if ((k = hex_to_bin(in_str[len--])) != -1)
                        out[i] = k;
                else
                        return 0;
 
-               if (j == 0)
+               if (len == 0)
                        break;
-               if ((k = hex_to_bin(in_str[j--])) != -1)
+               if ((k = hex_to_bin(in_str[len--])) != -1)
                        out[i] += k << 4;
                else
                        return 0;
                if (!i--)
                        break;
        }
-       return status;
+       return 1;
 }
 
 /*===========================================================================*/
index 901cdfe..0b1bc04 100644 (file)
@@ -329,8 +329,8 @@ static ssize_t rtl_debugfs_set_write_h2c(struct file *filp,
 
        tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count);
 
-       if (!buffer || copy_from_user(tmp, buffer, tmp_len))
-               return count;
+       if (copy_from_user(tmp, buffer, tmp_len))
+               return -EFAULT;
 
        tmp[tmp_len] = '\0';
 
@@ -340,8 +340,8 @@ static ssize_t rtl_debugfs_set_write_h2c(struct file *filp,
                         &h2c_data[4], &h2c_data[5],
                         &h2c_data[6], &h2c_data[7]);
 
-       if (h2c_len <= 0)
-               return count;
+       if (h2c_len == 0)
+               return -EINVAL;
 
        for (i = 0; i < h2c_len; i++)
                h2c_data_packed[i] = (u8)h2c_data[i];
index 1a52ff5..7cde6bc 100644 (file)
@@ -269,11 +269,7 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v)
        for (i = 0 ; i < buf_size ; i += 8) {
                if (i % page_size == 0)
                        seq_printf(m, "PAGE %d\n", (i + offset) / page_size);
-               seq_printf(m, "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
-                          *(buf + i), *(buf + i + 1),
-                          *(buf + i + 2), *(buf + i + 3),
-                          *(buf + i + 4), *(buf + i + 5),
-                          *(buf + i + 6), *(buf + i + 7));
+               seq_printf(m, "%8ph\n", buf + i);
        }
        vfree(buf);
 
index efabd5b..a44b181 100644 (file)
@@ -1383,9 +1383,12 @@ void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
 void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
                            bool hw_scan)
 {
-       struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+       struct rtw_vif *rtwvif = vif ? (struct rtw_vif *)vif->drv_priv : NULL;
        u32 config = 0;
 
+       if (!rtwvif)
+               return;
+
        clear_bit(RTW_FLAG_SCANNING, rtwdev->flags);
        clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
 
index 93cce44..993bd6b 100644 (file)
@@ -2701,7 +2701,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = {
        {0x953, BIT(1), RTW_REG_DOMAIN_MAC8},
 };
 
-struct rtw_chip_info rtw8723d_hw_spec = {
+const struct rtw_chip_info rtw8723d_hw_spec = {
        .ops = &rtw8723d_ops,
        .id = RTW_CHIP_TYPE_8723D,
        .fw_name = "rtw88/rtw8723d_fw.bin",
index 41d3517..4641f6e 100644 (file)
@@ -72,6 +72,8 @@ struct rtw8723d_efuse {
        struct rtw8723de_efuse e;
 };
 
+extern const struct rtw_chip_info rtw8723d_hw_spec;
+
 /* phy status page0 */
 #define GET_PHY_STAT_P0_PWDB(phy_stat)                                         \
        le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
index 2dd6894..abbaafa 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include "pci.h"
-#include "rtw8723de.h"
+#include "rtw8723d.h"
 
 static const struct pci_device_id rtw_8723de_id_table[] = {
        {
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.h b/drivers/net/wireless/realtek/rtw88/rtw8723de.h
deleted file mode 100644 (file)
index 2b48948..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright(c) 2018-2019  Realtek Corporation
- */
-
-#ifndef __RTW_8723DE_H_
-#define __RTW_8723DE_H_
-
-extern struct rtw_chip_info rtw8723d_hw_spec;
-
-#endif
index ffee39e..42841f5 100644 (file)
@@ -1877,7 +1877,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8821c[] = {
        {0x60A, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
 };
 
-struct rtw_chip_info rtw8821c_hw_spec = {
+const struct rtw_chip_info rtw8821c_hw_spec = {
        .ops = &rtw8821c_ops,
        .id = RTW_CHIP_TYPE_8821C,
        .fw_name = "rtw88/rtw8821c_fw.bin",
index d9fbddd..2698801 100644 (file)
@@ -84,6 +84,8 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
        rtw_write32_mask(rtwdev, addr + 0x200, mask, data);
 }
 
+extern const struct rtw_chip_info rtw8821c_hw_spec;
+
 #define rtw_write32s_mask(rtwdev, addr, mask, data)                           \
        do {                                                                   \
                BUILD_BUG_ON((addr) < 0xC00 || (addr) >= 0xD00);               \
index 56d22f9..f3d971f 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include "pci.h"
-#include "rtw8821ce.h"
+#include "rtw8821c.h"
 
 static const struct pci_device_id rtw_8821ce_id_table[] = {
        {
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821ce.h b/drivers/net/wireless/realtek/rtw88/rtw8821ce.h
deleted file mode 100644 (file)
index 54142ac..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright(c) 2018-2019  Realtek Corporation
- */
-
-#ifndef __RTW_8821CE_H_
-#define __RTW_8821CE_H_
-
-extern struct rtw_chip_info rtw8821c_hw_spec;
-
-#endif
index dccd722..3218488 100644 (file)
@@ -2497,7 +2497,7 @@ static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = {
        [EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0},
 };
 
-struct rtw_chip_info rtw8822b_hw_spec = {
+const struct rtw_chip_info rtw8822b_hw_spec = {
        .ops = &rtw8822b_ops,
        .id = RTW_CHIP_TYPE_8822B,
        .fw_name = "rtw88/rtw8822b_fw.bin",
index 3fff8b8..01d3644 100644 (file)
@@ -187,4 +187,6 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
 #define REG_ANTWT      0x1904
 #define REG_IQKFAILMSK 0x1bf0
 
+extern const struct rtw_chip_info rtw8822b_hw_spec;
+
 #endif
index 62ee7e6..4994950 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include "pci.h"
-#include "rtw8822be.h"
+#include "rtw8822b.h"
 
 static const struct pci_device_id rtw_8822be_id_table[] = {
        {
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822be.h b/drivers/net/wireless/realtek/rtw88/rtw8822be.h
deleted file mode 100644 (file)
index 6668460..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright(c) 2018-2019  Realtek Corporation
- */
-
-#ifndef __RTW_8822BE_H_
-#define __RTW_8822BE_H_
-
-extern struct rtw_chip_info rtw8822b_hw_spec;
-
-#endif
index c043b5c..09f9e4a 100644 (file)
@@ -5310,7 +5310,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822c[] = {
        {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
 };
 
-struct rtw_chip_info rtw8822c_hw_spec = {
+const struct rtw_chip_info rtw8822c_hw_spec = {
        .ops = &rtw8822c_ops,
        .id = RTW_CHIP_TYPE_8822C,
        .fw_name = "rtw88/rtw8822c_fw.bin",
index 8201955..479d5d7 100644 (file)
@@ -118,6 +118,8 @@ enum rtw8822c_dpk_one_shot_action {
 void rtw8822c_parse_tbl_dpk(struct rtw_dev *rtwdev,
                            const struct rtw_table *tbl);
 
+extern const struct rtw_chip_info rtw8822c_hw_spec;
+
 #define RTW_DECL_TABLE_DPK(name)                       \
 const struct rtw_table name ## _tbl = {                        \
        .data = name,                                   \
index 3845b13..e26c6bc 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include "pci.h"
-#include "rtw8822ce.h"
+#include "rtw8822c.h"
 
 static const struct pci_device_id rtw_8822ce_id_table[] = {
        {
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.h b/drivers/net/wireless/realtek/rtw88/rtw8822ce.h
deleted file mode 100644 (file)
index fee32d7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright(c) 2018-2019  Realtek Corporation
- */
-
-#ifndef __RTW_8822CE_H_
-#define __RTW_8822CE_H_
-
-extern struct rtw_chip_info rtw8822c_hw_spec;
-
-#endif
index 8a26ade..db3c55f 100644 (file)
@@ -602,11 +602,18 @@ int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
        struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
        struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
        u8 bss_color = vif->bss_conf.he_bss_color.color;
+       u8 bss_mask;
+
+       if (vif->bss_conf.nontransmitted)
+               bss_mask = RTW89_BSSID_MATCH_5_BYTES;
+       else
+               bss_mask = RTW89_BSSID_MATCH_ALL;
 
        FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx);
        FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset);
        FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len);
        FWCMD_SET_ADDR_BSSID_VALID(cmd, bssid_cam->valid);
+       FWCMD_SET_ADDR_BSSID_MASK(cmd, bss_mask);
        FWCMD_SET_ADDR_BSSID_BB_SEL(cmd, bssid_cam->phy_idx);
        FWCMD_SET_ADDR_BSSID_BSS_COLOR(cmd, bss_color);
 
index a3931d3..74a6c47 100644 (file)
@@ -9,6 +9,9 @@
 
 #define RTW89_SEC_CAM_LEN      20
 
+#define RTW89_BSSID_MATCH_ALL GENMASK(5, 0)
+#define RTW89_BSSID_MATCH_5_BYTES GENMASK(4, 0)
+
 static inline void FWCMD_SET_ADDR_IDX(void *cmd, u32 value)
 {
        le32p_replace_bits((__le32 *)(cmd) + 1, value, GENMASK(7, 0));
@@ -309,6 +312,11 @@ static inline void FWCMD_SET_ADDR_BSSID_BB_SEL(void *cmd, u32 value)
        le32p_replace_bits((__le32 *)(cmd) + 13, value, BIT(1));
 }
 
+static inline void FWCMD_SET_ADDR_BSSID_MASK(void *cmd, u32 value)
+{
+       le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(7, 2));
+}
+
 static inline void FWCMD_SET_ADDR_BSSID_BSS_COLOR(void *cmd, u32 value)
 {
        le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(13, 8));
index a6a9057..d2f2a3d 100644 (file)
@@ -1343,6 +1343,47 @@ struct rtw89_vif_rx_stats_iter_data {
        const u8 *bssid;
 };
 
+static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
+                                     struct ieee80211_vif *vif,
+                                     struct sk_buff *skb)
+{
+       struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+       struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data;
+       u8 *pos, *end, type;
+       u16 aid;
+
+       if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) ||
+           rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION ||
+           rtwvif->net_type == RTW89_NET_TYPE_NO_LINK)
+               return;
+
+       type = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_TYPE_MASK);
+       if (type != IEEE80211_TRIGGER_TYPE_BASIC)
+               return;
+
+       end = (u8 *)tf + skb->len;
+       pos = tf->variable;
+
+       while (end - pos >= RTW89_TF_BASIC_USER_INFO_SZ) {
+               aid = RTW89_GET_TF_USER_INFO_AID12(pos);
+               rtw89_debug(rtwdev, RTW89_DBG_TXRX,
+                           "[TF] aid: %d, ul_mcs: %d, rua: %d\n",
+                           aid, RTW89_GET_TF_USER_INFO_UL_MCS(pos),
+                           RTW89_GET_TF_USER_INFO_RUA(pos));
+
+               if (aid == RTW89_TF_PAD)
+                       break;
+
+               if (aid == vif->bss_conf.aid) {
+                       rtwvif->stats.rx_tf_acc++;
+                       rtwdev->stats.rx_tf_acc++;
+                       break;
+               }
+
+               pos += RTW89_TF_BASIC_USER_INFO_SZ;
+       }
+}
+
 static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
                                    struct ieee80211_vif *vif)
 {
@@ -1355,6 +1396,11 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        const u8 *bssid = iter_data->bssid;
 
+       if (ieee80211_is_trigger(hdr->frame_control)) {
+               rtw89_stats_trigger_frame(rtwdev, vif, skb);
+               return;
+       }
+
        if (!ether_addr_equal(vif->bss_conf.bssid, bssid))
                return;
 
@@ -1608,7 +1654,7 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
 
        if (rtwdev->scanning &&
            RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
-               u8 chan = hal->current_channel;
+               u8 chan = hal->current_primary_channel;
                u8 band = hal->current_band_type;
                enum nl80211_band nl_band;
 
@@ -2023,6 +2069,8 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev,
        stats->rx_unicast = 0;
        stats->tx_cnt = 0;
        stats->rx_cnt = 0;
+       stats->rx_tf_periodic = stats->rx_tf_acc;
+       stats->rx_tf_acc = 0;
 
        if (tx_tfc_lv != stats->tx_tfc_lv || rx_tfc_lv != stats->rx_tfc_lv)
                return true;
@@ -2875,7 +2923,10 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
 void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
                              struct ieee80211_vif *vif, bool hw_scan)
 {
-       struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+       struct rtw89_vif *rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL;
+
+       if (!rtwvif)
+               return;
 
        ether_addr_copy(rtwvif->mac_addr, vif->addr);
        rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
@@ -3008,6 +3059,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
        ieee80211_hw_set(hw, SUPPORTS_PS);
        ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
        ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
+       ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
 
        hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
                                     BIT(NL80211_IFTYPE_AP);
index e8a7722..239d47d 100644 (file)
@@ -55,6 +55,16 @@ enum htc_om_channel_width {
 #define RTW89_HTC_MASK_HTC_OM_DL_MU_MIMO_RR BIT(16)
 #define RTW89_HTC_MASK_HTC_OM_UL_MU_DATA_DIS BIT(17)
 
+#define RTW89_TF_PAD GENMASK(11, 0)
+#define RTW89_TF_BASIC_USER_INFO_SZ 6
+
+#define RTW89_GET_TF_USER_INFO_AID12(data)     \
+       le32_get_bits(*((const __le32 *)(data)), GENMASK(11, 0))
+#define RTW89_GET_TF_USER_INFO_RUA(data)       \
+       le32_get_bits(*((const __le32 *)(data)), GENMASK(19, 12))
+#define RTW89_GET_TF_USER_INFO_UL_MCS(data)    \
+       le32_get_bits(*((const __le32 *)(data)), GENMASK(24, 21))
+
 enum rtw89_subband {
        RTW89_CH_2G = 0,
        RTW89_CH_5G_BAND_1 = 1,
@@ -943,6 +953,10 @@ struct rtw89_traffic_stats {
        u32 rx_throughput;
        u32 tx_throughput_raw;
        u32 rx_throughput_raw;
+
+       u32 rx_tf_acc;
+       u32 rx_tf_periodic;
+
        enum rtw89_tfc_lv tx_tfc_lv;
        enum rtw89_tfc_lv rx_tfc_lv;
        struct ewma_tp tx_ewma_tp;
@@ -2550,9 +2564,24 @@ enum rtw89_sar_sources {
        RTW89_SAR_SOURCE_NR,
 };
 
+enum rtw89_sar_subband {
+       RTW89_SAR_2GHZ_SUBBAND,
+       RTW89_SAR_5GHZ_SUBBAND_1_2, /* U-NII-1 and U-NII-2 */
+       RTW89_SAR_5GHZ_SUBBAND_2_E, /* U-NII-2-Extended */
+       RTW89_SAR_5GHZ_SUBBAND_3,   /* U-NII-3 */
+       RTW89_SAR_6GHZ_SUBBAND_5_L, /* U-NII-5 lower part */
+       RTW89_SAR_6GHZ_SUBBAND_5_H, /* U-NII-5 higher part */
+       RTW89_SAR_6GHZ_SUBBAND_6,   /* U-NII-6 */
+       RTW89_SAR_6GHZ_SUBBAND_7_L, /* U-NII-7 lower part */
+       RTW89_SAR_6GHZ_SUBBAND_7_H, /* U-NII-7 higher part */
+       RTW89_SAR_6GHZ_SUBBAND_8,   /* U-NII-8 */
+
+       RTW89_SAR_SUBBAND_NR,
+};
+
 struct rtw89_sar_cfg_common {
-       bool set[RTW89_SUBBAND_NR];
-       s32 cfg[RTW89_SUBBAND_NR];
+       bool set[RTW89_SAR_SUBBAND_NR];
+       s32 cfg[RTW89_SAR_SUBBAND_NR];
 };
 
 struct rtw89_sar_info {
@@ -2646,6 +2675,10 @@ struct rtw89_lck_info {
        u8 thermal[RF_PATH_MAX];
 };
 
+struct rtw89_rx_dck_info {
+       u8 thermal[RF_PATH_MAX];
+};
+
 struct rtw89_iqk_info {
        bool lok_cor_fail[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR];
        bool lok_fin_fail[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR];
@@ -2776,13 +2809,20 @@ enum rtw89_multi_cfo_mode {
 enum rtw89_phy_cfo_status {
        RTW89_PHY_DCFO_STATE_NORMAL = 0,
        RTW89_PHY_DCFO_STATE_ENHANCE = 1,
+       RTW89_PHY_DCFO_STATE_HOLD = 2,
        RTW89_PHY_DCFO_STATE_MAX
 };
 
+enum rtw89_phy_cfo_ul_ofdma_acc_mode {
+       RTW89_CFO_UL_OFDMA_ACC_DISABLE = 0,
+       RTW89_CFO_UL_OFDMA_ACC_ENABLE = 1
+};
+
 struct rtw89_cfo_tracking_info {
        u16 cfo_timer_ms;
        bool cfo_trig_by_timer_en;
        enum rtw89_phy_cfo_status phy_cfo_status;
+       enum rtw89_phy_cfo_ul_ofdma_acc_mode cfo_ul_ofdma_acc_mode;
        u8 phy_cfo_trk_cnt;
        bool is_adjust;
        enum rtw89_multi_cfo_mode rtw89_multi_cfo_mode;
@@ -3125,6 +3165,7 @@ struct rtw89_dev {
        struct rtw89_dpk_info dpk;
        struct rtw89_mcc_info mcc;
        struct rtw89_lck_info lck;
+       struct rtw89_rx_dck_info rx_dck;
        bool is_tssi_mode[RF_PATH_MAX];
        bool is_bt_iqk_timeout;
 
index 7820bc3..f00f819 100644 (file)
@@ -2376,7 +2376,8 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v)
        seq_printf(m, "TP TX: %u [%u] Mbps (lv: %d), RX: %u [%u] Mbps (lv: %d)\n",
                   stats->tx_throughput, stats->tx_throughput_raw, stats->tx_tfc_lv,
                   stats->rx_throughput, stats->rx_throughput_raw, stats->rx_tfc_lv);
-       seq_printf(m, "Beacon: %u\n", pkt_stat->beacon_nr);
+       seq_printf(m, "Beacon: %u, TF: %u\n", pkt_stat->beacon_nr,
+                  stats->rx_tf_periodic);
        seq_printf(m, "Avg packet length: TX=%u, RX=%u\n", stats->tx_avg_len,
                   stats->rx_avg_len);
 
index de72155..561b04f 100644 (file)
@@ -24,6 +24,7 @@ enum rtw89_debug_mask {
        RTW89_DBG_BTC = BIT(13),
        RTW89_DBG_BF = BIT(14),
        RTW89_DBG_HW_SCAN = BIT(15),
+       RTW89_DBG_SAR = BIT(16),
 };
 
 enum rtw89_debug_mac_reg_sel {
index 4718ace..2d9c315 100644 (file)
@@ -2257,7 +2257,7 @@ static int rtw89_hw_scan_add_chan_list(struct rtw89_dev *rtwdev,
                list_add_tail(&ch_info->list, &chan_list);
                off_chan_time += ch_info->period;
        }
-       rtw89_fw_h2c_scan_list_offload(rtwdev, list_len, &chan_list);
+       ret = rtw89_fw_h2c_scan_list_offload(rtwdev, list_len, &chan_list);
 
 out:
        list_for_each_entry_safe(ch_info, tmp, &chan_list, list) {
@@ -2339,6 +2339,9 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
        rtwvif->scan_req = NULL;
        rtwvif->scan_ies = NULL;
        rtwdev->scan_info.scanning_vif = NULL;
+
+       if (rtwvif->net_type != RTW89_NET_TYPE_NO_LINK)
+               rtw89_store_op_chan(rtwdev, false);
 }
 
 void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
@@ -2365,20 +2368,27 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
                if (ret)
                        goto out;
        }
-       rtw89_fw_h2c_scan_offload(rtwdev, &opt, rtwvif);
+       ret = rtw89_fw_h2c_scan_offload(rtwdev, &opt, rtwvif);
 out:
        return ret;
 }
 
-void rtw89_store_op_chan(struct rtw89_dev *rtwdev)
+void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup)
 {
        struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
        struct rtw89_hal *hal = &rtwdev->hal;
 
-       scan_info->op_pri_ch = hal->current_primary_channel;
-       scan_info->op_chan = hal->current_channel;
-       scan_info->op_bw = hal->current_band_width;
-       scan_info->op_band = hal->current_band_type;
+       if (backup) {
+               scan_info->op_pri_ch = hal->current_primary_channel;
+               scan_info->op_chan = hal->current_channel;
+               scan_info->op_bw = hal->current_band_width;
+               scan_info->op_band = hal->current_band_type;
+       } else {
+               hal->current_primary_channel = scan_info->op_pri_ch;
+               hal->current_channel = scan_info->op_chan;
+               hal->current_band_width = scan_info->op_bw;
+               hal->current_band_type = scan_info->op_band;
+       }
 }
 
 #define H2C_FW_CPU_EXCEPTION_LEN 4
index 95a55c4..e75ad22 100644 (file)
@@ -2633,17 +2633,14 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev,
                     struct rtw89_mac_c2h_info *c2h_info);
 int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable);
 void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev);
-void rtw89_store_op_chan(struct rtw89_dev *rtwdev);
+void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup);
 void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
                         struct ieee80211_scan_request *req);
 void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
                            bool aborted);
 int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
                          bool enable);
-void rtw89_hw_scan_status_report(struct rtw89_dev *rtwdev, struct sk_buff *skb);
-void rtw89_hw_scan_chan_switch(struct rtw89_dev *rtwdev, struct sk_buff *skb);
 void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
-void rtw89_store_op_chan(struct rtw89_dev *rtwdev);
 int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev);
 
 #endif
index 3cf8929..93124b8 100644 (file)
@@ -3681,17 +3681,20 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
                rtw89_hw_scan_complete(rtwdev, vif, false);
                break;
        case RTW89_SCAN_ENTER_CH_NOTIFY:
-               if (rtw89_is_op_chan(rtwdev, band, chan))
+               hal->prev_band_type = hal->current_band_type;
+               hal->current_band_type = band;
+               hal->prev_primary_channel = hal->current_primary_channel;
+               hal->current_primary_channel = chan;
+               hal->current_channel = chan;
+               hal->current_band_width = RTW89_CHANNEL_WIDTH_20;
+               if (rtw89_is_op_chan(rtwdev, band, chan)) {
+                       rtw89_store_op_chan(rtwdev, false);
                        ieee80211_wake_queues(rtwdev->hw);
+               }
                break;
        default:
                return;
        }
-
-       hal->prev_band_type = hal->current_band_type;
-       hal->prev_primary_channel = hal->current_channel;
-       hal->current_channel = chan;
-       hal->current_band_type = band;
 }
 
 static void
index 9f511c8..f666193 100644 (file)
@@ -666,6 +666,7 @@ enum mac_ax_err_info {
        MAC_AX_ERR_L2_ERR_APB_BBRF_TO_RX4281 = 0x2360,
        MAC_AX_ERR_L2_ERR_APB_BBRF_TO_OTHERS = 0x2370,
        MAC_AX_ERR_L2_RESET_DONE = 0x2400,
+       MAC_AX_ERR_L2_ERR_WDT_TIMEOUT_INT = 0x2599,
        MAC_AX_ERR_CPU_EXCEPTION = 0x3000,
        MAC_AX_ERR_ASSERTION = 0x4000,
        MAC_AX_GET_ERR_MAX,
index f24e4a2..6d0c62c 100644 (file)
@@ -350,7 +350,7 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
                        rtw89_phy_set_bss_color(rtwdev, vif);
                        rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif);
                        rtw89_mac_port_update(rtwdev, rtwvif);
-                       rtw89_store_op_chan(rtwdev);
+                       rtw89_store_op_chan(rtwdev, true);
                } else {
                        /* Abort ongoing scan if cancel_scan isn't issued
                         * when disconnected by peer
index 0ef7821..25872df 100644 (file)
@@ -738,6 +738,9 @@ static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev)
        if (unlikely(isrs.halt_c2h_isrs & B_AX_HALT_C2H_INT_EN))
                rtw89_ser_notify(rtwdev, rtw89_mac_get_err_status(rtwdev));
 
+       if (unlikely(isrs.halt_c2h_isrs & B_AX_WDT_TIMEOUT_INT_EN))
+               rtw89_ser_notify(rtwdev, MAC_AX_ERR_L2_ERR_WDT_TIMEOUT_INT);
+
        if (unlikely(rtwpci->under_recovery))
                goto enable_intr;
 
@@ -3126,7 +3129,7 @@ static void rtw89_pci_recovery_intr_mask_v1(struct rtw89_dev *rtwdev)
        struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
 
        rtwpci->ind_intrs = B_AX_HS0ISR_IND_INT_EN;
-       rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN;
+       rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN;
        rtwpci->intrs[0] = 0;
        rtwpci->intrs[1] = 0;
 }
@@ -3138,7 +3141,7 @@ static void rtw89_pci_default_intr_mask_v1(struct rtw89_dev *rtwdev)
        rtwpci->ind_intrs = B_AX_HCI_AXIDMA_INT_EN |
                            B_AX_HS1ISR_IND_INT_EN |
                            B_AX_HS0ISR_IND_INT_EN;
-       rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN;
+       rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN;
        rtwpci->intrs[0] = B_AX_TXDMA_STUCK_INT_EN |
                           B_AX_RXDMA_INT_EN |
                           B_AX_RXP1DMA_INT_EN |
@@ -3155,7 +3158,7 @@ static void rtw89_pci_low_power_intr_mask_v1(struct rtw89_dev *rtwdev)
 
        rtwpci->ind_intrs = B_AX_HS1ISR_IND_INT_EN |
                            B_AX_HS0ISR_IND_INT_EN;
-       rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN;
+       rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN;
        rtwpci->intrs[0] = 0;
        rtwpci->intrs[1] = B_AX_GPIO18_INT_EN;
 }
index bb585ed..a118647 100644 (file)
@@ -94,6 +94,7 @@
 
 /* Interrupts */
 #define R_AX_HIMR0 0x01A0
+#define B_AX_WDT_TIMEOUT_INT_EN BIT(22)
 #define B_AX_HALT_C2H_INT_EN BIT(21)
 #define R_AX_HISR0 0x01A4
 
index 762cdba..217aacb 100644 (file)
@@ -2151,6 +2151,7 @@ static void rtw89_phy_cfo_init(struct rtw89_dev *rtwdev)
        cfo->cfo_trig_by_timer_en = false;
        cfo->phy_cfo_trk_cnt = 0;
        cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
+       cfo->cfo_ul_ofdma_acc_mode = RTW89_CFO_UL_OFDMA_ACC_ENABLE;
 }
 
 static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev,
@@ -2419,6 +2420,13 @@ void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev)
 {
        struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
        struct rtw89_traffic_stats *stats = &rtwdev->stats;
+       bool is_ul_ofdma = false, ofdma_acc_en = false;
+
+       if (stats->rx_tf_periodic > CFO_TF_CNT_TH)
+               is_ul_ofdma = true;
+       if (cfo->cfo_ul_ofdma_acc_mode == RTW89_CFO_UL_OFDMA_ACC_ENABLE &&
+           is_ul_ofdma)
+               ofdma_acc_en = true;
 
        switch (cfo->phy_cfo_status) {
        case RTW89_PHY_DCFO_STATE_NORMAL:
@@ -2430,16 +2438,26 @@ void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev)
                }
                break;
        case RTW89_PHY_DCFO_STATE_ENHANCE:
-               if (cfo->phy_cfo_trk_cnt >= CFO_PERIOD_CNT) {
+               if (stats->tx_throughput <= CFO_TP_LOWER)
+                       cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
+               else if (ofdma_acc_en &&
+                        cfo->phy_cfo_trk_cnt >= CFO_PERIOD_CNT)
+                       cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_HOLD;
+               else
+                       cfo->phy_cfo_trk_cnt++;
+
+               if (cfo->phy_cfo_status == RTW89_PHY_DCFO_STATE_NORMAL) {
                        cfo->phy_cfo_trk_cnt = 0;
                        cfo->cfo_trig_by_timer_en = false;
                }
-               if (cfo->cfo_trig_by_timer_en == 1)
-                       cfo->phy_cfo_trk_cnt++;
+               break;
+       case RTW89_PHY_DCFO_STATE_HOLD:
                if (stats->tx_throughput <= CFO_TP_LOWER) {
                        cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
                        cfo->phy_cfo_trk_cnt = 0;
                        cfo->cfo_trig_by_timer_en = false;
+               } else {
+                       cfo->phy_cfo_trk_cnt++;
                }
                break;
        default:
index 2916601..e20636f 100644 (file)
@@ -62,6 +62,7 @@
 #define CFO_COMP_PERIOD 250
 #define CFO_COMP_WEIGHT 8
 #define MAX_CFO_TOLERANCE 30
+#define CFO_TF_CNT_TH 300
 
 #define CCX_MAX_PERIOD 2097
 #define CCX_MAX_PERIOD_UNIT 32
index 64840c8..b697aef 100644 (file)
@@ -1861,6 +1861,7 @@ static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev)
 {
        rtw8852c_dpk_track(rtwdev);
        rtw8852c_lck_track(rtwdev);
+       rtw8852c_rx_dck_track(rtwdev);
 }
 
 static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
index dfb9cab..4186d82 100644 (file)
@@ -3864,6 +3864,7 @@ void rtw8852c_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
 
 void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_afe)
 {
+       struct rtw89_rx_dck_info *rx_dck = &rtwdev->rx_dck;
        u8 path, kpath;
        u32 rf_reg5;
 
@@ -3883,6 +3884,7 @@ void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_a
                rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
                rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX);
                _set_rx_dck(rtwdev, phy, path, is_afe);
+               rx_dck->thermal[path] = ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
                rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5);
 
                if (rtwdev->is_tssi_mode[path])
@@ -3891,6 +3893,31 @@ void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_a
        }
 }
 
+#define RTW8852C_RX_DCK_TH 8
+
+void rtw8852c_rx_dck_track(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_rx_dck_info *rx_dck = &rtwdev->rx_dck;
+       u8 cur_thermal;
+       int delta;
+       int path;
+
+       for (path = 0; path < RF_PATH_NUM_8852C; path++) {
+               cur_thermal =
+                       ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
+               delta = abs((int)cur_thermal - rx_dck->thermal[path]);
+
+               rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+                           "[RX_DCK] path=%d current thermal=0x%x delta=0x%x\n",
+                           path, cur_thermal, delta);
+
+               if (delta >= RTW8852C_RX_DCK_TH) {
+                       rtw8852c_rx_dck(rtwdev, RTW89_PHY_0, false);
+                       return;
+               }
+       }
+}
+
 void rtw8852c_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
 {
        u32 tx_en;
index c32756f..5118a49 100644 (file)
@@ -12,6 +12,7 @@ void rtw8852c_rck(struct rtw89_dev *rtwdev);
 void rtw8852c_dack(struct rtw89_dev *rtwdev);
 void rtw8852c_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
 void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool is_afe);
+void rtw8852c_rx_dck_track(struct rtw89_dev *rtwdev);
 void rtw8852c_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
 void rtw8852c_dpk_track(struct rtw89_dev *rtwdev);
 void rtw8852c_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
index 097c878..eb2d3ec 100644 (file)
 #include "debug.h"
 #include "sar.h"
 
+static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev,
+                                                   u32 center_freq)
+{
+       switch (center_freq) {
+       default:
+               rtw89_debug(rtwdev, RTW89_DBG_SAR,
+                           "center freq: %u to SAR subband is unhandled\n",
+                           center_freq);
+               fallthrough;
+       case 2412 ... 2484:
+               return RTW89_SAR_2GHZ_SUBBAND;
+       case 5180 ... 5320:
+               return RTW89_SAR_5GHZ_SUBBAND_1_2;
+       case 5500 ... 5720:
+               return RTW89_SAR_5GHZ_SUBBAND_2_E;
+       case 5745 ... 5825:
+               return RTW89_SAR_5GHZ_SUBBAND_3;
+       case 5955 ... 6155:
+               return RTW89_SAR_6GHZ_SUBBAND_5_L;
+       case 6175 ... 6415:
+               return RTW89_SAR_6GHZ_SUBBAND_5_H;
+       case 6435 ... 6515:
+               return RTW89_SAR_6GHZ_SUBBAND_6;
+       case 6535 ... 6695:
+               return RTW89_SAR_6GHZ_SUBBAND_7_L;
+       case 6715 ... 6855:
+               return RTW89_SAR_6GHZ_SUBBAND_7_H;
+
+       /* freq 6875 (ch 185, 20MHz) spans RTW89_SAR_6GHZ_SUBBAND_7_H
+        * and RTW89_SAR_6GHZ_SUBBAND_8, so directly describe it with
+        * struct rtw89_sar_span in the following.
+        */
+
+       case 6895 ... 7115:
+               return RTW89_SAR_6GHZ_SUBBAND_8;
+       }
+}
+
+struct rtw89_sar_span {
+       enum rtw89_sar_subband subband_low;
+       enum rtw89_sar_subband subband_high;
+};
+
+#define RTW89_SAR_SPAN_VALID(span) ((span)->subband_high)
+
+#define RTW89_SAR_6GHZ_SPAN_HEAD 6145
+#define RTW89_SAR_6GHZ_SPAN_IDX(center_freq) \
+       ((((int)(center_freq) - RTW89_SAR_6GHZ_SPAN_HEAD) / 5) / 2)
+
+#define RTW89_DECL_SAR_6GHZ_SPAN(center_freq, subband_l, subband_h) \
+       [RTW89_SAR_6GHZ_SPAN_IDX(center_freq)] = { \
+               .subband_low = RTW89_SAR_6GHZ_ ## subband_l, \
+               .subband_high = RTW89_SAR_6GHZ_ ## subband_h, \
+       }
+
+/* Since 6GHz SAR subbands are not edge aligned, some cases span two SAR
+ * subbands. In the following, we describe each of them with rtw89_sar_span.
+ */
+static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = {
+       RTW89_DECL_SAR_6GHZ_SPAN(6145, SUBBAND_5_L, SUBBAND_5_H),
+       RTW89_DECL_SAR_6GHZ_SPAN(6165, SUBBAND_5_L, SUBBAND_5_H),
+       RTW89_DECL_SAR_6GHZ_SPAN(6185, SUBBAND_5_L, SUBBAND_5_H),
+       RTW89_DECL_SAR_6GHZ_SPAN(6505, SUBBAND_6, SUBBAND_7_L),
+       RTW89_DECL_SAR_6GHZ_SPAN(6525, SUBBAND_6, SUBBAND_7_L),
+       RTW89_DECL_SAR_6GHZ_SPAN(6545, SUBBAND_6, SUBBAND_7_L),
+       RTW89_DECL_SAR_6GHZ_SPAN(6665, SUBBAND_7_L, SUBBAND_7_H),
+       RTW89_DECL_SAR_6GHZ_SPAN(6705, SUBBAND_7_L, SUBBAND_7_H),
+       RTW89_DECL_SAR_6GHZ_SPAN(6825, SUBBAND_7_H, SUBBAND_8),
+       RTW89_DECL_SAR_6GHZ_SPAN(6865, SUBBAND_7_H, SUBBAND_8),
+       RTW89_DECL_SAR_6GHZ_SPAN(6875, SUBBAND_7_H, SUBBAND_8),
+       RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8),
+};
+
 static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg)
 {
        struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common;
-       enum rtw89_subband subband = rtwdev->hal.current_subband;
+       struct rtw89_hal *hal = &rtwdev->hal;
+       enum rtw89_band band = hal->current_band_type;
+       u32 center_freq = hal->current_freq;
+       const struct rtw89_sar_span *span = NULL;
+       enum rtw89_sar_subband subband_l, subband_h;
+       int idx;
+
+       if (band == RTW89_BAND_6G) {
+               idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq);
+               /* To decrease size of rtw89_sar_overlapping_6ghz[],
+                * RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs
+                * to make first span as index 0 of the table. So, if center
+                * frequency is less than the first one, it will get netative.
+                */
+               if (idx >= 0 && idx < ARRAY_SIZE(rtw89_sar_overlapping_6ghz))
+                       span = &rtw89_sar_overlapping_6ghz[idx];
+       }
+
+       if (span && RTW89_SAR_SPAN_VALID(span)) {
+               subband_l = span->subband_low;
+               subband_h = span->subband_high;
+       } else {
+               subband_l = rtw89_sar_get_subband(rtwdev, center_freq);
+               subband_h = subband_l;
+       }
+
+       rtw89_debug(rtwdev, RTW89_DBG_SAR,
+                   "for {band %u, center_freq %u}, SAR subband: {%u, %u}\n",
+                   band, center_freq, subband_l, subband_h);
 
-       if (!rtwsar->set[subband])
+       if (!rtwsar->set[subband_l] && !rtwsar->set[subband_h])
                return -ENODATA;
 
-       *cfg = rtwsar->cfg[subband];
+       if (!rtwsar->set[subband_l])
+               *cfg = rtwsar->cfg[subband_h];
+       else if (!rtwsar->set[subband_h])
+               *cfg = rtwsar->cfg[subband_l];
+       else
+               *cfg = min(rtwsar->cfg[subband_l], rtwsar->cfg[subband_h]);
+
        return 0;
 }
 
@@ -128,21 +235,20 @@ exit:
        return ret;
 }
 
-static const u8 rtw89_common_sar_subband_map[] = {
-       RTW89_CH_2G,
-       RTW89_CH_5G_BAND_1,
-       RTW89_CH_5G_BAND_3,
-       RTW89_CH_5G_BAND_4,
-};
-
 static const struct cfg80211_sar_freq_ranges rtw89_common_sar_freq_ranges[] = {
        { .start_freq = 2412, .end_freq = 2484, },
        { .start_freq = 5180, .end_freq = 5320, },
        { .start_freq = 5500, .end_freq = 5720, },
        { .start_freq = 5745, .end_freq = 5825, },
+       { .start_freq = 5955, .end_freq = 6155, },
+       { .start_freq = 6175, .end_freq = 6415, },
+       { .start_freq = 6435, .end_freq = 6515, },
+       { .start_freq = 6535, .end_freq = 6695, },
+       { .start_freq = 6715, .end_freq = 6875, },
+       { .start_freq = 6875, .end_freq = 7115, },
 };
 
-static_assert(ARRAY_SIZE(rtw89_common_sar_subband_map) ==
+static_assert(RTW89_SAR_SUBBAND_NR ==
              ARRAY_SIZE(rtw89_common_sar_freq_ranges));
 
 const struct cfg80211_sar_capa rtw89_sar_capa = {
@@ -159,7 +265,6 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
        u8 fct;
        u32 freq_start;
        u32 freq_end;
-       u32 band;
        s32 power;
        u32 i, idx;
 
@@ -175,15 +280,14 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
 
                freq_start = rtw89_common_sar_freq_ranges[idx].start_freq;
                freq_end = rtw89_common_sar_freq_ranges[idx].end_freq;
-               band = rtw89_common_sar_subband_map[idx];
                power = sar->sub_specs[i].power;
 
-               rtw89_info(rtwdev, "On freq %u to %u, ", freq_start, freq_end);
-               rtw89_info(rtwdev, "set SAR power limit %d (unit: 1/%lu dBm)\n",
-                          power, BIT(fct));
+               rtw89_debug(rtwdev, RTW89_DBG_SAR,
+                           "On freq %u to %u, set SAR limit %d (unit: 1/%lu dBm)\n",
+                           freq_start, freq_end, power, BIT(fct));
 
-               sar_common.set[band] = true;
-               sar_common.cfg[band] = power;
+               sar_common.set[idx] = true;
+               sar_common.cfg[idx] = power;
        }
 
        return rtw89_apply_sar_common(rtwdev, &sar_common);
index 3d1b8a1..52c7f56 100644 (file)
@@ -286,8 +286,7 @@ static int load_firmware_secure(struct wfx_dev *wdev)
 
 error:
        kfree(buf);
-       if (fw)
-               release_firmware(fw);
+       release_firmware(fw);
        if (ret)
                print_boot_status(wdev);
        return ret;
index 10e019c..3b4ded2 100644 (file)
@@ -327,18 +327,12 @@ static int cw1200_bh_rx_helper(struct cw1200_common *priv,
        if (WARN_ON(wsm_handle_rx(priv, wsm_id, wsm, &skb_rx)))
                goto err;
 
-       if (skb_rx) {
-               dev_kfree_skb(skb_rx);
-               skb_rx = NULL;
-       }
+       dev_kfree_skb(skb_rx);
 
        return 0;
 
 err:
-       if (skb_rx) {
-               dev_kfree_skb(skb_rx);
-               skb_rx = NULL;
-       }
+       dev_kfree_skb(skb_rx);
        return -1;
 }
 
index 514f2c1..ba14d83 100644 (file)
@@ -654,7 +654,7 @@ static int __init virt_wifi_init_module(void)
 {
        int err;
 
-       /* Guaranteed to be locallly-administered and not multicast. */
+       /* Guaranteed to be locally-administered and not multicast. */
        eth_random_addr(fake_router_bssid);
 
        err = register_netdevice_notifier(&virt_wifi_notifier);
index d9dea48..8174d7b 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/debugfs.h>
 
 typedef unsigned int pending_ring_idx_t;
-#define INVALID_PENDING_RING_IDX (~0U)
 
 struct pending_tx_info {
        struct xen_netif_tx_request req; /* tx request */
@@ -82,8 +81,6 @@ struct xenvif_rx_meta {
 /* Discriminate from any valid pending_idx value. */
 #define INVALID_PENDING_IDX 0xFFFF
 
-#define MAX_BUFFER_OFFSET XEN_PAGE_SIZE
-
 #define MAX_PENDING_REQS XEN_NETIF_TX_RING_SIZE
 
 /* The maximum number of frags is derived from the size of a grant (same
@@ -367,11 +364,6 @@ void xenvif_free(struct xenvif *vif);
 int xenvif_xenbus_init(void);
 void xenvif_xenbus_fini(void);
 
-int xenvif_schedulable(struct xenvif *vif);
-
-int xenvif_queue_stopped(struct xenvif_queue *queue);
-void xenvif_wake_queue(struct xenvif_queue *queue);
-
 /* (Un)Map communication rings. */
 void xenvif_unmap_frontend_data_rings(struct xenvif_queue *queue);
 int xenvif_map_frontend_data_rings(struct xenvif_queue *queue,
@@ -394,7 +386,6 @@ int xenvif_dealloc_kthread(void *data);
 irqreturn_t xenvif_ctrl_irq_fn(int irq, void *data);
 
 bool xenvif_have_rx_work(struct xenvif_queue *queue, bool test_kthread);
-void xenvif_rx_action(struct xenvif_queue *queue);
 void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb);
 
 void xenvif_carrier_on(struct xenvif *vif);
@@ -403,9 +394,6 @@ void xenvif_carrier_on(struct xenvif *vif);
 void xenvif_zerocopy_callback(struct sk_buff *skb, struct ubuf_info *ubuf,
                              bool zerocopy_success);
 
-/* Unmap a pending page and release it back to the guest */
-void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx);
-
 static inline pending_ring_idx_t nr_pending_reqs(struct xenvif_queue *queue)
 {
        return MAX_PENDING_REQS -
index 8e03537..fb32ae8 100644 (file)
@@ -69,7 +69,7 @@ void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue)
        wake_up(&queue->dealloc_wq);
 }
 
-int xenvif_schedulable(struct xenvif *vif)
+static int xenvif_schedulable(struct xenvif *vif)
 {
        return netif_running(vif->dev) &&
                test_bit(VIF_STATUS_CONNECTED, &vif->status) &&
@@ -177,20 +177,6 @@ irqreturn_t xenvif_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-int xenvif_queue_stopped(struct xenvif_queue *queue)
-{
-       struct net_device *dev = queue->vif->dev;
-       unsigned int id = queue->id;
-       return netif_tx_queue_stopped(netdev_get_tx_queue(dev, id));
-}
-
-void xenvif_wake_queue(struct xenvif_queue *queue)
-{
-       struct net_device *dev = queue->vif->dev;
-       unsigned int id = queue->id;
-       netif_tx_wake_queue(netdev_get_tx_queue(dev, id));
-}
-
 static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb,
                               struct net_device *sb_dev)
 {
index d93814c..fc61a44 100644 (file)
@@ -112,6 +112,8 @@ static void make_tx_response(struct xenvif_queue *queue,
                             s8       st);
 static void push_tx_responses(struct xenvif_queue *queue);
 
+static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx);
+
 static inline int tx_work_todo(struct xenvif_queue *queue);
 
 static inline unsigned long idx_to_pfn(struct xenvif_queue *queue,
@@ -1418,7 +1420,7 @@ static void push_tx_responses(struct xenvif_queue *queue)
                notify_remote_via_irq(queue->tx_irq);
 }
 
-void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
+static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
 {
        int ret;
        struct gnttab_unmap_grant_ref tx_unmap_op;
index dbac4c0..8df2c73 100644 (file)
@@ -486,7 +486,7 @@ static void xenvif_rx_skb(struct xenvif_queue *queue)
 
 #define RX_BATCH_SIZE 64
 
-void xenvif_rx_action(struct xenvif_queue *queue)
+static void xenvif_rx_action(struct xenvif_queue *queue)
 {
        struct sk_buff_head completed_skbs;
        unsigned int work_done = 0;
index 4519ef4..e59ea21 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2020 Facebook */
 
+#include <linux/bits.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -88,10 +89,10 @@ struct tod_reg {
 #define TOD_CTRL_DISABLE_FMT_A BIT(17)
 #define TOD_CTRL_DISABLE_FMT_B BIT(16)
 #define TOD_CTRL_ENABLE                BIT(0)
-#define TOD_CTRL_GNSS_MASK     ((1U << 4) - 1)
+#define TOD_CTRL_GNSS_MASK     GENMASK(3, 0)
 #define TOD_CTRL_GNSS_SHIFT    24
 
-#define TOD_STATUS_UTC_MASK            0xff
+#define TOD_STATUS_UTC_MASK            GENMASK(7, 0)
 #define TOD_STATUS_UTC_VALID           BIT(8)
 #define TOD_STATUS_LEAP_ANNOUNCE       BIT(12)
 #define TOD_STATUS_LEAP_VALID          BIT(16)
@@ -205,7 +206,7 @@ struct frequency_reg {
 #define FREQ_STATUS_VALID      BIT(31)
 #define FREQ_STATUS_ERROR      BIT(30)
 #define FREQ_STATUS_OVERRUN    BIT(29)
-#define FREQ_STATUS_MASK       (BIT(24) - 1)
+#define FREQ_STATUS_MASK       GENMASK(23, 0)
 
 struct ptp_ocp_flash_info {
        const char *name;
@@ -674,9 +675,9 @@ static const struct ocp_selector ptp_ocp_clock[] = {
        { }
 };
 
+#define SMA_DISABLE            BIT(16)
 #define SMA_ENABLE             BIT(15)
-#define SMA_SELECT_MASK                ((1U << 15) - 1)
-#define SMA_DISABLE            0x10000
+#define SMA_SELECT_MASK                GENMASK(14, 0)
 
 static const struct ocp_selector ptp_ocp_sma_in[] = {
        { .name = "10Mhz",      .value = 0x0000 },
@@ -2154,7 +2155,7 @@ ptp_ocp_fb_set_pins(struct ptp_ocp *bp)
        struct ptp_pin_desc *config;
        int i;
 
-       config = kzalloc(sizeof(*config) * 4, GFP_KERNEL);
+       config = kcalloc(4, sizeof(*config), GFP_KERNEL);
        if (!config)
                return -ENOMEM;
 
@@ -3440,7 +3441,7 @@ ptp_ocp_tod_status_show(struct seq_file *s, void *data)
 
        val = ioread32(&bp->tod->utc_status);
        seq_printf(s, "UTC status register: 0x%08X\n", val);
-       seq_printf(s, "UTC offset: %d  valid:%d\n",
+       seq_printf(s, "UTC offset: %ld  valid:%d\n",
                val & TOD_STATUS_UTC_MASK, val & TOD_STATUS_UTC_VALID ? 1 : 0);
        seq_printf(s, "Leap second info valid:%d, Leap second announce %d\n",
                val & TOD_STATUS_LEAP_VALID ? 1 : 0,
@@ -3700,10 +3701,8 @@ ptp_ocp_detach(struct ptp_ocp *bp)
                serial8250_unregister_port(bp->mac_port);
        if (bp->nmea_port != -1)
                serial8250_unregister_port(bp->nmea_port);
-       if (bp->spi_flash)
-               platform_device_unregister(bp->spi_flash);
-       if (bp->i2c_ctrl)
-               platform_device_unregister(bp->i2c_ctrl);
+       platform_device_unregister(bp->spi_flash);
+       platform_device_unregister(bp->i2c_ctrl);
        if (bp->i2c_clk)
                clk_hw_unregister_fixed_rate(bp->i2c_clk);
        if (bp->n_irqs)
@@ -3773,7 +3772,6 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 out:
        ptp_ocp_detach(bp);
-       pci_set_drvdata(pdev, NULL);
 out_disable:
        pci_disable_device(pdev);
 out_free:
@@ -3789,7 +3787,6 @@ ptp_ocp_remove(struct pci_dev *pdev)
 
        devlink_unregister(devlink);
        ptp_ocp_detach(bp);
-       pci_set_drvdata(pdev, NULL);
        pci_disable_device(pdev);
 
        devlink_free(devlink);
index 75d40ac..5c65ae6 100644 (file)
@@ -76,6 +76,7 @@
 #define IEEE80211_STYPE_ACTION         0x00D0
 
 /* control */
+#define IEEE80211_STYPE_TRIGGER                0x0020
 #define IEEE80211_STYPE_CTL_EXT                0x0060
 #define IEEE80211_STYPE_BACK_REQ       0x0080
 #define IEEE80211_STYPE_BACK           0x0090
@@ -295,6 +296,17 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
 
 #define IEEE80211_HT_CTL_LEN           4
 
+/* trigger type within common_info of trigger frame */
+#define IEEE80211_TRIGGER_TYPE_MASK            0xf
+#define IEEE80211_TRIGGER_TYPE_BASIC           0x0
+#define IEEE80211_TRIGGER_TYPE_BFRP            0x1
+#define IEEE80211_TRIGGER_TYPE_MU_BAR          0x2
+#define IEEE80211_TRIGGER_TYPE_MU_RTS          0x3
+#define IEEE80211_TRIGGER_TYPE_BSRP            0x4
+#define IEEE80211_TRIGGER_TYPE_GCR_MU_BAR      0x5
+#define IEEE80211_TRIGGER_TYPE_BQRP            0x6
+#define IEEE80211_TRIGGER_TYPE_NFRP            0x7
+
 struct ieee80211_hdr {
        __le16 frame_control;
        __le16 duration_id;
@@ -324,6 +336,15 @@ struct ieee80211_qos_hdr {
        __le16 qos_ctrl;
 } __packed __aligned(2);
 
+struct ieee80211_trigger {
+       __le16 frame_control;
+       __le16 duration;
+       u8 ra[ETH_ALEN];
+       u8 ta[ETH_ALEN];
+       __le64 common_info;
+       u8 variable[];
+} __packed __aligned(2);
+
 /**
  * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set
  * @fc: frame control bytes in little-endian byteorder
@@ -729,6 +750,16 @@ static inline bool ieee80211_is_qos_nullfunc(__le16 fc)
               cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
 }
 
+/**
+ * ieee80211_is_trigger - check if frame is trigger frame
+ * @fc: frame control field in little-endian byteorder
+ */
+static inline bool ieee80211_is_trigger(__le16 fc)
+{
+       return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
+              cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_TRIGGER);
+}
+
 /**
  * ieee80211_is_any_nullfunc - check if frame is regular or QoS nullfunc frame
  * @fc: frame control bytes in little-endian byteorder
index b422947..5230251 100644 (file)
@@ -46,10 +46,10 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
 
                pcpu_stats = get_cpu_ptr(vlan->pcpu_stats);
                u64_stats_update_begin(&pcpu_stats->syncp);
-               pcpu_stats->rx_packets++;
-               pcpu_stats->rx_bytes += len;
+               u64_stats_inc(&pcpu_stats->rx_packets);
+               u64_stats_add(&pcpu_stats->rx_bytes, len);
                if (multicast)
-                       pcpu_stats->rx_multicast++;
+                       u64_stats_inc(&pcpu_stats->rx_multicast);
                u64_stats_update_end(&pcpu_stats->syncp);
                put_cpu_ptr(vlan->pcpu_stats);
        } else {
index add6079..fc985e5 100644 (file)
 #include <uapi/linux/if_team.h>
 
 struct team_pcpu_stats {
-       u64                     rx_packets;
-       u64                     rx_bytes;
-       u64                     rx_multicast;
-       u64                     tx_packets;
-       u64                     tx_bytes;
+       u64_stats_t             rx_packets;
+       u64_stats_t             rx_bytes;
+       u64_stats_t             rx_multicast;
+       u64_stats_t             tx_packets;
+       u64_stats_t             tx_bytes;
        struct u64_stats_sync   syncp;
        u32                     rx_dropped;
        u32                     tx_dropped;
index 2be4dd7..e00c4ee 100644 (file)
@@ -118,11 +118,11 @@ static inline void vlan_drop_rx_stag_filter_info(struct net_device *dev)
  *     @tx_dropped: number of tx drops
  */
 struct vlan_pcpu_stats {
-       u64                     rx_packets;
-       u64                     rx_bytes;
-       u64                     rx_multicast;
-       u64                     tx_packets;
-       u64                     tx_bytes;
+       u64_stats_t             rx_packets;
+       u64_stats_t             rx_bytes;
+       u64_stats_t             rx_multicast;
+       u64_stats_t             tx_packets;
+       u64_stats_t             tx_bytes;
        struct u64_stats_sync   syncp;
        u32                     rx_errors;
        u32                     tx_dropped;
index f615a66..89afa4f 100644 (file)
@@ -2636,10 +2636,10 @@ struct packet_offload {
 
 /* often modified stats are per-CPU, other are shared (netdev->stats) */
 struct pcpu_sw_netstats {
-       u64     rx_packets;
-       u64     rx_bytes;
-       u64     tx_packets;
-       u64     tx_bytes;
+       u64_stats_t             rx_packets;
+       u64_stats_t             rx_bytes;
+       u64_stats_t             tx_packets;
+       u64_stats_t             tx_bytes;
        struct u64_stats_sync   syncp;
 } __aligned(4 * sizeof(u64));
 
@@ -2656,8 +2656,8 @@ static inline void dev_sw_netstats_rx_add(struct net_device *dev, unsigned int l
        struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
 
        u64_stats_update_begin(&tstats->syncp);
-       tstats->rx_bytes += len;
-       tstats->rx_packets++;
+       u64_stats_add(&tstats->rx_bytes, len);
+       u64_stats_inc(&tstats->rx_packets);
        u64_stats_update_end(&tstats->syncp);
 }
 
@@ -2668,8 +2668,8 @@ static inline void dev_sw_netstats_tx_add(struct net_device *dev,
        struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
 
        u64_stats_update_begin(&tstats->syncp);
-       tstats->tx_bytes += len;
-       tstats->tx_packets += packets;
+       u64_stats_add(&tstats->tx_bytes, len);
+       u64_stats_add(&tstats->tx_packets, packets);
        u64_stats_update_end(&tstats->syncp);
 }
 
@@ -3981,8 +3981,8 @@ static inline void netdev_tracker_free(struct net_device *dev,
 #endif
 }
 
-static inline void dev_hold_track(struct net_device *dev,
-                                 netdevice_tracker *tracker, gfp_t gfp)
+static inline void netdev_hold(struct net_device *dev,
+                              netdevice_tracker *tracker, gfp_t gfp)
 {
        if (dev) {
                __dev_hold(dev);
@@ -3990,8 +3990,8 @@ static inline void dev_hold_track(struct net_device *dev,
        }
 }
 
-static inline void dev_put_track(struct net_device *dev,
-                                netdevice_tracker *tracker)
+static inline void netdev_put(struct net_device *dev,
+                             netdevice_tracker *tracker)
 {
        if (dev) {
                netdev_tracker_free(dev, tracker);
@@ -4004,11 +4004,11 @@ static inline void dev_put_track(struct net_device *dev,
  *     @dev: network device
  *
  * Hold reference to device to keep it from being freed.
- * Try using dev_hold_track() instead.
+ * Try using netdev_hold() instead.
  */
 static inline void dev_hold(struct net_device *dev)
 {
-       dev_hold_track(dev, NULL, GFP_ATOMIC);
+       netdev_hold(dev, NULL, GFP_ATOMIC);
 }
 
 /**
@@ -4016,17 +4016,17 @@ static inline void dev_hold(struct net_device *dev)
  *     @dev: network device
  *
  * Release reference to device to allow it to be freed.
- * Try using dev_put_track() instead.
+ * Try using netdev_put() instead.
  */
 static inline void dev_put(struct net_device *dev)
 {
-       dev_put_track(dev, NULL);
+       netdev_put(dev, NULL);
 }
 
-static inline void dev_replace_track(struct net_device *odev,
-                                    struct net_device *ndev,
-                                    netdevice_tracker *tracker,
-                                    gfp_t gfp)
+static inline void netdev_ref_replace(struct net_device *odev,
+                                     struct net_device *ndev,
+                                     netdevice_tracker *tracker,
+                                     gfp_t gfp)
 {
        if (odev)
                netdev_tracker_free(odev, tracker);
index d3d1055..82edf03 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/netfilter/nf_conntrack_common.h>
 #endif
 #include <net/net_debug.h>
+#include <net/dropreason.h>
 
 /**
  * DOC: skb checksums
@@ -337,184 +338,6 @@ struct sk_buff_head {
 
 struct sk_buff;
 
-/* The reason of skb drop, which is used in kfree_skb_reason().
- * en...maybe they should be splited by group?
- *
- * Each item here should also be in 'TRACE_SKB_DROP_REASON', which is
- * used to translate the reason to string.
- */
-enum skb_drop_reason {
-       SKB_NOT_DROPPED_YET = 0,
-       SKB_DROP_REASON_NOT_SPECIFIED,  /* drop reason is not specified */
-       SKB_DROP_REASON_NO_SOCKET,      /* socket not found */
-       SKB_DROP_REASON_PKT_TOO_SMALL,  /* packet size is too small */
-       SKB_DROP_REASON_TCP_CSUM,       /* TCP checksum error */
-       SKB_DROP_REASON_SOCKET_FILTER,  /* dropped by socket filter */
-       SKB_DROP_REASON_UDP_CSUM,       /* UDP checksum error */
-       SKB_DROP_REASON_NETFILTER_DROP, /* dropped by netfilter */
-       SKB_DROP_REASON_OTHERHOST,      /* packet don't belong to current
-                                        * host (interface is in promisc
-                                        * mode)
-                                        */
-       SKB_DROP_REASON_IP_CSUM,        /* IP checksum error */
-       SKB_DROP_REASON_IP_INHDR,       /* there is something wrong with
-                                        * IP header (see
-                                        * IPSTATS_MIB_INHDRERRORS)
-                                        */
-       SKB_DROP_REASON_IP_RPFILTER,    /* IP rpfilter validate failed.
-                                        * see the document for rp_filter
-                                        * in ip-sysctl.rst for more
-                                        * information
-                                        */
-       SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST, /* destination address of L2
-                                                 * is multicast, but L3 is
-                                                 * unicast.
-                                                 */
-       SKB_DROP_REASON_XFRM_POLICY,    /* xfrm policy check failed */
-       SKB_DROP_REASON_IP_NOPROTO,     /* no support for IP protocol */
-       SKB_DROP_REASON_SOCKET_RCVBUFF, /* socket receive buff is full */
-       SKB_DROP_REASON_PROTO_MEM,      /* proto memory limition, such as
-                                        * udp packet drop out of
-                                        * udp_memory_allocated.
-                                        */
-       SKB_DROP_REASON_TCP_MD5NOTFOUND,        /* no MD5 hash and one
-                                                * expected, corresponding
-                                                * to LINUX_MIB_TCPMD5NOTFOUND
-                                                */
-       SKB_DROP_REASON_TCP_MD5UNEXPECTED,      /* MD5 hash and we're not
-                                                * expecting one, corresponding
-                                                * to LINUX_MIB_TCPMD5UNEXPECTED
-                                                */
-       SKB_DROP_REASON_TCP_MD5FAILURE, /* MD5 hash and its wrong,
-                                        * corresponding to
-                                        * LINUX_MIB_TCPMD5FAILURE
-                                        */
-       SKB_DROP_REASON_SOCKET_BACKLOG, /* failed to add skb to socket
-                                        * backlog (see
-                                        * LINUX_MIB_TCPBACKLOGDROP)
-                                        */
-       SKB_DROP_REASON_TCP_FLAGS,      /* TCP flags invalid */
-       SKB_DROP_REASON_TCP_ZEROWINDOW, /* TCP receive window size is zero,
-                                        * see LINUX_MIB_TCPZEROWINDOWDROP
-                                        */
-       SKB_DROP_REASON_TCP_OLD_DATA,   /* the TCP data reveived is already
-                                        * received before (spurious retrans
-                                        * may happened), see
-                                        * LINUX_MIB_DELAYEDACKLOST
-                                        */
-       SKB_DROP_REASON_TCP_OVERWINDOW, /* the TCP data is out of window,
-                                        * the seq of the first byte exceed
-                                        * the right edges of receive
-                                        * window
-                                        */
-       SKB_DROP_REASON_TCP_OFOMERGE,   /* the data of skb is already in
-                                        * the ofo queue, corresponding to
-                                        * LINUX_MIB_TCPOFOMERGE
-                                        */
-       SKB_DROP_REASON_TCP_RFC7323_PAWS, /* PAWS check, corresponding to
-                                          * LINUX_MIB_PAWSESTABREJECTED
-                                          */
-       SKB_DROP_REASON_TCP_INVALID_SEQUENCE, /* Not acceptable SEQ field */
-       SKB_DROP_REASON_TCP_RESET,      /* Invalid RST packet */
-       SKB_DROP_REASON_TCP_INVALID_SYN, /* Incoming packet has unexpected SYN flag */
-       SKB_DROP_REASON_TCP_CLOSE,      /* TCP socket in CLOSE state */
-       SKB_DROP_REASON_TCP_FASTOPEN,   /* dropped by FASTOPEN request socket */
-       SKB_DROP_REASON_TCP_OLD_ACK,    /* TCP ACK is old, but in window */
-       SKB_DROP_REASON_TCP_TOO_OLD_ACK, /* TCP ACK is too old */
-       SKB_DROP_REASON_TCP_ACK_UNSENT_DATA, /* TCP ACK for data we haven't sent yet */
-       SKB_DROP_REASON_TCP_OFO_QUEUE_PRUNE, /* pruned from TCP OFO queue */
-       SKB_DROP_REASON_TCP_OFO_DROP,   /* data already in receive queue */
-       SKB_DROP_REASON_IP_OUTNOROUTES, /* route lookup failed */
-       SKB_DROP_REASON_BPF_CGROUP_EGRESS,      /* dropped by
-                                                * BPF_PROG_TYPE_CGROUP_SKB
-                                                * eBPF program
-                                                */
-       SKB_DROP_REASON_IPV6DISABLED,   /* IPv6 is disabled on the device */
-       SKB_DROP_REASON_NEIGH_CREATEFAIL,       /* failed to create neigh
-                                                * entry
-                                                */
-       SKB_DROP_REASON_NEIGH_FAILED,   /* neigh entry in failed state */
-       SKB_DROP_REASON_NEIGH_QUEUEFULL,        /* arp_queue for neigh
-                                                * entry is full
-                                                */
-       SKB_DROP_REASON_NEIGH_DEAD,     /* neigh entry is dead */
-       SKB_DROP_REASON_TC_EGRESS,      /* dropped in TC egress HOOK */
-       SKB_DROP_REASON_QDISC_DROP,     /* dropped by qdisc when packet
-                                        * outputting (failed to enqueue to
-                                        * current qdisc)
-                                        */
-       SKB_DROP_REASON_CPU_BACKLOG,    /* failed to enqueue the skb to
-                                        * the per CPU backlog queue. This
-                                        * can be caused by backlog queue
-                                        * full (see netdev_max_backlog in
-                                        * net.rst) or RPS flow limit
-                                        */
-       SKB_DROP_REASON_XDP,            /* dropped by XDP in input path */
-       SKB_DROP_REASON_TC_INGRESS,     /* dropped in TC ingress HOOK */
-       SKB_DROP_REASON_UNHANDLED_PROTO,        /* protocol not implemented
-                                                * or not supported
-                                                */
-       SKB_DROP_REASON_SKB_CSUM,       /* sk_buff checksum computation
-                                        * error
-                                        */
-       SKB_DROP_REASON_SKB_GSO_SEG,    /* gso segmentation error */
-       SKB_DROP_REASON_SKB_UCOPY_FAULT,        /* failed to copy data from
-                                                * user space, e.g., via
-                                                * zerocopy_sg_from_iter()
-                                                * or skb_orphan_frags_rx()
-                                                */
-       SKB_DROP_REASON_DEV_HDR,        /* device driver specific
-                                        * header/metadata is invalid
-                                        */
-       /* the device is not ready to xmit/recv due to any of its data
-        * structure that is not up/ready/initialized, e.g., the IFF_UP is
-        * not set, or driver specific tun->tfiles[txq] is not initialized
-        */
-       SKB_DROP_REASON_DEV_READY,
-       SKB_DROP_REASON_FULL_RING,      /* ring buffer is full */
-       SKB_DROP_REASON_NOMEM,          /* error due to OOM */
-       SKB_DROP_REASON_HDR_TRUNC,      /* failed to trunc/extract the header
-                                        * from networking data, e.g., failed
-                                        * to pull the protocol header from
-                                        * frags via pskb_may_pull()
-                                        */
-       SKB_DROP_REASON_TAP_FILTER,     /* dropped by (ebpf) filter directly
-                                        * attached to tun/tap, e.g., via
-                                        * TUNSETFILTEREBPF
-                                        */
-       SKB_DROP_REASON_TAP_TXFILTER,   /* dropped by tx filter implemented
-                                        * at tun/tap, e.g., check_filter()
-                                        */
-       SKB_DROP_REASON_ICMP_CSUM,      /* ICMP checksum error */
-       SKB_DROP_REASON_INVALID_PROTO,  /* the packet doesn't follow RFC
-                                        * 2211, such as a broadcasts
-                                        * ICMP_TIMESTAMP
-                                        */
-       SKB_DROP_REASON_IP_INADDRERRORS,        /* host unreachable, corresponding
-                                                * to IPSTATS_MIB_INADDRERRORS
-                                                */
-       SKB_DROP_REASON_IP_INNOROUTES,  /* network unreachable, corresponding
-                                        * to IPSTATS_MIB_INADDRERRORS
-                                        */
-       SKB_DROP_REASON_PKT_TOO_BIG,    /* packet size is too big (maybe exceed
-                                        * the MTU)
-                                        */
-       SKB_DROP_REASON_MAX,
-};
-
-#define SKB_DR_INIT(name, reason)                              \
-       enum skb_drop_reason name = SKB_DROP_REASON_##reason
-#define SKB_DR(name)                                           \
-       SKB_DR_INIT(name, NOT_SPECIFIED)
-#define SKB_DR_SET(name, reason)                               \
-       (name = SKB_DROP_REASON_##reason)
-#define SKB_DR_OR(name, reason)                                        \
-       do {                                                    \
-               if (name == SKB_DROP_REASON_NOT_SPECIFIED ||    \
-                   name == SKB_NOT_DROPPED_YET)                \
-                       SKB_DR_SET(name, reason);               \
-       } while (0)
-
 /* To allow 64K frame to be packed as single skb without frag_list we
  * require 64K/PAGE_SIZE pages plus 1 additional page to allow for
  * buffers which do not start on a page boundary.
index 61b4906..1618b76 100644 (file)
@@ -107,7 +107,8 @@ struct bond_option {
 };
 
 int __bond_opt_set(struct bonding *bond, unsigned int option,
-                  struct bond_opt_value *val);
+                  struct bond_opt_value *val,
+                  struct nlattr *bad_attr, struct netlink_ext_ack *extack);
 int __bond_opt_set_notify(struct bonding *bond, unsigned int option,
                          struct bond_opt_value *val);
 int bond_opt_tryset_rtnl(struct bonding *bond, unsigned int option, char *buf);
diff --git a/include/net/dropreason.h b/include/net/dropreason.h
new file mode 100644 (file)
index 0000000..fae9b40
--- /dev/null
@@ -0,0 +1,256 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _LINUX_DROPREASON_H
+#define _LINUX_DROPREASON_H
+
+/**
+ * enum skb_drop_reason - the reasons of skb drops
+ *
+ * The reason of skb drop, which is used in kfree_skb_reason().
+ */
+enum skb_drop_reason {
+       /**
+        * @SKB_NOT_DROPPED_YET: skb is not dropped yet (used for no-drop case)
+        */
+       SKB_NOT_DROPPED_YET = 0,
+       /** @SKB_DROP_REASON_NOT_SPECIFIED: drop reason is not specified */
+       SKB_DROP_REASON_NOT_SPECIFIED,
+       /** @SKB_DROP_REASON_NO_SOCKET: socket not found */
+       SKB_DROP_REASON_NO_SOCKET,
+       /** @SKB_DROP_REASON_PKT_TOO_SMALL: packet size is too small */
+       SKB_DROP_REASON_PKT_TOO_SMALL,
+       /** @SKB_DROP_REASON_TCP_CSUM: TCP checksum error */
+       SKB_DROP_REASON_TCP_CSUM,
+       /** @SKB_DROP_REASON_SOCKET_FILTER: dropped by socket filter */
+       SKB_DROP_REASON_SOCKET_FILTER,
+       /** @SKB_DROP_REASON_UDP_CSUM: UDP checksum error */
+       SKB_DROP_REASON_UDP_CSUM,
+       /** @SKB_DROP_REASON_NETFILTER_DROP: dropped by netfilter */
+       SKB_DROP_REASON_NETFILTER_DROP,
+       /**
+        * @SKB_DROP_REASON_OTHERHOST: packet don't belong to current host
+        * (interface is in promisc mode)
+        */
+       SKB_DROP_REASON_OTHERHOST,
+       /** @SKB_DROP_REASON_IP_CSUM: IP checksum error */
+       SKB_DROP_REASON_IP_CSUM,
+       /**
+        * @SKB_DROP_REASON_IP_INHDR: there is something wrong with IP header (see
+        * IPSTATS_MIB_INHDRERRORS)
+        */
+       SKB_DROP_REASON_IP_INHDR,
+       /**
+        * @SKB_DROP_REASON_IP_RPFILTER: IP rpfilter validate failed. see the
+        * document for rp_filter in ip-sysctl.rst for more information
+        */
+       SKB_DROP_REASON_IP_RPFILTER,
+       /**
+        * @SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST: destination address of L2 is
+        * multicast, but L3 is unicast.
+        */
+       SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST,
+       /** @SKB_DROP_REASON_XFRM_POLICY: xfrm policy check failed */
+       SKB_DROP_REASON_XFRM_POLICY,
+       /** @SKB_DROP_REASON_IP_NOPROTO: no support for IP protocol */
+       SKB_DROP_REASON_IP_NOPROTO,
+       /** @SKB_DROP_REASON_SOCKET_RCVBUFF: socket receive buff is full */
+       SKB_DROP_REASON_SOCKET_RCVBUFF,
+       /**
+        * @SKB_DROP_REASON_PROTO_MEM: proto memory limition, such as udp packet
+        * drop out of udp_memory_allocated.
+        */
+       SKB_DROP_REASON_PROTO_MEM,
+       /**
+        * @SKB_DROP_REASON_TCP_MD5NOTFOUND: no MD5 hash and one expected,
+        * corresponding to LINUX_MIB_TCPMD5NOTFOUND
+        */
+       SKB_DROP_REASON_TCP_MD5NOTFOUND,
+       /**
+        * @SKB_DROP_REASON_TCP_MD5UNEXPECTED: MD5 hash and we're not expecting
+        * one, corresponding to LINUX_MIB_TCPMD5UNEXPECTED
+        */
+       SKB_DROP_REASON_TCP_MD5UNEXPECTED,
+       /**
+        * @SKB_DROP_REASON_TCP_MD5FAILURE: MD5 hash and its wrong, corresponding
+        * to LINUX_MIB_TCPMD5FAILURE
+        */
+       SKB_DROP_REASON_TCP_MD5FAILURE,
+       /**
+        * @SKB_DROP_REASON_SOCKET_BACKLOG: failed to add skb to socket backlog (
+        * see LINUX_MIB_TCPBACKLOGDROP)
+        */
+       SKB_DROP_REASON_SOCKET_BACKLOG,
+       /** @SKB_DROP_REASON_TCP_FLAGS: TCP flags invalid */
+       SKB_DROP_REASON_TCP_FLAGS,
+       /**
+        * @SKB_DROP_REASON_TCP_ZEROWINDOW: TCP receive window size is zero,
+        * see LINUX_MIB_TCPZEROWINDOWDROP
+        */
+       SKB_DROP_REASON_TCP_ZEROWINDOW,
+       /**
+        * @SKB_DROP_REASON_TCP_OLD_DATA: the TCP data reveived is already
+        * received before (spurious retrans may happened), see
+        * LINUX_MIB_DELAYEDACKLOST
+        */
+       SKB_DROP_REASON_TCP_OLD_DATA,
+       /**
+        * @SKB_DROP_REASON_TCP_OVERWINDOW: the TCP data is out of window,
+        * the seq of the first byte exceed the right edges of receive
+        * window
+        */
+       SKB_DROP_REASON_TCP_OVERWINDOW,
+       /**
+        * @SKB_DROP_REASON_TCP_OFOMERGE: the data of skb is already in the ofo
+        * queue, corresponding to LINUX_MIB_TCPOFOMERGE
+        */
+       SKB_DROP_REASON_TCP_OFOMERGE,
+       /**
+        * @SKB_DROP_REASON_TCP_RFC7323_PAWS: PAWS check, corresponding to
+        * LINUX_MIB_PAWSESTABREJECTED
+        */
+       SKB_DROP_REASON_TCP_RFC7323_PAWS,
+       /** @SKB_DROP_REASON_TCP_INVALID_SEQUENCE: Not acceptable SEQ field */
+       SKB_DROP_REASON_TCP_INVALID_SEQUENCE,
+       /** @SKB_DROP_REASON_TCP_RESET: Invalid RST packet */
+       SKB_DROP_REASON_TCP_RESET,
+       /**
+        * @SKB_DROP_REASON_TCP_INVALID_SYN: Incoming packet has unexpected
+        * SYN flag
+        */
+       SKB_DROP_REASON_TCP_INVALID_SYN,
+       /** @SKB_DROP_REASON_TCP_CLOSE: TCP socket in CLOSE state */
+       SKB_DROP_REASON_TCP_CLOSE,
+       /** @SKB_DROP_REASON_TCP_FASTOPEN: dropped by FASTOPEN request socket */
+       SKB_DROP_REASON_TCP_FASTOPEN,
+       /** @SKB_DROP_REASON_TCP_OLD_ACK: TCP ACK is old, but in window */
+       SKB_DROP_REASON_TCP_OLD_ACK,
+       /** @SKB_DROP_REASON_TCP_TOO_OLD_ACK: TCP ACK is too old */
+       SKB_DROP_REASON_TCP_TOO_OLD_ACK,
+       /**
+        * @SKB_DROP_REASON_TCP_ACK_UNSENT_DATA: TCP ACK for data we haven't
+        * sent yet
+        */
+       SKB_DROP_REASON_TCP_ACK_UNSENT_DATA,
+       /** @SKB_DROP_REASON_TCP_OFO_QUEUE_PRUNE: pruned from TCP OFO queue */
+       SKB_DROP_REASON_TCP_OFO_QUEUE_PRUNE,
+       /** @SKB_DROP_REASON_TCP_OFO_DROP: data already in receive queue */
+       SKB_DROP_REASON_TCP_OFO_DROP,
+       /** @SKB_DROP_REASON_IP_OUTNOROUTES: route lookup failed */
+       SKB_DROP_REASON_IP_OUTNOROUTES,
+       /**
+        * @SKB_DROP_REASON_BPF_CGROUP_EGRESS: dropped by BPF_PROG_TYPE_CGROUP_SKB
+        * eBPF program
+        */
+       SKB_DROP_REASON_BPF_CGROUP_EGRESS,
+       /** @SKB_DROP_REASON_IPV6DISABLED: IPv6 is disabled on the device */
+       SKB_DROP_REASON_IPV6DISABLED,
+       /** @SKB_DROP_REASON_NEIGH_CREATEFAIL: failed to create neigh entry */
+       SKB_DROP_REASON_NEIGH_CREATEFAIL,
+       /** @SKB_DROP_REASON_NEIGH_FAILED: neigh entry in failed state */
+       SKB_DROP_REASON_NEIGH_FAILED,
+       /** @SKB_DROP_REASON_NEIGH_QUEUEFULL: arp_queue for neigh entry is full */
+       SKB_DROP_REASON_NEIGH_QUEUEFULL,
+       /** @SKB_DROP_REASON_NEIGH_DEAD: neigh entry is dead */
+       SKB_DROP_REASON_NEIGH_DEAD,
+       /** @SKB_DROP_REASON_TC_EGRESS: dropped in TC egress HOOK */
+       SKB_DROP_REASON_TC_EGRESS,
+       /**
+        * @SKB_DROP_REASON_QDISC_DROP: dropped by qdisc when packet outputting (
+        * failed to enqueue to current qdisc)
+        */
+       SKB_DROP_REASON_QDISC_DROP,
+       /**
+        * @SKB_DROP_REASON_CPU_BACKLOG: failed to enqueue the skb to the per CPU
+        * backlog queue. This can be caused by backlog queue full (see
+        * netdev_max_backlog in net.rst) or RPS flow limit
+        */
+       SKB_DROP_REASON_CPU_BACKLOG,
+       /** @SKB_DROP_REASON_XDP: dropped by XDP in input path */
+       SKB_DROP_REASON_XDP,
+       /** @SKB_DROP_REASON_TC_INGRESS: dropped in TC ingress HOOK */
+       SKB_DROP_REASON_TC_INGRESS,
+       /** @SKB_DROP_REASON_UNHANDLED_PROTO: protocol not implemented or not supported */
+       SKB_DROP_REASON_UNHANDLED_PROTO,
+       /** @SKB_DROP_REASON_SKB_CSUM: sk_buff checksum computation error */
+       SKB_DROP_REASON_SKB_CSUM,
+       /** @SKB_DROP_REASON_SKB_GSO_SEG: gso segmentation error */
+       SKB_DROP_REASON_SKB_GSO_SEG,
+       /**
+        * @SKB_DROP_REASON_SKB_UCOPY_FAULT: failed to copy data from user space,
+        * e.g., via zerocopy_sg_from_iter() or skb_orphan_frags_rx()
+        */
+       SKB_DROP_REASON_SKB_UCOPY_FAULT,
+       /** @SKB_DROP_REASON_DEV_HDR: device driver specific header/metadata is invalid */
+       SKB_DROP_REASON_DEV_HDR,
+       /**
+        * @SKB_DROP_REASON_DEV_READY: the device is not ready to xmit/recv due to
+        * any of its data structure that is not up/ready/initialized,
+        * e.g., the IFF_UP is not set, or driver specific tun->tfiles[txq]
+        * is not initialized
+        */
+       SKB_DROP_REASON_DEV_READY,
+       /** @SKB_DROP_REASON_FULL_RING: ring buffer is full */
+       SKB_DROP_REASON_FULL_RING,
+       /** @SKB_DROP_REASON_NOMEM: error due to OOM */
+       SKB_DROP_REASON_NOMEM,
+       /**
+        * @SKB_DROP_REASON_HDR_TRUNC: failed to trunc/extract the header from
+        * networking data, e.g., failed to pull the protocol header from
+        * frags via pskb_may_pull()
+        */
+       SKB_DROP_REASON_HDR_TRUNC,
+       /**
+        * @SKB_DROP_REASON_TAP_FILTER: dropped by (ebpf) filter directly attached
+        * to tun/tap, e.g., via TUNSETFILTEREBPF
+        */
+       SKB_DROP_REASON_TAP_FILTER,
+       /**
+        * @SKB_DROP_REASON_TAP_TXFILTER: dropped by tx filter implemented at
+        * tun/tap, e.g., check_filter()
+        */
+       SKB_DROP_REASON_TAP_TXFILTER,
+       /** @SKB_DROP_REASON_ICMP_CSUM: ICMP checksum error */
+       SKB_DROP_REASON_ICMP_CSUM,
+       /**
+        * @SKB_DROP_REASON_INVALID_PROTO: the packet doesn't follow RFC 2211,
+        * such as a broadcasts ICMP_TIMESTAMP
+        */
+       SKB_DROP_REASON_INVALID_PROTO,
+       /**
+        * @SKB_DROP_REASON_IP_INADDRERRORS: host unreachable, corresponding to
+        * IPSTATS_MIB_INADDRERRORS
+        */
+       SKB_DROP_REASON_IP_INADDRERRORS,
+       /**
+        * @SKB_DROP_REASON_IP_INNOROUTES: network unreachable, corresponding to
+        * IPSTATS_MIB_INADDRERRORS
+        */
+       SKB_DROP_REASON_IP_INNOROUTES,
+       /**
+        * @SKB_DROP_REASON_PKT_TOO_BIG: packet size is too big (maybe exceed the
+        * MTU)
+        */
+       SKB_DROP_REASON_PKT_TOO_BIG,
+       /**
+        * @SKB_DROP_REASON_MAX: the maximum of drop reason, which shouldn't be
+        * used as a real 'reason'
+        */
+       SKB_DROP_REASON_MAX,
+};
+
+#define SKB_DR_INIT(name, reason)                              \
+       enum skb_drop_reason name = SKB_DROP_REASON_##reason
+#define SKB_DR(name)                                           \
+       SKB_DR_INIT(name, NOT_SPECIFIED)
+#define SKB_DR_SET(name, reason)                               \
+       (name = SKB_DROP_REASON_##reason)
+#define SKB_DR_OR(name, reason)                                        \
+       do {                                                    \
+               if (name == SKB_DROP_REASON_NOT_SPECIFIED ||    \
+                   name == SKB_NOT_DROPPED_YET)                \
+                       SKB_DR_SET(name, reason);               \
+       } while (0)
+
+extern const char * const drop_reasons[];
+
+#endif
index c24fa93..70cbc4a 100644 (file)
@@ -456,8 +456,8 @@ static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len)
                struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats);
 
                u64_stats_update_begin(&tstats->syncp);
-               tstats->tx_bytes += pkt_len;
-               tstats->tx_packets++;
+               u64_stats_add(&tstats->tx_bytes, pkt_len);
+               u64_stats_inc(&tstats->tx_packets);
                u64_stats_update_end(&tstats->syncp);
                put_cpu_ptr(tstats);
        } else {
index ebadb21..5c9e97e 100644 (file)
@@ -1958,36 +1958,6 @@ struct ieee80211_key_seq {
        };
 };
 
-/**
- * struct ieee80211_cipher_scheme - cipher scheme
- *
- * This structure contains a cipher scheme information defining
- * the secure packet crypto handling.
- *
- * @cipher: a cipher suite selector
- * @iftype: a cipher iftype bit mask indicating an allowed cipher usage
- * @hdr_len: a length of a security header used the cipher
- * @pn_len: a length of a packet number in the security header
- * @pn_off: an offset of pn from the beginning of the security header
- * @key_idx_off: an offset of key index byte in the security header
- * @key_idx_mask: a bit mask of key_idx bits
- * @key_idx_shift: a bit shift needed to get key_idx
- *     key_idx value calculation:
- *      (sec_header_base[key_idx_off] & key_idx_mask) >> key_idx_shift
- * @mic_len: a mic length in bytes
- */
-struct ieee80211_cipher_scheme {
-       u32 cipher;
-       u16 iftype;
-       u8 hdr_len;
-       u8 pn_len;
-       u8 pn_off;
-       u8 key_idx_off;
-       u8 key_idx_mask;
-       u8 key_idx_shift;
-       u8 mic_len;
-};
-
 /**
  * enum set_key_cmd - key command
  *
@@ -2664,9 +2634,6 @@ enum ieee80211_hw_flags {
  *     deliver to a WMM STA during any Service Period triggered by the WMM STA.
  *     Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values.
  *
- * @n_cipher_schemes: a size of an array of cipher schemes definitions.
- * @cipher_schemes: a pointer to an array of cipher scheme definitions
- *     supported by HW.
  * @max_nan_de_entries: maximum number of NAN DE functions supported by the
  *     device.
  *
@@ -2716,8 +2683,6 @@ struct ieee80211_hw {
        netdev_features_t netdev_features;
        u8 uapsd_queues;
        u8 uapsd_max_sp_len;
-       u8 n_cipher_schemes;
-       const struct ieee80211_cipher_scheme *cipher_schemes;
        u8 max_nan_de_entries;
        u8 tx_sk_pacing_shift;
        u8 weight_multiplier;
index c585ef6..657873e 100644 (file)
@@ -611,7 +611,7 @@ void sock_net_set(struct sock *sk, struct net *net)
 
 int sk_set_peek_off(struct sock *sk, int val);
 
-static inline int sk_peek_offset(struct sock *sk, int flags)
+static inline int sk_peek_offset(const struct sock *sk, int flags)
 {
        if (unlikely(flags & MSG_PEEK)) {
                return READ_ONCE(sk->sk_peek_off);
@@ -863,7 +863,7 @@ static inline void sk_add_bind2_node(struct sock *sk, struct hlist_head *list)
                ({ tpos = (typeof(*tpos) *)((void *)pos - offset); 1;});       \
             pos = rcu_dereference(hlist_next_rcu(pos)))
 
-static inline struct user_namespace *sk_user_ns(struct sock *sk)
+static inline struct user_namespace *sk_user_ns(const struct sock *sk)
 {
        /* Careful only use this in a context where these parameters
         * can not change and must all be valid, such as recvmsg from
@@ -909,7 +909,7 @@ enum sock_flags {
 
 #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
 
-static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
+static inline void sock_copy_flags(struct sock *nsk, const struct sock *osk)
 {
        nsk->sk_flags = osk->sk_flags;
 }
index c39d910..9287712 100644 (file)
@@ -1923,7 +1923,7 @@ static inline void xfrm_dev_state_free(struct xfrm_state *x)
                if (dev->xfrmdev_ops->xdo_dev_state_free)
                        dev->xfrmdev_ops->xdo_dev_state_free(x);
                xso->dev = NULL;
-               dev_put_track(dev, &xso->dev_tracker);
+               netdev_put(dev, &xso->dev_tracker);
        }
 }
 #else
index a477bf9..45264e4 100644 (file)
@@ -9,92 +9,6 @@
 #include <linux/netdevice.h>
 #include <linux/tracepoint.h>
 
-#define TRACE_SKB_DROP_REASON                                  \
-       EM(SKB_DROP_REASON_NOT_SPECIFIED, NOT_SPECIFIED)        \
-       EM(SKB_DROP_REASON_NO_SOCKET, NO_SOCKET)                \
-       EM(SKB_DROP_REASON_PKT_TOO_SMALL, PKT_TOO_SMALL)        \
-       EM(SKB_DROP_REASON_TCP_CSUM, TCP_CSUM)                  \
-       EM(SKB_DROP_REASON_SOCKET_FILTER, SOCKET_FILTER)        \
-       EM(SKB_DROP_REASON_UDP_CSUM, UDP_CSUM)                  \
-       EM(SKB_DROP_REASON_NETFILTER_DROP, NETFILTER_DROP)      \
-       EM(SKB_DROP_REASON_OTHERHOST, OTHERHOST)                \
-       EM(SKB_DROP_REASON_IP_CSUM, IP_CSUM)                    \
-       EM(SKB_DROP_REASON_IP_INHDR, IP_INHDR)                  \
-       EM(SKB_DROP_REASON_IP_RPFILTER, IP_RPFILTER)            \
-       EM(SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST,             \
-          UNICAST_IN_L2_MULTICAST)                             \
-       EM(SKB_DROP_REASON_XFRM_POLICY, XFRM_POLICY)            \
-       EM(SKB_DROP_REASON_IP_NOPROTO, IP_NOPROTO)              \
-       EM(SKB_DROP_REASON_SOCKET_RCVBUFF, SOCKET_RCVBUFF)      \
-       EM(SKB_DROP_REASON_PROTO_MEM, PROTO_MEM)                \
-       EM(SKB_DROP_REASON_TCP_MD5NOTFOUND, TCP_MD5NOTFOUND)    \
-       EM(SKB_DROP_REASON_TCP_MD5UNEXPECTED,                   \
-          TCP_MD5UNEXPECTED)                                   \
-       EM(SKB_DROP_REASON_TCP_MD5FAILURE, TCP_MD5FAILURE)      \
-       EM(SKB_DROP_REASON_SOCKET_BACKLOG, SOCKET_BACKLOG)      \
-       EM(SKB_DROP_REASON_TCP_FLAGS, TCP_FLAGS)                \
-       EM(SKB_DROP_REASON_TCP_ZEROWINDOW, TCP_ZEROWINDOW)      \
-       EM(SKB_DROP_REASON_TCP_OLD_DATA, TCP_OLD_DATA)          \
-       EM(SKB_DROP_REASON_TCP_OVERWINDOW, TCP_OVERWINDOW)      \
-       EM(SKB_DROP_REASON_TCP_OFOMERGE, TCP_OFOMERGE)          \
-       EM(SKB_DROP_REASON_TCP_OFO_DROP, TCP_OFO_DROP)          \
-       EM(SKB_DROP_REASON_TCP_RFC7323_PAWS, TCP_RFC7323_PAWS)  \
-       EM(SKB_DROP_REASON_TCP_INVALID_SEQUENCE,                \
-          TCP_INVALID_SEQUENCE)                                \
-       EM(SKB_DROP_REASON_TCP_RESET, TCP_RESET)                \
-       EM(SKB_DROP_REASON_TCP_INVALID_SYN, TCP_INVALID_SYN)    \
-       EM(SKB_DROP_REASON_TCP_CLOSE, TCP_CLOSE)                \
-       EM(SKB_DROP_REASON_TCP_FASTOPEN, TCP_FASTOPEN)          \
-       EM(SKB_DROP_REASON_TCP_OLD_ACK, TCP_OLD_ACK)            \
-       EM(SKB_DROP_REASON_TCP_TOO_OLD_ACK, TCP_TOO_OLD_ACK)    \
-       EM(SKB_DROP_REASON_TCP_ACK_UNSENT_DATA,                 \
-          TCP_ACK_UNSENT_DATA)                                 \
-       EM(SKB_DROP_REASON_TCP_OFO_QUEUE_PRUNE,                 \
-         TCP_OFO_QUEUE_PRUNE)                                  \
-       EM(SKB_DROP_REASON_IP_OUTNOROUTES, IP_OUTNOROUTES)      \
-       EM(SKB_DROP_REASON_BPF_CGROUP_EGRESS,                   \
-          BPF_CGROUP_EGRESS)                                   \
-       EM(SKB_DROP_REASON_IPV6DISABLED, IPV6DISABLED)          \
-       EM(SKB_DROP_REASON_NEIGH_CREATEFAIL, NEIGH_CREATEFAIL)  \
-       EM(SKB_DROP_REASON_NEIGH_FAILED, NEIGH_FAILED)          \
-       EM(SKB_DROP_REASON_NEIGH_QUEUEFULL, NEIGH_QUEUEFULL)    \
-       EM(SKB_DROP_REASON_NEIGH_DEAD, NEIGH_DEAD)              \
-       EM(SKB_DROP_REASON_TC_EGRESS, TC_EGRESS)                \
-       EM(SKB_DROP_REASON_QDISC_DROP, QDISC_DROP)              \
-       EM(SKB_DROP_REASON_CPU_BACKLOG, CPU_BACKLOG)            \
-       EM(SKB_DROP_REASON_XDP, XDP)                            \
-       EM(SKB_DROP_REASON_TC_INGRESS, TC_INGRESS)              \
-       EM(SKB_DROP_REASON_UNHANDLED_PROTO, UNHANDLED_PROTO)    \
-       EM(SKB_DROP_REASON_SKB_CSUM, SKB_CSUM)                  \
-       EM(SKB_DROP_REASON_SKB_GSO_SEG, SKB_GSO_SEG)            \
-       EM(SKB_DROP_REASON_SKB_UCOPY_FAULT, SKB_UCOPY_FAULT)    \
-       EM(SKB_DROP_REASON_DEV_HDR, DEV_HDR)                    \
-       EM(SKB_DROP_REASON_DEV_READY, DEV_READY)                \
-       EM(SKB_DROP_REASON_FULL_RING, FULL_RING)                \
-       EM(SKB_DROP_REASON_NOMEM, NOMEM)                        \
-       EM(SKB_DROP_REASON_HDR_TRUNC, HDR_TRUNC)                \
-       EM(SKB_DROP_REASON_TAP_FILTER, TAP_FILTER)              \
-       EM(SKB_DROP_REASON_TAP_TXFILTER, TAP_TXFILTER)          \
-       EM(SKB_DROP_REASON_ICMP_CSUM, ICMP_CSUM)                \
-       EM(SKB_DROP_REASON_INVALID_PROTO, INVALID_PROTO)        \
-       EM(SKB_DROP_REASON_IP_INADDRERRORS, IP_INADDRERRORS)    \
-       EM(SKB_DROP_REASON_IP_INNOROUTES, IP_INNOROUTES)        \
-       EM(SKB_DROP_REASON_PKT_TOO_BIG, PKT_TOO_BIG)            \
-       EMe(SKB_DROP_REASON_MAX, MAX)
-
-#undef EM
-#undef EMe
-
-#define EM(a, b)       TRACE_DEFINE_ENUM(a);
-#define EMe(a, b)      TRACE_DEFINE_ENUM(a);
-
-TRACE_SKB_DROP_REASON
-
-#undef EM
-#undef EMe
-#define EM(a, b)       { a, #b },
-#define EMe(a, b)      { a, #b }
-
 /*
  * Tracepoint for free an sk_buff:
  */
@@ -121,8 +35,7 @@ TRACE_EVENT(kfree_skb,
 
        TP_printk("skbaddr=%p protocol=%u location=%p reason: %s",
                  __entry->skbaddr, __entry->protocol, __entry->location,
-                 __print_symbolic(__entry->reason,
-                                  TRACE_SKB_DROP_REASON))
+                 drop_reasons[__entry->reason])
 );
 
 TRACE_EVENT(consume_skb,
index d9490e3..98f905f 100644 (file)
@@ -5874,7 +5874,7 @@ enum nl80211_ap_sme_features {
  * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up
  *     the connected inactive stations in AP mode.
  * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested
- *     to work properly to suppport receiving regulatory hints from
+ *     to work properly to support receiving regulatory hints from
  *     cellular base stations.
  * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only
  *     here to reserve the value for API/ABI compatibility)
index d6bbbd4..7b37459 100644 (file)
 
 #include "nhc.h"
 
-static struct rb_root rb_root = RB_ROOT;
-static struct lowpan_nhc *lowpan_nexthdr_nhcs[NEXTHDR_MAX + 1];
+static const struct lowpan_nhc *lowpan_nexthdr_nhcs[NEXTHDR_MAX + 1];
 static DEFINE_SPINLOCK(lowpan_nhc_lock);
 
-static int lowpan_nhc_insert(struct lowpan_nhc *nhc)
+static const struct lowpan_nhc *lowpan_nhc_by_nhcid(struct sk_buff *skb)
 {
-       struct rb_node **new = &rb_root.rb_node, *parent = NULL;
-
-       /* Figure out where to put new node */
-       while (*new) {
-               struct lowpan_nhc *this = rb_entry(*new, struct lowpan_nhc,
-                                                  node);
-               int result, len_dif, len;
-
-               len_dif = nhc->idlen - this->idlen;
-
-               if (nhc->idlen < this->idlen)
-                       len = nhc->idlen;
-               else
-                       len = this->idlen;
-
-               result = memcmp(nhc->id, this->id, len);
-               if (!result)
-                       result = len_dif;
-
-               parent = *new;
-               if (result < 0)
-                       new = &((*new)->rb_left);
-               else if (result > 0)
-                       new = &((*new)->rb_right);
-               else
-                       return -EEXIST;
-       }
+       const struct lowpan_nhc *nhc;
+       int i;
+       u8 id;
 
-       /* Add new node and rebalance tree. */
-       rb_link_node(&nhc->node, parent, new);
-       rb_insert_color(&nhc->node, &rb_root);
+       if (!pskb_may_pull(skb, 1))
+               return NULL;
 
-       return 0;
-}
+       id = *skb->data;
 
-static void lowpan_nhc_remove(struct lowpan_nhc *nhc)
-{
-       rb_erase(&nhc->node, &rb_root);
-}
+       for (i = 0; i < NEXTHDR_MAX + 1; i++) {
+               nhc = lowpan_nexthdr_nhcs[i];
+               if (!nhc)
+                       continue;
 
-static struct lowpan_nhc *lowpan_nhc_by_nhcid(const struct sk_buff *skb)
-{
-       struct rb_node *node = rb_root.rb_node;
-       const u8 *nhcid_skb_ptr = skb->data;
-
-       while (node) {
-               struct lowpan_nhc *nhc = rb_entry(node, struct lowpan_nhc,
-                                                 node);
-               u8 nhcid_skb_ptr_masked[LOWPAN_NHC_MAX_ID_LEN];
-               int result, i;
-
-               if (nhcid_skb_ptr + nhc->idlen > skb->data + skb->len)
-                       return NULL;
-
-               /* copy and mask afterwards the nhid value from skb */
-               memcpy(nhcid_skb_ptr_masked, nhcid_skb_ptr, nhc->idlen);
-               for (i = 0; i < nhc->idlen; i++)
-                       nhcid_skb_ptr_masked[i] &= nhc->idmask[i];
-
-               result = memcmp(nhcid_skb_ptr_masked, nhc->id, nhc->idlen);
-               if (result < 0)
-                       node = node->rb_left;
-               else if (result > 0)
-                       node = node->rb_right;
-               else
+               if ((id & nhc->idmask) == nhc->id)
                        return nhc;
        }
 
@@ -92,7 +41,7 @@ static struct lowpan_nhc *lowpan_nhc_by_nhcid(const struct sk_buff *skb)
 int lowpan_nhc_check_compression(struct sk_buff *skb,
                                 const struct ipv6hdr *hdr, u8 **hc_ptr)
 {
-       struct lowpan_nhc *nhc;
+       const struct lowpan_nhc *nhc;
        int ret = 0;
 
        spin_lock_bh(&lowpan_nhc_lock);
@@ -110,7 +59,7 @@ int lowpan_nhc_do_compression(struct sk_buff *skb, const struct ipv6hdr *hdr,
                              u8 **hc_ptr)
 {
        int ret;
-       struct lowpan_nhc *nhc;
+       const struct lowpan_nhc *nhc;
 
        spin_lock_bh(&lowpan_nhc_lock);
 
@@ -153,7 +102,7 @@ int lowpan_nhc_do_uncompression(struct sk_buff *skb,
                                const struct net_device *dev,
                                struct ipv6hdr *hdr)
 {
-       struct lowpan_nhc *nhc;
+       const struct lowpan_nhc *nhc;
        int ret;
 
        spin_lock_bh(&lowpan_nhc_lock);
@@ -189,18 +138,9 @@ int lowpan_nhc_do_uncompression(struct sk_buff *skb,
        return 0;
 }
 
-int lowpan_nhc_add(struct lowpan_nhc *nhc)
+int lowpan_nhc_add(const struct lowpan_nhc *nhc)
 {
-       int ret;
-
-       if (!nhc->idlen || !nhc->idsetup)
-               return -EINVAL;
-
-       WARN_ONCE(nhc->idlen > LOWPAN_NHC_MAX_ID_LEN,
-                 "LOWPAN_NHC_MAX_ID_LEN should be updated to %zd.\n",
-                 nhc->idlen);
-
-       nhc->idsetup(nhc);
+       int ret = 0;
 
        spin_lock_bh(&lowpan_nhc_lock);
 
@@ -209,10 +149,6 @@ int lowpan_nhc_add(struct lowpan_nhc *nhc)
                goto out;
        }
 
-       ret = lowpan_nhc_insert(nhc);
-       if (ret < 0)
-               goto out;
-
        lowpan_nexthdr_nhcs[nhc->nexthdr] = nhc;
 out:
        spin_unlock_bh(&lowpan_nhc_lock);
@@ -220,11 +156,10 @@ out:
 }
 EXPORT_SYMBOL(lowpan_nhc_add);
 
-void lowpan_nhc_del(struct lowpan_nhc *nhc)
+void lowpan_nhc_del(const struct lowpan_nhc *nhc)
 {
        spin_lock_bh(&lowpan_nhc_lock);
 
-       lowpan_nhc_remove(nhc);
        lowpan_nexthdr_nhcs[nhc->nexthdr] = NULL;
 
        spin_unlock_bh(&lowpan_nhc_lock);
index 67951c4..ab7b497 100644 (file)
  * @_name: const char * of common header compression name.
  * @_nexthdr: ipv6 nexthdr field for the header compression.
  * @_nexthdrlen: ipv6 nexthdr len for the reserved space.
- * @_idsetup: callback to setup id and mask values.
- * @_idlen: len for the next header id and mask, should be always the same.
+ * @_id: one byte nhc id value.
+ * @_idmask: one byte nhc id mask value.
  * @_uncompress: callback for uncompression call.
  * @_compress: callback for compression call.
  */
 #define LOWPAN_NHC(__nhc, _name, _nexthdr,     \
-                  _hdrlen, _idsetup, _idlen,   \
+                  _hdrlen, _id, _idmask,       \
                   _uncompress, _compress)      \
-static u8 __nhc##_val[_idlen];                 \
-static u8 __nhc##_mask[_idlen];                        \
-static struct lowpan_nhc __nhc = {             \
+static const struct lowpan_nhc __nhc = {       \
        .name           = _name,                \
        .nexthdr        = _nexthdr,             \
        .nexthdrlen     = _hdrlen,              \
-       .id             = __nhc##_val,          \
-       .idmask         = __nhc##_mask,         \
-       .idlen          = _idlen,               \
-       .idsetup        = _idsetup,             \
+       .id             = _id,                  \
+       .idmask         = _idmask,              \
        .uncompress     = _uncompress,          \
        .compress       = _compress,            \
 }
@@ -53,27 +49,21 @@ module_exit(__nhc##_exit);
 /**
  * struct lowpan_nhc - hold 6lowpan next hdr compression ifnformation
  *
- * @node: holder for the rbtree.
  * @name: name of the specific next header compression
  * @nexthdr: next header value of the protocol which should be compressed.
  * @nexthdrlen: ipv6 nexthdr len for the reserved space.
- * @id: array for nhc id. Note this need to be in network byteorder.
- * @mask: array for nhc id mask. Note this need to be in network byteorder.
- * @len: the length of the next header id and mask.
- * @setup: callback to setup fill the next header id value and mask.
+ * @id: one byte nhc id value.
+ * @idmask: one byte nhc id mask value.
  * @compress: callback to do the header compression.
  * @uncompress: callback to do the header uncompression.
  */
 struct lowpan_nhc {
-       struct rb_node  node;
        const char      *name;
-       const u8        nexthdr;
-       const size_t    nexthdrlen;
-       u8              *id;
-       u8              *idmask;
-       const size_t    idlen;
+       u8              nexthdr;
+       size_t          nexthdrlen;
+       u8              id;
+       u8              idmask;
 
-       void            (*idsetup)(struct lowpan_nhc *nhc);
        int             (*uncompress)(struct sk_buff *skb, size_t needed);
        int             (*compress)(struct sk_buff *skb, u8 **hc_ptr);
 };
@@ -126,14 +116,14 @@ int lowpan_nhc_do_uncompression(struct sk_buff *skb,
  *
  * @nhc: nhc which should be add.
  */
-int lowpan_nhc_add(struct lowpan_nhc *nhc);
+int lowpan_nhc_add(const struct lowpan_nhc *nhc);
 
 /**
  * lowpan_nhc_del - delete a next header compression from framework
  *
  * @nhc: nhc which should be delete.
  */
-void lowpan_nhc_del(struct lowpan_nhc *nhc);
+void lowpan_nhc_del(const struct lowpan_nhc *nhc);
 
 /**
  * lowpan_nhc_init - adding all default nhcs
index 4768a94..0cbcc78 100644 (file)
@@ -6,18 +6,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_NHC_DEST_IDLEN  1
 #define LOWPAN_NHC_DEST_ID_0   0xe6
 #define LOWPAN_NHC_DEST_MASK_0 0xfe
 
-static void dest_nhid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_NHC_DEST_ID_0;
-       nhc->idmask[0] = LOWPAN_NHC_DEST_MASK_0;
-}
-
 LOWPAN_NHC(nhc_dest, "RFC6282 Destination Options", NEXTHDR_DEST, 0,
-          dest_nhid_setup, LOWPAN_NHC_DEST_IDLEN, NULL, NULL);
+          LOWPAN_NHC_DEST_ID_0, LOWPAN_NHC_DEST_MASK_0,  NULL, NULL);
 
 module_lowpan_nhc(nhc_dest);
 MODULE_DESCRIPTION("6LoWPAN next header RFC6282 Destination Options compression");
index be85f07..9414552 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_NHC_FRAGMENT_IDLEN      1
 #define LOWPAN_NHC_FRAGMENT_ID_0       0xe4
 #define LOWPAN_NHC_FRAGMENT_MASK_0     0xfe
 
-static void fragment_nhid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_NHC_FRAGMENT_ID_0;
-       nhc->idmask[0] = LOWPAN_NHC_FRAGMENT_MASK_0;
-}
-
 LOWPAN_NHC(nhc_fragment, "RFC6282 Fragment", NEXTHDR_FRAGMENT, 0,
-          fragment_nhid_setup, LOWPAN_NHC_FRAGMENT_IDLEN, NULL, NULL);
+          LOWPAN_NHC_FRAGMENT_ID_0, LOWPAN_NHC_FRAGMENT_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(nhc_fragment);
 MODULE_DESCRIPTION("6LoWPAN next header RFC6282 Fragment compression");
index a9137f1..e4745dd 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_GHC_EXT_DEST_IDLEN      1
 #define LOWPAN_GHC_EXT_DEST_ID_0       0xb6
 #define LOWPAN_GHC_EXT_DEST_MASK_0     0xfe
 
-static void dest_ghid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_GHC_EXT_DEST_ID_0;
-       nhc->idmask[0] = LOWPAN_GHC_EXT_DEST_MASK_0;
-}
-
 LOWPAN_NHC(ghc_ext_dest, "RFC7400 Destination Extension Header", NEXTHDR_DEST,
-          0, dest_ghid_setup, LOWPAN_GHC_EXT_DEST_IDLEN, NULL, NULL);
+          0, LOWPAN_GHC_EXT_DEST_ID_0, LOWPAN_GHC_EXT_DEST_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(ghc_ext_dest);
 MODULE_DESCRIPTION("6LoWPAN generic header destination extension compression");
index d49b745..220e5ab 100644 (file)
@@ -5,19 +5,12 @@
 
 #include "nhc.h"
 
-#define LOWPAN_GHC_EXT_FRAG_IDLEN      1
 #define LOWPAN_GHC_EXT_FRAG_ID_0       0xb4
 #define LOWPAN_GHC_EXT_FRAG_MASK_0     0xfe
 
-static void frag_ghid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_GHC_EXT_FRAG_ID_0;
-       nhc->idmask[0] = LOWPAN_GHC_EXT_FRAG_MASK_0;
-}
-
 LOWPAN_NHC(ghc_ext_frag, "RFC7400 Fragmentation Extension Header",
-          NEXTHDR_FRAGMENT, 0, frag_ghid_setup,
-          LOWPAN_GHC_EXT_FRAG_IDLEN, NULL, NULL);
+          NEXTHDR_FRAGMENT, 0, LOWPAN_GHC_EXT_FRAG_ID_0,
+          LOWPAN_GHC_EXT_FRAG_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(ghc_ext_frag);
 MODULE_DESCRIPTION("6LoWPAN generic header fragmentation extension compression");
index 3beedf5..9b0de4d 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_GHC_EXT_HOP_IDLEN       1
 #define LOWPAN_GHC_EXT_HOP_ID_0                0xb0
 #define LOWPAN_GHC_EXT_HOP_MASK_0      0xfe
 
-static void hop_ghid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_GHC_EXT_HOP_ID_0;
-       nhc->idmask[0] = LOWPAN_GHC_EXT_HOP_MASK_0;
-}
-
 LOWPAN_NHC(ghc_ext_hop, "RFC7400 Hop-by-Hop Extension Header", NEXTHDR_HOP, 0,
-          hop_ghid_setup, LOWPAN_GHC_EXT_HOP_IDLEN, NULL, NULL);
+          LOWPAN_GHC_EXT_HOP_ID_0, LOWPAN_GHC_EXT_HOP_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(ghc_ext_hop);
 MODULE_DESCRIPTION("6LoWPAN generic header hop-by-hop extension compression");
index 70dc0ea..3e86fae 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_GHC_EXT_ROUTE_IDLEN     1
 #define LOWPAN_GHC_EXT_ROUTE_ID_0      0xb2
 #define LOWPAN_GHC_EXT_ROUTE_MASK_0    0xfe
 
-static void route_ghid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_GHC_EXT_ROUTE_ID_0;
-       nhc->idmask[0] = LOWPAN_GHC_EXT_ROUTE_MASK_0;
-}
-
 LOWPAN_NHC(ghc_ext_route, "RFC7400 Routing Extension Header", NEXTHDR_ROUTING,
-          0, route_ghid_setup, LOWPAN_GHC_EXT_ROUTE_IDLEN, NULL, NULL);
+          0, LOWPAN_GHC_EXT_ROUTE_ID_0, LOWPAN_GHC_EXT_ROUTE_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(ghc_ext_route);
 MODULE_DESCRIPTION("6LoWPAN generic header routing extension compression");
index 339ceff..1634f3e 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_GHC_ICMPV6_IDLEN                1
 #define LOWPAN_GHC_ICMPV6_ID_0         0xdf
 #define LOWPAN_GHC_ICMPV6_MASK_0       0xff
 
-static void icmpv6_ghid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_GHC_ICMPV6_ID_0;
-       nhc->idmask[0] = LOWPAN_GHC_ICMPV6_MASK_0;
-}
-
 LOWPAN_NHC(ghc_icmpv6, "RFC7400 ICMPv6", NEXTHDR_ICMP, 0,
-          icmpv6_ghid_setup, LOWPAN_GHC_ICMPV6_IDLEN, NULL, NULL);
+          LOWPAN_GHC_ICMPV6_ID_0, LOWPAN_GHC_ICMPV6_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(ghc_icmpv6);
 MODULE_DESCRIPTION("6LoWPAN generic header ICMPv6 compression");
index f47fec6..4ac4813 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_GHC_UDP_IDLEN   1
 #define LOWPAN_GHC_UDP_ID_0    0xd0
 #define LOWPAN_GHC_UDP_MASK_0  0xf8
 
-static void udp_ghid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_GHC_UDP_ID_0;
-       nhc->idmask[0] = LOWPAN_GHC_UDP_MASK_0;
-}
-
 LOWPAN_NHC(ghc_udp, "RFC7400 UDP", NEXTHDR_UDP, 0,
-          udp_ghid_setup, LOWPAN_GHC_UDP_IDLEN, NULL, NULL);
+          LOWPAN_GHC_UDP_ID_0, LOWPAN_GHC_UDP_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(ghc_udp);
 MODULE_DESCRIPTION("6LoWPAN generic header UDP compression");
index 158fc19..182087d 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_NHC_HOP_IDLEN   1
 #define LOWPAN_NHC_HOP_ID_0    0xe0
 #define LOWPAN_NHC_HOP_MASK_0  0xfe
 
-static void hop_nhid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_NHC_HOP_ID_0;
-       nhc->idmask[0] = LOWPAN_NHC_HOP_MASK_0;
-}
-
 LOWPAN_NHC(nhc_hop, "RFC6282 Hop-by-Hop Options", NEXTHDR_HOP, 0,
-          hop_nhid_setup, LOWPAN_NHC_HOP_IDLEN, NULL, NULL);
+          LOWPAN_NHC_HOP_ID_0, LOWPAN_NHC_HOP_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(nhc_hop);
 MODULE_DESCRIPTION("6LoWPAN next header RFC6282 Hop-by-Hop Options compression");
index 08b7589..2024236 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_NHC_IPV6_IDLEN  1
 #define LOWPAN_NHC_IPV6_ID_0   0xee
 #define LOWPAN_NHC_IPV6_MASK_0 0xfe
 
-static void ipv6_nhid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_NHC_IPV6_ID_0;
-       nhc->idmask[0] = LOWPAN_NHC_IPV6_MASK_0;
-}
-
-LOWPAN_NHC(nhc_ipv6, "RFC6282 IPv6", NEXTHDR_IPV6, 0, ipv6_nhid_setup,
-          LOWPAN_NHC_IPV6_IDLEN, NULL, NULL);
+LOWPAN_NHC(nhc_ipv6, "RFC6282 IPv6", NEXTHDR_IPV6, 0, LOWPAN_NHC_IPV6_ID_0,
+          LOWPAN_NHC_IPV6_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(nhc_ipv6);
 MODULE_DESCRIPTION("6LoWPAN next header RFC6282 IPv6 compression");
index ac8fca6..1c31d87 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_NHC_MOBILITY_IDLEN      1
 #define LOWPAN_NHC_MOBILITY_ID_0       0xe8
 #define LOWPAN_NHC_MOBILITY_MASK_0     0xfe
 
-static void mobility_nhid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_NHC_MOBILITY_ID_0;
-       nhc->idmask[0] = LOWPAN_NHC_MOBILITY_MASK_0;
-}
-
 LOWPAN_NHC(nhc_mobility, "RFC6282 Mobility", NEXTHDR_MOBILITY, 0,
-          mobility_nhid_setup, LOWPAN_NHC_MOBILITY_IDLEN, NULL, NULL);
+          LOWPAN_NHC_MOBILITY_ID_0, LOWPAN_NHC_MOBILITY_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(nhc_mobility);
 MODULE_DESCRIPTION("6LoWPAN next header RFC6282 Mobility compression");
index 1c17402..dae03eb 100644 (file)
@@ -5,18 +5,11 @@
 
 #include "nhc.h"
 
-#define LOWPAN_NHC_ROUTING_IDLEN       1
 #define LOWPAN_NHC_ROUTING_ID_0                0xe2
 #define LOWPAN_NHC_ROUTING_MASK_0      0xfe
 
-static void routing_nhid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_NHC_ROUTING_ID_0;
-       nhc->idmask[0] = LOWPAN_NHC_ROUTING_MASK_0;
-}
-
 LOWPAN_NHC(nhc_routing, "RFC6282 Routing", NEXTHDR_ROUTING, 0,
-          routing_nhid_setup, LOWPAN_NHC_ROUTING_IDLEN, NULL, NULL);
+          LOWPAN_NHC_ROUTING_ID_0, LOWPAN_NHC_ROUTING_MASK_0, NULL, NULL);
 
 module_lowpan_nhc(nhc_routing);
 MODULE_DESCRIPTION("6LoWPAN next header RFC6282 Routing compression");
index 33f17bd..0a506c7 100644 (file)
@@ -14,7 +14,6 @@
 
 #define LOWPAN_NHC_UDP_MASK            0xF8
 #define LOWPAN_NHC_UDP_ID              0xF0
-#define LOWPAN_NHC_UDP_IDLEN           1
 
 #define LOWPAN_NHC_UDP_4BIT_PORT       0xF0B0
 #define LOWPAN_NHC_UDP_4BIT_MASK       0xFFF0
@@ -169,14 +168,8 @@ static int udp_compress(struct sk_buff *skb, u8 **hc_ptr)
        return 0;
 }
 
-static void udp_nhid_setup(struct lowpan_nhc *nhc)
-{
-       nhc->id[0] = LOWPAN_NHC_UDP_ID;
-       nhc->idmask[0] = LOWPAN_NHC_UDP_MASK;
-}
-
 LOWPAN_NHC(nhc_udp, "RFC6282 UDP", NEXTHDR_UDP, sizeof(struct udphdr),
-          udp_nhid_setup, LOWPAN_NHC_UDP_IDLEN, udp_uncompress, udp_compress);
+          LOWPAN_NHC_UDP_ID, LOWPAN_NHC_UDP_MASK, udp_uncompress, udp_compress);
 
 module_lowpan_nhc(nhc_udp);
 MODULE_DESCRIPTION("6LoWPAN next header RFC6282 UDP compression");
index acf8c79..5aa8144 100644 (file)
@@ -63,10 +63,10 @@ bool vlan_do_receive(struct sk_buff **skbp)
        rx_stats = this_cpu_ptr(vlan_dev_priv(vlan_dev)->vlan_pcpu_stats);
 
        u64_stats_update_begin(&rx_stats->syncp);
-       rx_stats->rx_packets++;
-       rx_stats->rx_bytes += skb->len;
+       u64_stats_inc(&rx_stats->rx_packets);
+       u64_stats_add(&rx_stats->rx_bytes, skb->len);
        if (skb->pkt_type == PACKET_MULTICAST)
-               rx_stats->rx_multicast++;
+               u64_stats_inc(&rx_stats->rx_multicast);
        u64_stats_update_end(&rx_stats->syncp);
 
        return true;
index 839f202..035812b 100644 (file)
@@ -128,8 +128,8 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
 
                stats = this_cpu_ptr(vlan->vlan_pcpu_stats);
                u64_stats_update_begin(&stats->syncp);
-               stats->tx_packets++;
-               stats->tx_bytes += len;
+               u64_stats_inc(&stats->tx_packets);
+               u64_stats_add(&stats->tx_bytes, len);
                u64_stats_update_end(&stats->syncp);
        } else {
                this_cpu_inc(vlan->vlan_pcpu_stats->tx_dropped);
@@ -615,7 +615,7 @@ static int vlan_dev_init(struct net_device *dev)
                return -ENOMEM;
 
        /* Get vlan's reference to real_dev */
-       dev_hold_track(real_dev, &vlan->dev_tracker, GFP_KERNEL);
+       netdev_hold(real_dev, &vlan->dev_tracker, GFP_KERNEL);
 
        return 0;
 }
@@ -713,11 +713,11 @@ static void vlan_dev_get_stats64(struct net_device *dev,
                p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i);
                do {
                        start = u64_stats_fetch_begin_irq(&p->syncp);
-                       rxpackets       = p->rx_packets;
-                       rxbytes         = p->rx_bytes;
-                       rxmulticast     = p->rx_multicast;
-                       txpackets       = p->tx_packets;
-                       txbytes         = p->tx_bytes;
+                       rxpackets       = u64_stats_read(&p->rx_packets);
+                       rxbytes         = u64_stats_read(&p->rx_bytes);
+                       rxmulticast     = u64_stats_read(&p->rx_multicast);
+                       txpackets       = u64_stats_read(&p->tx_packets);
+                       txbytes         = u64_stats_read(&p->tx_bytes);
                } while (u64_stats_fetch_retry_irq(&p->syncp, start));
 
                stats->rx_packets       += rxpackets;
@@ -726,8 +726,8 @@ static void vlan_dev_get_stats64(struct net_device *dev,
                stats->tx_packets       += txpackets;
                stats->tx_bytes         += txbytes;
                /* rx_errors & tx_dropped are u32 */
-               rx_errors       += p->rx_errors;
-               tx_dropped      += p->tx_dropped;
+               rx_errors       += READ_ONCE(p->rx_errors);
+               tx_dropped      += READ_ONCE(p->tx_dropped);
        }
        stats->rx_errors  = rx_errors;
        stats->tx_dropped = tx_dropped;
@@ -852,7 +852,7 @@ static void vlan_dev_free(struct net_device *dev)
        vlan->vlan_pcpu_stats = NULL;
 
        /* Get rid of the vlan's reference to real_dev */
-       dev_put_track(vlan->real_dev, &vlan->dev_tracker);
+       netdev_put(vlan->real_dev, &vlan->dev_tracker);
 }
 
 void vlan_setup(struct net_device *dev)
index 95393bb..1a5c0b0 100644 (file)
@@ -102,7 +102,8 @@ again:
                        ax25_disconnect(s, ENETUNREACH);
                        s->ax25_dev = NULL;
                        if (sk->sk_socket) {
-                               dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+                               netdev_put(ax25_dev->dev,
+                                          &ax25_dev->dev_tracker);
                                ax25_dev_put(ax25_dev);
                        }
                        ax25_cb_del(s);
@@ -1065,7 +1066,7 @@ static int ax25_release(struct socket *sock)
                        del_timer_sync(&ax25->t3timer);
                        del_timer_sync(&ax25->idletimer);
                }
-               dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+               netdev_put(ax25_dev->dev, &ax25_dev->dev_tracker);
                ax25_dev_put(ax25_dev);
        }
 
@@ -1146,7 +1147,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
        if (ax25_dev) {
                ax25_fillin_cb(ax25, ax25_dev);
-               dev_hold_track(ax25_dev->dev, &ax25_dev->dev_tracker, GFP_ATOMIC);
+               netdev_hold(ax25_dev->dev, &ax25_dev->dev_tracker, GFP_ATOMIC);
        }
 
 done:
index 95a76d5..ab88b6a 100644 (file)
@@ -60,7 +60,7 @@ void ax25_dev_device_up(struct net_device *dev)
        refcount_set(&ax25_dev->refcount, 1);
        dev->ax25_ptr     = ax25_dev;
        ax25_dev->dev     = dev;
-       dev_hold_track(dev, &ax25_dev->dev_tracker, GFP_ATOMIC);
+       netdev_hold(dev, &ax25_dev->dev_tracker, GFP_ATOMIC);
        ax25_dev->forward = NULL;
        ax25_dev->device_up = true;
 
@@ -136,7 +136,7 @@ unlock_put:
        spin_unlock_bh(&ax25_dev_lock);
        ax25_dev_put(ax25_dev);
        dev->ax25_ptr = NULL;
-       dev_put_track(dev, &ax25_dev->dev_tracker);
+       netdev_put(dev, &ax25_dev->dev_tracker);
        ax25_dev_put(ax25_dev);
 }
 
@@ -205,7 +205,7 @@ void __exit ax25_dev_free(void)
        ax25_dev = ax25_dev_list;
        while (ax25_dev != NULL) {
                s        = ax25_dev;
-               dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker);
+               netdev_put(ax25_dev->dev, &ax25_dev->dev_tracker);
                ax25_dev = ax25_dev->next;
                kfree(s);
        }
index 47fcbad..a84a7cf 100644 (file)
@@ -274,7 +274,7 @@ static void destroy_nbp(struct net_bridge_port *p)
 
        p->br = NULL;
        p->dev = NULL;
-       dev_put_track(dev, &p->dev_tracker);
+       netdev_put(dev, &p->dev_tracker);
 
        kobject_put(&p->kobj);
 }
@@ -423,7 +423,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
                return ERR_PTR(-ENOMEM);
 
        p->br = br;
-       dev_hold_track(dev, &p->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &p->dev_tracker, GFP_KERNEL);
        p->dev = dev;
        p->path_cost = port_cost(dev);
        p->priority = 0x8000 >> BR_PORT_BITS;
@@ -434,7 +434,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
        br_stp_port_timer_init(p);
        err = br_multicast_add_port(p);
        if (err) {
-               dev_put_track(dev, &p->dev_tracker);
+               netdev_put(dev, &p->dev_tracker);
                kfree(p);
                p = ERR_PTR(err);
        }
@@ -615,7 +615,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
        err = dev_set_allmulti(dev, 1);
        if (err) {
                br_multicast_del_port(p);
-               dev_put_track(dev, &p->dev_tracker);
+               netdev_put(dev, &p->dev_tracker);
                kfree(p);       /* kobject not yet init'd, manually free */
                goto err1;
        }
@@ -725,7 +725,7 @@ err3:
        sysfs_remove_link(br->ifobj, p->dev->name);
 err2:
        br_multicast_del_port(p);
-       dev_put_track(dev, &p->dev_tracker);
+       netdev_put(dev, &p->dev_tracker);
        kobject_put(&p->kobj);
        dev_set_allmulti(dev, -1);
 err1:
index bb01776..1ef14a0 100644 (file)
@@ -1770,10 +1770,10 @@ static int br_fill_linkxstats(struct sk_buff *skb,
                        if (v->vid == pvid)
                                vxi.flags |= BRIDGE_VLAN_INFO_PVID;
                        br_vlan_get_stats(v, &stats);
-                       vxi.rx_bytes = stats.rx_bytes;
-                       vxi.rx_packets = stats.rx_packets;
-                       vxi.tx_bytes = stats.tx_bytes;
-                       vxi.tx_packets = stats.tx_packets;
+                       vxi.rx_bytes = u64_stats_read(&stats.rx_bytes);
+                       vxi.rx_packets = u64_stats_read(&stats.rx_packets);
+                       vxi.tx_bytes = u64_stats_read(&stats.tx_bytes);
+                       vxi.tx_packets = u64_stats_read(&stats.tx_packets);
 
                        if (nla_put(skb, BRIDGE_XSTATS_VLAN, sizeof(vxi), &vxi))
                                goto nla_put_failure;
index 0f5e75c..6e53dc9 100644 (file)
@@ -505,8 +505,8 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
        if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) {
                stats = this_cpu_ptr(v->stats);
                u64_stats_update_begin(&stats->syncp);
-               stats->tx_bytes += skb->len;
-               stats->tx_packets++;
+               u64_stats_add(&stats->tx_bytes, skb->len);
+               u64_stats_inc(&stats->tx_packets);
                u64_stats_update_end(&stats->syncp);
        }
 
@@ -624,8 +624,8 @@ static bool __allowed_ingress(const struct net_bridge *br,
        if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) {
                stats = this_cpu_ptr(v->stats);
                u64_stats_update_begin(&stats->syncp);
-               stats->rx_bytes += skb->len;
-               stats->rx_packets++;
+               u64_stats_add(&stats->rx_bytes, skb->len);
+               u64_stats_inc(&stats->rx_packets);
                u64_stats_update_end(&stats->syncp);
        }
 
@@ -1379,16 +1379,16 @@ void br_vlan_get_stats(const struct net_bridge_vlan *v,
                cpu_stats = per_cpu_ptr(v->stats, i);
                do {
                        start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
-                       rxpackets = cpu_stats->rx_packets;
-                       rxbytes = cpu_stats->rx_bytes;
-                       txbytes = cpu_stats->tx_bytes;
-                       txpackets = cpu_stats->tx_packets;
+                       rxpackets = u64_stats_read(&cpu_stats->rx_packets);
+                       rxbytes = u64_stats_read(&cpu_stats->rx_bytes);
+                       txbytes = u64_stats_read(&cpu_stats->tx_bytes);
+                       txpackets = u64_stats_read(&cpu_stats->tx_packets);
                } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
 
-               stats->rx_packets += rxpackets;
-               stats->rx_bytes += rxbytes;
-               stats->tx_bytes += txbytes;
-               stats->tx_packets += txpackets;
+               u64_stats_add(&stats->rx_packets, rxpackets);
+               u64_stats_add(&stats->rx_bytes, rxbytes);
+               u64_stats_add(&stats->tx_bytes, txbytes);
+               u64_stats_add(&stats->tx_packets, txpackets);
        }
 }
 
@@ -1779,14 +1779,18 @@ static bool br_vlan_stats_fill(struct sk_buff *skb,
                return false;
 
        br_vlan_get_stats(v, &stats);
-       if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_RX_BYTES, stats.rx_bytes,
+       if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_RX_BYTES,
+                             u64_stats_read(&stats.rx_bytes),
                              BRIDGE_VLANDB_STATS_PAD) ||
            nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_RX_PACKETS,
-                             stats.rx_packets, BRIDGE_VLANDB_STATS_PAD) ||
-           nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_TX_BYTES, stats.tx_bytes,
+                             u64_stats_read(&stats.rx_packets),
+                             BRIDGE_VLANDB_STATS_PAD) ||
+           nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_TX_BYTES,
+                             u64_stats_read(&stats.tx_bytes),
                              BRIDGE_VLANDB_STATS_PAD) ||
            nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_TX_PACKETS,
-                             stats.tx_packets, BRIDGE_VLANDB_STATS_PAD))
+                             u64_stats_read(&stats.tx_packets),
+                             BRIDGE_VLANDB_STATS_PAD))
                goto out_err;
 
        nla_nest_end(skb, nest);
diff --git a/net/core/.gitignore b/net/core/.gitignore
new file mode 100644 (file)
index 0000000..df1e743
--- /dev/null
@@ -0,0 +1 @@
+dropreason_str.c
index a8e4f73..e8ce3bd 100644 (file)
@@ -4,7 +4,8 @@
 #
 
 obj-y := sock.o request_sock.o skbuff.o datagram.o stream.o scm.o \
-        gen_stats.o gen_estimator.o net_namespace.o secure_seq.o flow_dissector.o
+        gen_stats.o gen_estimator.o net_namespace.o secure_seq.o \
+        flow_dissector.o dropreason_str.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
@@ -39,3 +40,23 @@ obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o
 obj-$(CONFIG_BPF_SYSCALL) += sock_map.o
 obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o
 obj-$(CONFIG_OF)       += of_net.o
+
+clean-files := dropreason_str.c
+
+quiet_cmd_dropreason_str = GEN     $@
+cmd_dropreason_str = awk -F ',' 'BEGIN{ print "\#include <net/dropreason.h>\n"; \
+       print "const char * const drop_reasons[] = {" }\
+       /^enum skb_drop/ { dr=1; }\
+       /^\};/ { dr=0; }\
+       /^\tSKB_DROP_REASON_/ {\
+               if (dr) {\
+                       sub(/\tSKB_DROP_REASON_/, "", $$1);\
+                       printf "\t[SKB_DROP_REASON_%s] = \"%s\",\n", $$1, $$1;\
+               }\
+       }\
+       END{ print "};" }' $< > $@
+
+$(obj)/dropreason_str.c: $(srctree)/include/net/dropreason.h
+       $(call cmd,dropreason_str)
+
+$(obj)/dropreason_str.o: $(obj)/dropreason_str.c
index 08ce317..8958c42 100644 (file)
@@ -3925,7 +3925,7 @@ int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
        skb->pkt_type = PACKET_LOOPBACK;
        if (skb->ip_summed == CHECKSUM_NONE)
                skb->ip_summed = CHECKSUM_UNNECESSARY;
-       WARN_ON(!skb_dst(skb));
+       DEBUG_NET_WARN_ON_ONCE(!skb_dst(skb));
        skb_dst_force(skb);
        netif_rx(skb);
        return 0;
@@ -6351,6 +6351,23 @@ int dev_set_threaded(struct net_device *dev, bool threaded)
 }
 EXPORT_SYMBOL(dev_set_threaded);
 
+/* Double check that napi_get_frags() allocates skbs with
+ * skb->head being backed by slab, not a page fragment.
+ * This is to make sure bug fixed in 3226b158e67c
+ * ("net: avoid 32 x truesize under-estimation for tiny skbs")
+ * does not accidentally come back.
+ */
+static void napi_get_frags_check(struct napi_struct *napi)
+{
+       struct sk_buff *skb;
+
+       local_bh_disable();
+       skb = napi_get_frags(napi);
+       WARN_ON_ONCE(skb && skb->head_frag);
+       napi_free_frags(napi);
+       local_bh_enable();
+}
+
 void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
                           int (*poll)(struct napi_struct *, int), int weight)
 {
@@ -6378,6 +6395,7 @@ void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
        set_bit(NAPI_STATE_NPSVC, &napi->state);
        list_add_rcu(&napi->dev_list, &dev->napi_list);
        napi_hash_add(napi);
+       napi_get_frags_check(napi);
        /* Create kthread for this napi if dev->threaded is set.
         * Clear dev->threaded if kthread creation failed so that
         * threaded mode will not be enabled in napi_enable().
@@ -7463,7 +7481,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
        adj->ref_nr = 1;
        adj->private = private;
        adj->ignore = false;
-       dev_hold_track(adj_dev, &adj->dev_tracker, GFP_KERNEL);
+       netdev_hold(adj_dev, &adj->dev_tracker, GFP_KERNEL);
 
        pr_debug("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d; dev_hold on %s\n",
                 dev->name, adj_dev->name, adj->ref_nr, adj_dev->name);
@@ -7492,7 +7510,7 @@ remove_symlinks:
        if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list))
                netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);
 free_adj:
-       dev_put_track(adj_dev, &adj->dev_tracker);
+       netdev_put(adj_dev, &adj->dev_tracker);
        kfree(adj);
 
        return ret;
@@ -7534,7 +7552,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
        list_del_rcu(&adj->list);
        pr_debug("adjacency: dev_put for %s, because link removed from %s to %s\n",
                 adj_dev->name, dev->name, adj_dev->name);
-       dev_put_track(adj_dev, &adj->dev_tracker);
+       netdev_put(adj_dev, &adj->dev_tracker);
        kfree_rcu(adj, rcu);
 }
 
@@ -10062,7 +10080,7 @@ int register_netdevice(struct net_device *dev)
 
        dev_init_scheduler(dev);
 
-       dev_hold_track(dev, &dev->dev_registered_tracker, GFP_KERNEL);
+       netdev_hold(dev, &dev->dev_registered_tracker, GFP_KERNEL);
        list_netdevice(dev);
 
        add_device_randomness(dev->dev_addr, dev->addr_len);
@@ -10459,23 +10477,23 @@ void dev_fetch_sw_netstats(struct rtnl_link_stats64 *s,
        int cpu;
 
        for_each_possible_cpu(cpu) {
+               u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
                const struct pcpu_sw_netstats *stats;
-               struct pcpu_sw_netstats tmp;
                unsigned int start;
 
                stats = per_cpu_ptr(netstats, cpu);
                do {
                        start = u64_stats_fetch_begin_irq(&stats->syncp);
-                       tmp.rx_packets = stats->rx_packets;
-                       tmp.rx_bytes   = stats->rx_bytes;
-                       tmp.tx_packets = stats->tx_packets;
-                       tmp.tx_bytes   = stats->tx_bytes;
+                       rx_packets = u64_stats_read(&stats->rx_packets);
+                       rx_bytes   = u64_stats_read(&stats->rx_bytes);
+                       tx_packets = u64_stats_read(&stats->tx_packets);
+                       tx_bytes   = u64_stats_read(&stats->tx_bytes);
                } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
 
-               s->rx_packets += tmp.rx_packets;
-               s->rx_bytes   += tmp.rx_bytes;
-               s->tx_packets += tmp.tx_packets;
-               s->tx_bytes   += tmp.tx_bytes;
+               s->rx_packets += rx_packets;
+               s->rx_bytes   += rx_bytes;
+               s->tx_packets += tx_packets;
+               s->tx_bytes   += tx_bytes;
        }
 }
 EXPORT_SYMBOL_GPL(dev_fetch_sw_netstats);
@@ -10868,7 +10886,7 @@ void unregister_netdevice_many(struct list_head *head)
        synchronize_net();
 
        list_for_each_entry(dev, head, unreg_list) {
-               dev_put_track(dev, &dev->dev_registered_tracker);
+               netdev_put(dev, &dev->dev_registered_tracker);
                net_set_todo(dev);
        }
 
index 4f6be44..7674bb9 100644 (file)
@@ -384,10 +384,10 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,
                        return -ENODEV;
                if (!netif_is_bridge_master(dev))
                        return -EOPNOTSUPP;
-               dev_hold_track(dev, &dev_tracker, GFP_KERNEL);
+               netdev_hold(dev, &dev_tracker, GFP_KERNEL);
                rtnl_unlock();
                err = br_ioctl_call(net, netdev_priv(dev), cmd, ifr, NULL);
-               dev_put_track(dev, &dev_tracker);
+               netdev_put(dev, &dev_tracker);
                rtnl_lock();
                return err;
 
index 5cc8849..db61f3a 100644 (file)
@@ -7946,8 +7946,8 @@ static int devlink_nl_cmd_health_reporter_test_doit(struct sk_buff *skb,
 }
 
 struct devlink_stats {
-       u64 rx_bytes;
-       u64 rx_packets;
+       u64_stats_t rx_bytes;
+       u64_stats_t rx_packets;
        struct u64_stats_sync syncp;
 };
 
@@ -8104,12 +8104,12 @@ static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
                cpu_stats = per_cpu_ptr(trap_stats, i);
                do {
                        start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
-                       rx_packets = cpu_stats->rx_packets;
-                       rx_bytes = cpu_stats->rx_bytes;
+                       rx_packets = u64_stats_read(&cpu_stats->rx_packets);
+                       rx_bytes = u64_stats_read(&cpu_stats->rx_bytes);
                } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
 
-               stats->rx_packets += rx_packets;
-               stats->rx_bytes += rx_bytes;
+               u64_stats_add(&stats->rx_packets, rx_packets);
+               u64_stats_add(&stats->rx_bytes, rx_bytes);
        }
 }
 
@@ -8127,11 +8127,13 @@ devlink_trap_group_stats_put(struct sk_buff *msg,
                return -EMSGSIZE;
 
        if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
-                             stats.rx_packets, DEVLINK_ATTR_PAD))
+                             u64_stats_read(&stats.rx_packets),
+                             DEVLINK_ATTR_PAD))
                goto nla_put_failure;
 
        if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
-                             stats.rx_bytes, DEVLINK_ATTR_PAD))
+                             u64_stats_read(&stats.rx_bytes),
+                             DEVLINK_ATTR_PAD))
                goto nla_put_failure;
 
        nla_nest_end(msg, attr);
@@ -8171,11 +8173,13 @@ static int devlink_trap_stats_put(struct sk_buff *msg, struct devlink *devlink,
                goto nla_put_failure;
 
        if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
-                             stats.rx_packets, DEVLINK_ATTR_PAD))
+                             u64_stats_read(&stats.rx_packets),
+                             DEVLINK_ATTR_PAD))
                goto nla_put_failure;
 
        if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
-                             stats.rx_bytes, DEVLINK_ATTR_PAD))
+                             u64_stats_read(&stats.rx_bytes),
+                             DEVLINK_ATTR_PAD))
                goto nla_put_failure;
 
        nla_nest_end(msg, attr);
@@ -11641,8 +11645,8 @@ devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
 
        stats = this_cpu_ptr(trap_stats);
        u64_stats_update_begin(&stats->syncp);
-       stats->rx_bytes += skb_len;
-       stats->rx_packets++;
+       u64_stats_add(&stats->rx_bytes, skb_len);
+       u64_stats_inc(&stats->rx_packets);
        u64_stats_update_end(&stats->syncp);
 }
 
index 41cac0e..75501e1 100644 (file)
 static int trace_state = TRACE_OFF;
 static bool monitor_hw;
 
-#undef EM
-#undef EMe
-
-#define EM(a, b)       [a] = #b,
-#define EMe(a, b)      [a] = #b
-
-/* drop_reasons is used to translate 'enum skb_drop_reason' to string,
- * which is reported to user space.
- */
-static const char * const drop_reasons[] = {
-       TRACE_SKB_DROP_REASON
-};
-
 /* net_dm_mutex
  *
  * An overall lock guarding every operation coming from userspace.
@@ -68,7 +55,7 @@ static const char * const drop_reasons[] = {
 static DEFINE_MUTEX(net_dm_mutex);
 
 struct net_dm_stats {
-       u64 dropped;
+       u64_stats_t dropped;
        struct u64_stats_sync syncp;
 };
 
@@ -543,7 +530,7 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore,
 unlock_free:
        spin_unlock_irqrestore(&data->drop_queue.lock, flags);
        u64_stats_update_begin(&data->stats.syncp);
-       data->stats.dropped++;
+       u64_stats_inc(&data->stats.dropped);
        u64_stats_update_end(&data->stats.syncp);
        consume_skb(nskb);
 }
@@ -877,7 +864,8 @@ net_dm_hw_metadata_copy(const struct devlink_trap_metadata *metadata)
        }
 
        hw_metadata->input_dev = metadata->input_dev;
-       dev_hold_track(hw_metadata->input_dev, &hw_metadata->dev_tracker, GFP_ATOMIC);
+       netdev_hold(hw_metadata->input_dev, &hw_metadata->dev_tracker,
+                   GFP_ATOMIC);
 
        return hw_metadata;
 
@@ -893,7 +881,7 @@ free_hw_metadata:
 static void
 net_dm_hw_metadata_free(struct devlink_trap_metadata *hw_metadata)
 {
-       dev_put_track(hw_metadata->input_dev, &hw_metadata->dev_tracker);
+       netdev_put(hw_metadata->input_dev, &hw_metadata->dev_tracker);
        kfree(hw_metadata->fa_cookie);
        kfree(hw_metadata->trap_name);
        kfree(hw_metadata->trap_group_name);
@@ -998,7 +986,7 @@ net_dm_hw_trap_packet_probe(void *ignore, const struct devlink *devlink,
 unlock_free:
        spin_unlock_irqrestore(&hw_data->drop_queue.lock, flags);
        u64_stats_update_begin(&hw_data->stats.syncp);
-       hw_data->stats.dropped++;
+       u64_stats_inc(&hw_data->stats.dropped);
        u64_stats_update_end(&hw_data->stats.syncp);
        net_dm_hw_metadata_free(n_hw_metadata);
 free:
@@ -1445,10 +1433,10 @@ static void net_dm_stats_read(struct net_dm_stats *stats)
 
                do {
                        start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
-                       dropped = cpu_stats->dropped;
+                       dropped = u64_stats_read(&cpu_stats->dropped);
                } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
 
-               stats->dropped += dropped;
+               u64_stats_add(&stats->dropped, dropped);
        }
 }
 
@@ -1464,7 +1452,7 @@ static int net_dm_stats_put(struct sk_buff *msg)
                return -EMSGSIZE;
 
        if (nla_put_u64_64bit(msg, NET_DM_ATTR_STATS_DROPPED,
-                             stats.dropped, NET_DM_ATTR_PAD))
+                             u64_stats_read(&stats.dropped), NET_DM_ATTR_PAD))
                goto nla_put_failure;
 
        nla_nest_end(msg, attr);
@@ -1489,10 +1477,10 @@ static void net_dm_hw_stats_read(struct net_dm_stats *stats)
 
                do {
                        start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
-                       dropped = cpu_stats->dropped;
+                       dropped = u64_stats_read(&cpu_stats->dropped);
                } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
 
-               stats->dropped += dropped;
+               u64_stats_add(&stats->dropped, dropped);
        }
 }
 
@@ -1508,7 +1496,7 @@ static int net_dm_hw_stats_put(struct sk_buff *msg)
                return -EMSGSIZE;
 
        if (nla_put_u64_64bit(msg, NET_DM_ATTR_STATS_DROPPED,
-                             stats.dropped, NET_DM_ATTR_PAD))
+                             u64_stats_read(&stats.dropped), NET_DM_ATTR_PAD))
                goto nla_put_failure;
 
        nla_nest_end(msg, attr);
index d16c2c9..bc9c9be 100644 (file)
@@ -49,7 +49,7 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
              unsigned short flags)
 {
        dst->dev = dev;
-       dev_hold_track(dev, &dst->dev_tracker, GFP_ATOMIC);
+       netdev_hold(dev, &dst->dev_tracker, GFP_ATOMIC);
        dst->ops = ops;
        dst_init_metrics(dst, dst_default_metrics.metrics, true);
        dst->expires = 0UL;
@@ -117,7 +117,7 @@ struct dst_entry *dst_destroy(struct dst_entry * dst)
 
        if (dst->ops->destroy)
                dst->ops->destroy(dst);
-       dev_put_track(dst->dev, &dst->dev_tracker);
+       netdev_put(dst->dev, &dst->dev_tracker);
 
        lwtstate_put(dst->lwtstate);
 
@@ -159,8 +159,8 @@ void dst_dev_put(struct dst_entry *dst)
        dst->input = dst_discard;
        dst->output = dst_discard_out;
        dst->dev = blackhole_netdev;
-       dev_replace_track(dev, blackhole_netdev, &dst->dev_tracker,
-                         GFP_ATOMIC);
+       netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker,
+                          GFP_ATOMIC);
 }
 EXPORT_SYMBOL(dst_dev_put);
 
index dcaa92a..864d2d8 100644 (file)
@@ -252,7 +252,7 @@ struct failover *failover_register(struct net_device *dev,
                return ERR_PTR(-ENOMEM);
 
        rcu_assign_pointer(failover->ops, ops);
-       dev_hold_track(dev, &failover->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &failover->dev_tracker, GFP_KERNEL);
        dev->priv_flags |= IFF_FAILOVER;
        rcu_assign_pointer(failover->failover_dev, dev);
 
@@ -285,7 +285,7 @@ void failover_unregister(struct failover *failover)
                    failover_dev->name);
 
        failover_dev->priv_flags &= ~IFF_FAILOVER;
-       dev_put_track(failover_dev, &failover->dev_tracker);
+       netdev_put(failover_dev, &failover->dev_tracker);
 
        spin_lock(&failover_lock);
        list_del(&failover->list);
index a244d3b..aa6cb1f 100644 (file)
@@ -110,7 +110,7 @@ static void linkwatch_add_event(struct net_device *dev)
        spin_lock_irqsave(&lweventlist_lock, flags);
        if (list_empty(&dev->link_watch_list)) {
                list_add_tail(&dev->link_watch_list, &lweventlist);
-               dev_hold_track(dev, &dev->linkwatch_dev_tracker, GFP_ATOMIC);
+               netdev_hold(dev, &dev->linkwatch_dev_tracker, GFP_ATOMIC);
        }
        spin_unlock_irqrestore(&lweventlist_lock, flags);
 }
index 5462528..d8ec706 100644 (file)
@@ -624,7 +624,7 @@ ___neigh_create(struct neigh_table *tbl, const void *pkey,
 
        memcpy(n->primary_key, pkey, key_len);
        n->dev = dev;
-       dev_hold_track(dev, &n->dev_tracker, GFP_ATOMIC);
+       netdev_hold(dev, &n->dev_tracker, GFP_ATOMIC);
 
        /* Protocol specific setup. */
        if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
@@ -770,10 +770,10 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
        write_pnet(&n->net, net);
        memcpy(n->key, pkey, key_len);
        n->dev = dev;
-       dev_hold_track(dev, &n->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &n->dev_tracker, GFP_KERNEL);
 
        if (tbl->pconstructor && tbl->pconstructor(n)) {
-               dev_put_track(dev, &n->dev_tracker);
+               netdev_put(dev, &n->dev_tracker);
                kfree(n);
                n = NULL;
                goto out;
@@ -805,7 +805,7 @@ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
                        write_unlock_bh(&tbl->lock);
                        if (tbl->pdestructor)
                                tbl->pdestructor(n);
-                       dev_put_track(n->dev, &n->dev_tracker);
+                       netdev_put(n->dev, &n->dev_tracker);
                        kfree(n);
                        return 0;
                }
@@ -838,7 +838,7 @@ static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
                n->next = NULL;
                if (tbl->pdestructor)
                        tbl->pdestructor(n);
-               dev_put_track(n->dev, &n->dev_tracker);
+               netdev_put(n->dev, &n->dev_tracker);
                kfree(n);
        }
        return -ENOENT;
@@ -879,7 +879,7 @@ void neigh_destroy(struct neighbour *neigh)
        if (dev->netdev_ops->ndo_neigh_destroy)
                dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
 
-       dev_put_track(dev, &neigh->dev_tracker);
+       netdev_put(dev, &neigh->dev_tracker);
        neigh_parms_put(neigh->parms);
 
        neigh_dbg(2, "neigh %p is destroyed\n", neigh);
@@ -1671,13 +1671,13 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
                refcount_set(&p->refcnt, 1);
                p->reachable_time =
                                neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
-               dev_hold_track(dev, &p->dev_tracker, GFP_KERNEL);
+               netdev_hold(dev, &p->dev_tracker, GFP_KERNEL);
                p->dev = dev;
                write_pnet(&p->net, net);
                p->sysctl_table = NULL;
 
                if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
-                       dev_put_track(dev, &p->dev_tracker);
+                       netdev_put(dev, &p->dev_tracker);
                        kfree(p);
                        return NULL;
                }
@@ -1708,7 +1708,7 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
        list_del(&parms->list);
        parms->dead = 1;
        write_unlock_bh(&tbl->lock);
-       dev_put_track(parms->dev, &parms->dev_tracker);
+       netdev_put(parms->dev, &parms->dev_tracker);
        call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
 }
 EXPORT_SYMBOL(neigh_parms_release);
index e319e24..d49fc97 100644 (file)
@@ -1016,7 +1016,7 @@ static void rx_queue_release(struct kobject *kobj)
 #endif
 
        memset(kobj, 0, sizeof(*kobj));
-       dev_put_track(queue->dev, &queue->dev_tracker);
+       netdev_put(queue->dev, &queue->dev_tracker);
 }
 
 static const void *rx_queue_namespace(struct kobject *kobj)
@@ -1056,7 +1056,7 @@ static int rx_queue_add_kobject(struct net_device *dev, int index)
        /* Kobject_put later will trigger rx_queue_release call which
         * decreases dev refcount: Take that reference here
         */
-       dev_hold_track(queue->dev, &queue->dev_tracker, GFP_KERNEL);
+       netdev_hold(queue->dev, &queue->dev_tracker, GFP_KERNEL);
 
        kobj->kset = dev->queues_kset;
        error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
@@ -1619,7 +1619,7 @@ static void netdev_queue_release(struct kobject *kobj)
        struct netdev_queue *queue = to_netdev_queue(kobj);
 
        memset(kobj, 0, sizeof(*kobj));
-       dev_put_track(queue->dev, &queue->dev_tracker);
+       netdev_put(queue->dev, &queue->dev_tracker);
 }
 
 static const void *netdev_queue_namespace(struct kobject *kobj)
@@ -1659,7 +1659,7 @@ static int netdev_queue_add_kobject(struct net_device *dev, int index)
        /* Kobject_put later will trigger netdev_queue_release call
         * which decreases dev refcount: Take that reference here
         */
-       dev_hold_track(queue->dev, &queue->dev_tracker, GFP_KERNEL);
+       netdev_hold(queue->dev, &queue->dev_tracker, GFP_KERNEL);
 
        kobj->kset = dev->queues_kset;
        error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL,
index db72446..5d27067 100644 (file)
@@ -853,7 +853,7 @@ void netpoll_cleanup(struct netpoll *np)
        if (!np->dev)
                goto out;
        __netpoll_cleanup(np);
-       dev_put_track(np->dev, &np->dev_tracker);
+       netdev_put(np->dev, &np->dev_tracker);
        np->dev = NULL;
 out:
        rtnl_unlock();
index 84b62cd..88906ba 100644 (file)
@@ -2100,7 +2100,7 @@ static int pktgen_setup_dev(const struct pktgen_net *pn,
 
        /* Clean old setups */
        if (pkt_dev->odev) {
-               dev_put_track(pkt_dev->odev, &pkt_dev->dev_tracker);
+               netdev_put(pkt_dev->odev, &pkt_dev->dev_tracker);
                pkt_dev->odev = NULL;
        }
 
@@ -3807,7 +3807,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
 
        return add_dev_to_thread(t, pkt_dev);
 out2:
-       dev_put_track(pkt_dev->odev, &pkt_dev->dev_tracker);
+       netdev_put(pkt_dev->odev, &pkt_dev->dev_tracker);
 out1:
 #ifdef CONFIG_XFRM
        free_SAs(pkt_dev);
@@ -3901,7 +3901,7 @@ static int pktgen_remove_device(struct pktgen_thread *t,
        /* Dis-associate from the interface */
 
        if (pkt_dev->odev) {
-               dev_put_track(pkt_dev->odev, &pkt_dev->dev_tracker);
+               netdev_put(pkt_dev->odev, &pkt_dev->dev_tracker);
                pkt_dev->odev = NULL;
        }
 
index 5b3559c..fec75f8 100644 (file)
@@ -91,6 +91,9 @@ static struct kmem_cache *skbuff_ext_cache __ro_after_init;
 int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
 EXPORT_SYMBOL(sysctl_max_skb_frags);
 
+/* The array 'drop_reasons' is auto-generated in dropreason_str.c */
+EXPORT_SYMBOL(drop_reasons);
+
 /**
  *     skb_panic - private function for out-of-line support
  *     @skb:   buffer
@@ -557,6 +560,7 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len,
        struct sk_buff *skb;
        void *data;
 
+       DEBUG_NET_WARN_ON_ONCE(!in_softirq());
        len += NET_SKB_PAD + NET_IP_ALIGN;
 
        /* If requested length is either too small or too big,
@@ -725,7 +729,7 @@ void skb_release_head_state(struct sk_buff *skb)
 {
        skb_dst_drop(skb);
        if (skb->destructor) {
-               WARN_ON(in_hardirq());
+               DEBUG_NET_WARN_ON_ONCE(in_hardirq());
                skb->destructor(skb);
        }
 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
@@ -978,7 +982,7 @@ void napi_consume_skb(struct sk_buff *skb, int budget)
                return;
        }
 
-       lockdep_assert_in_softirq();
+       DEBUG_NET_WARN_ON_ONCE(!in_softirq());
 
        if (!skb_unref(skb))
                return;
index 2ff40dd..f5062d9 100644 (file)
@@ -2844,7 +2844,7 @@ void __release_sock(struct sock *sk)
                do {
                        next = skb->next;
                        prefetch(next);
-                       WARN_ON_ONCE(skb_dst_is_noref(skb));
+                       DEBUG_NET_WARN_ON_ONCE(skb_dst_is_noref(skb));
                        skb_mark_not_on_list(skb);
                        sk_backlog_rcv(sk, skb);
 
index 06b36c7..ccc083c 100644 (file)
@@ -196,13 +196,13 @@ void sk_stream_kill_queues(struct sock *sk)
        __skb_queue_purge(&sk->sk_receive_queue);
 
        /* Next, the write queue. */
-       WARN_ON(!skb_queue_empty(&sk->sk_write_queue));
+       WARN_ON_ONCE(!skb_queue_empty(&sk->sk_write_queue));
 
        /* Account for returned memory. */
        sk_mem_reclaim_final(sk);
 
-       WARN_ON(sk->sk_wmem_queued);
-       WARN_ON(sk->sk_forward_alloc);
+       WARN_ON_ONCE(sk->sk_wmem_queued);
+       WARN_ON_ONCE(sk->sk_forward_alloc);
 
        /* It is _impossible_ for the backlog to contain anything
         * when we get here.  All user references to this socket
index 801a5d4..2e1ac63 100644 (file)
@@ -935,10 +935,10 @@ static void dsa_slave_get_ethtool_stats(struct net_device *dev,
                s = per_cpu_ptr(dev->tstats, i);
                do {
                        start = u64_stats_fetch_begin_irq(&s->syncp);
-                       tx_packets = s->tx_packets;
-                       tx_bytes = s->tx_bytes;
-                       rx_packets = s->rx_packets;
-                       rx_bytes = s->rx_bytes;
+                       tx_packets = u64_stats_read(&s->tx_packets);
+                       tx_bytes = u64_stats_read(&s->tx_bytes);
+                       rx_packets = u64_stats_read(&s->rx_packets);
+                       rx_bytes = u64_stats_read(&s->rx_bytes);
                } while (u64_stats_fetch_retry_irq(&s->syncp, start));
                data[0] += tx_packets;
                data[1] += tx_bytes;
index 326e14e..d05ff6a 100644 (file)
@@ -2010,7 +2010,7 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
         * removal of the device.
         */
        busy = true;
-       dev_hold_track(dev, &dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &dev_tracker, GFP_KERNEL);
        rtnl_unlock();
 
        if (rc == 0) {
@@ -2034,7 +2034,7 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
        }
 
        rtnl_lock();
-       dev_put_track(dev, &dev_tracker);
+       netdev_put(dev, &dev_tracker);
        busy = false;
 
        (void) ops->set_phys_id(dev, ETHTOOL_ID_INACTIVE);
index 5fe8f4a..e26079e 100644 (file)
@@ -402,7 +402,7 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
                ops->cleanup_data(reply_data);
 
        genlmsg_end(rskb, reply_payload);
-       dev_put_track(req_info->dev, &req_info->dev_tracker);
+       netdev_put(req_info->dev, &req_info->dev_tracker);
        kfree(reply_data);
        kfree(req_info);
        return genlmsg_reply(rskb, info);
@@ -414,7 +414,7 @@ err_cleanup:
        if (ops->cleanup_data)
                ops->cleanup_data(reply_data);
 err_dev:
-       dev_put_track(req_info->dev, &req_info->dev_tracker);
+       netdev_put(req_info->dev, &req_info->dev_tracker);
        kfree(reply_data);
        kfree(req_info);
        return ret;
@@ -550,7 +550,7 @@ static int ethnl_default_start(struct netlink_callback *cb)
                 * same parser as for non-dump (doit) requests is used, it
                 * would take reference to the device if it finds one
                 */
-               dev_put_track(req_info->dev, &req_info->dev_tracker);
+               netdev_put(req_info->dev, &req_info->dev_tracker);
                req_info->dev = NULL;
        }
        if (ret < 0)
index 7919ddb..c0d5876 100644 (file)
@@ -237,7 +237,7 @@ struct ethnl_req_info {
 
 static inline void ethnl_parse_header_dev_put(struct ethnl_req_info *req_info)
 {
-       dev_put_track(req_info->dev, &req_info->dev_tracker);
+       netdev_put(req_info->dev, &req_info->dev_tracker);
 }
 
 /**
index 93da9f7..30e0e89 100644 (file)
@@ -148,10 +148,10 @@ void inet_sock_destruct(struct sock *sk)
                return;
        }
 
-       WARN_ON(atomic_read(&sk->sk_rmem_alloc));
-       WARN_ON(refcount_read(&sk->sk_wmem_alloc));
-       WARN_ON(sk->sk_wmem_queued);
-       WARN_ON(sk_forward_alloc_get(sk));
+       WARN_ON_ONCE(atomic_read(&sk->sk_rmem_alloc));
+       WARN_ON_ONCE(refcount_read(&sk->sk_wmem_alloc));
+       WARN_ON_ONCE(sk->sk_wmem_queued);
+       WARN_ON_ONCE(sk_forward_alloc_get(sk));
 
        kfree(rcu_dereference_protected(inet->inet_opt, 1));
        dst_release(rcu_dereference_protected(sk->sk_dst_cache, 1));
index b2366ad..92b778e 100644 (file)
@@ -244,7 +244,7 @@ void in_dev_finish_destroy(struct in_device *idev)
 #ifdef NET_REFCNT_DEBUG
        pr_debug("%s: %p=%s\n", __func__, idev, dev ? dev->name : "NIL");
 #endif
-       dev_put_track(dev, &idev->dev_tracker);
+       netdev_put(dev, &idev->dev_tracker);
        if (!idev->dead)
                pr_err("Freeing alive in_device %p\n", idev);
        else
@@ -272,7 +272,7 @@ static struct in_device *inetdev_init(struct net_device *dev)
        if (IPV4_DEVCONF(in_dev->cnf, FORWARDING))
                dev_disable_lro(dev);
        /* Reference in_dev->dev */
-       dev_hold_track(dev, &in_dev->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &in_dev->dev_tracker, GFP_KERNEL);
        /* Account for reference dev->ip_ptr (below) */
        refcount_set(&in_dev->refcnt, 1);
 
index a57ba23..a5439a8 100644 (file)
@@ -211,7 +211,7 @@ static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp)
 
 void fib_nh_common_release(struct fib_nh_common *nhc)
 {
-       dev_put_track(nhc->nhc_dev, &nhc->nhc_dev_tracker);
+       netdev_put(nhc->nhc_dev, &nhc->nhc_dev_tracker);
        lwtstate_put(nhc->nhc_lwtstate);
        rt_fibinfo_free_cpus(nhc->nhc_pcpu_rth_output);
        rt_fibinfo_free(&nhc->nhc_rth_input);
@@ -1057,7 +1057,8 @@ static int fib_check_nh_v6_gw(struct net *net, struct fib_nh *nh,
        err = ipv6_stub->fib6_nh_init(net, &fib6_nh, &cfg, GFP_KERNEL, extack);
        if (!err) {
                nh->fib_nh_dev = fib6_nh.fib_nh_dev;
-               dev_hold_track(nh->fib_nh_dev, &nh->fib_nh_dev_tracker, GFP_KERNEL);
+               netdev_hold(nh->fib_nh_dev, &nh->fib_nh_dev_tracker,
+                           GFP_KERNEL);
                nh->fib_nh_oif = nh->fib_nh_dev->ifindex;
                nh->fib_nh_scope = RT_SCOPE_LINK;
 
@@ -1141,7 +1142,7 @@ static int fib_check_nh_v4_gw(struct net *net, struct fib_nh *nh, u32 table,
                if (!netif_carrier_ok(dev))
                        nh->fib_nh_flags |= RTNH_F_LINKDOWN;
                nh->fib_nh_dev = dev;
-               dev_hold_track(dev, &nh->fib_nh_dev_tracker, GFP_ATOMIC);
+               netdev_hold(dev, &nh->fib_nh_dev_tracker, GFP_ATOMIC);
                nh->fib_nh_scope = RT_SCOPE_LINK;
                return 0;
        }
@@ -1195,7 +1196,7 @@ static int fib_check_nh_v4_gw(struct net *net, struct fib_nh *nh, u32 table,
                               "No egress device for nexthop gateway");
                goto out;
        }
-       dev_hold_track(dev, &nh->fib_nh_dev_tracker, GFP_ATOMIC);
+       netdev_hold(dev, &nh->fib_nh_dev_tracker, GFP_ATOMIC);
        if (!netif_carrier_ok(dev))
                nh->fib_nh_flags |= RTNH_F_LINKDOWN;
        err = (dev->flags & IFF_UP) ? 0 : -ENETDOWN;
@@ -1229,7 +1230,7 @@ static int fib_check_nh_nongw(struct net *net, struct fib_nh *nh,
        }
 
        nh->fib_nh_dev = in_dev->dev;
-       dev_hold_track(nh->fib_nh_dev, &nh->fib_nh_dev_tracker, GFP_ATOMIC);
+       netdev_hold(nh->fib_nh_dev, &nh->fib_nh_dev_tracker, GFP_ATOMIC);
        nh->fib_nh_scope = RT_SCOPE_HOST;
        if (!netif_carrier_ok(nh->fib_nh_dev))
                nh->fib_nh_flags |= RTNH_F_LINKDOWN;
index 13e6329..8324e54 100644 (file)
@@ -691,7 +691,7 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify,
        if (v->flags & (VIFF_TUNNEL | VIFF_REGISTER) && !notify)
                unregister_netdevice_queue(dev, head);
 
-       dev_put_track(dev, &v->dev_tracker);
+       netdev_put(dev, &v->dev_tracker);
        return 0;
 }
 
index 356f535..2d16bcc 100644 (file)
@@ -1550,9 +1550,8 @@ void rt_flush_dev(struct net_device *dev)
                        if (rt->dst.dev != dev)
                                continue;
                        rt->dst.dev = blackhole_netdev;
-                       dev_replace_track(dev, blackhole_netdev,
-                                         &rt->dst.dev_tracker,
-                                         GFP_ATOMIC);
+                       netdev_ref_replace(dev, blackhole_netdev,
+                                          &rt->dst.dev_tracker, GFP_ATOMIC);
                        list_move(&rt->rt_uncached, &ul->quarantine);
                }
                spin_unlock_bh(&ul->lock);
@@ -2851,7 +2850,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
                new->output = dst_discard_out;
 
                new->dev = net->loopback_dev;
-               dev_hold_track(new->dev, &new->dev_tracker, GFP_ATOMIC);
+               netdev_hold(new->dev, &new->dev_tracker, GFP_ATOMIC);
 
                rt->rt_is_input = ort->rt_is_input;
                rt->rt_iif = ort->rt_iif;
index 6fde0b1..3d0dfa6 100644 (file)
@@ -75,7 +75,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        xdst->u.rt.rt_iif = fl4->flowi4_iif;
 
        xdst->u.dst.dev = dev;
-       dev_hold_track(dev, &xdst->u.dst.dev_tracker, GFP_ATOMIC);
+       netdev_hold(dev, &xdst->u.dst.dev_tracker, GFP_ATOMIC);
 
        /* Sheit... I remember I did this right. Apparently,
         * it was magically lost, so this code needs audit */
index 1b19325..3497ad1 100644 (file)
@@ -398,13 +398,13 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
        if (ndev->cnf.forwarding)
                dev_disable_lro(dev);
        /* We refer to the device */
-       dev_hold_track(dev, &ndev->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &ndev->dev_tracker, GFP_KERNEL);
 
        if (snmp6_alloc_dev(ndev) < 0) {
                netdev_dbg(dev, "%s: cannot allocate memory for statistics\n",
                           __func__);
                neigh_parms_release(&nd_tbl, ndev->nd_parms);
-               dev_put_track(dev, &ndev->dev_tracker);
+               netdev_put(dev, &ndev->dev_tracker);
                kfree(ndev);
                return ERR_PTR(err);
        }
index 881d147..507a835 100644 (file)
@@ -263,7 +263,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
 #ifdef NET_REFCNT_DEBUG
        pr_debug("%s: %s\n", __func__, dev ? dev->name : "NIL");
 #endif
-       dev_put_track(dev, &idev->dev_tracker);
+       netdev_put(dev, &idev->dev_tracker);
        if (!idev->dead) {
                pr_warn("Freeing alive inet6 device %p\n", idev);
                return;
index 4e37f7c..3e22cbe 100644 (file)
@@ -398,7 +398,7 @@ static void ip6erspan_tunnel_uninit(struct net_device *dev)
        ip6erspan_tunnel_unlink_md(ign, t);
        ip6gre_tunnel_unlink(ign, t);
        dst_cache_reset(&t->dst_cache);
-       dev_put_track(dev, &t->dev_tracker);
+       netdev_put(dev, &t->dev_tracker);
 }
 
 static void ip6gre_tunnel_uninit(struct net_device *dev)
@@ -411,7 +411,7 @@ static void ip6gre_tunnel_uninit(struct net_device *dev)
        if (ign->fb_tunnel_dev == dev)
                WRITE_ONCE(ign->fb_tunnel_dev, NULL);
        dst_cache_reset(&t->dst_cache);
-       dev_put_track(dev, &t->dev_tracker);
+       netdev_put(dev, &t->dev_tracker);
 }
 
 
@@ -1495,7 +1495,7 @@ static int ip6gre_tunnel_init_common(struct net_device *dev)
        }
        ip6gre_tnl_init_features(dev);
 
-       dev_hold_track(dev, &tunnel->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &tunnel->dev_tracker, GFP_KERNEL);
        return 0;
 
 cleanup_dst_cache_init:
@@ -1887,7 +1887,7 @@ static int ip6erspan_tap_init(struct net_device *dev)
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
        ip6erspan_tnl_link_config(tunnel, 1);
 
-       dev_hold_track(dev, &tunnel->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &tunnel->dev_tracker, GFP_KERNEL);
        return 0;
 
 cleanup_dst_cache_init:
index 19325b7..c7279f2 100644 (file)
@@ -381,7 +381,7 @@ ip6_tnl_dev_uninit(struct net_device *dev)
        else
                ip6_tnl_unlink(ip6n, t);
        dst_cache_reset(&t->dst_cache);
-       dev_put_track(dev, &t->dev_tracker);
+       netdev_put(dev, &t->dev_tracker);
 }
 
 /**
@@ -796,7 +796,6 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
                                                struct sk_buff *skb),
                         bool log_ecn_err)
 {
-       struct pcpu_sw_netstats *tstats;
        const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
        int err;
 
@@ -856,11 +855,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
                }
        }
 
-       tstats = this_cpu_ptr(tunnel->dev->tstats);
-       u64_stats_update_begin(&tstats->syncp);
-       tstats->rx_packets++;
-       tstats->rx_bytes += skb->len;
-       u64_stats_update_end(&tstats->syncp);
+       dev_sw_netstats_rx_add(tunnel->dev, skb->len);
 
        skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev)));
 
@@ -1889,7 +1884,7 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
        dev->min_mtu = ETH_MIN_MTU;
        dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len;
 
-       dev_hold_track(dev, &t->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &t->dev_tracker, GFP_KERNEL);
        return 0;
 
 destroy_dst:
index 3a434d7..8fe59a7 100644 (file)
@@ -293,7 +293,7 @@ static void vti6_dev_uninit(struct net_device *dev)
                RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL);
        else
                vti6_tnl_unlink(ip6n, t);
-       dev_put_track(dev, &t->dev_tracker);
+       netdev_put(dev, &t->dev_tracker);
 }
 
 static int vti6_input_proto(struct sk_buff *skb, int nexthdr, __be32 spi,
@@ -936,7 +936,7 @@ static inline int vti6_dev_init_gen(struct net_device *dev)
        dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
-       dev_hold_track(dev, &t->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &t->dev_tracker, GFP_KERNEL);
        return 0;
 }
 
index 4e74bc6..d4aad41 100644 (file)
@@ -741,7 +741,7 @@ static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
        if ((v->flags & MIFF_REGISTER) && !notify)
                unregister_netdevice_queue(dev, head);
 
-       dev_put_track(dev, &v->dev_tracker);
+       netdev_put(dev, &v->dev_tracker);
        return 0;
 }
 
index d25dc83..0be01a4 100644 (file)
@@ -182,9 +182,9 @@ static void rt6_uncached_list_flush_dev(struct net_device *dev)
 
                        if (rt_dev == dev) {
                                rt->dst.dev = blackhole_netdev;
-                               dev_replace_track(rt_dev, blackhole_netdev,
-                                                 &rt->dst.dev_tracker,
-                                                 GFP_ATOMIC);
+                               netdev_ref_replace(rt_dev, blackhole_netdev,
+                                                  &rt->dst.dev_tracker,
+                                                  GFP_ATOMIC);
                                handled = true;
                        }
                        if (handled)
@@ -607,7 +607,7 @@ static void rt6_probe_deferred(struct work_struct *w)
 
        addrconf_addr_solict_mult(&work->target, &mcaddr);
        ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL, 0);
-       dev_put_track(work->dev, &work->dev_tracker);
+       netdev_put(work->dev, &work->dev_tracker);
        kfree(work);
 }
 
@@ -661,7 +661,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh)
        } else {
                INIT_WORK(&work->work, rt6_probe_deferred);
                work->target = *nh_gw;
-               dev_hold_track(dev, &work->dev_tracker, GFP_ATOMIC);
+               netdev_hold(dev, &work->dev_tracker, GFP_ATOMIC);
                work->dev = dev;
                schedule_work(&work->work);
        }
index c0b138c..fab89fd 100644 (file)
@@ -521,7 +521,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
                ipip6_tunnel_del_prl(tunnel, NULL);
        }
        dst_cache_reset(&tunnel->dst_cache);
-       dev_put_track(dev, &tunnel->dev_tracker);
+       netdev_put(dev, &tunnel->dev_tracker);
 }
 
 static int ipip6_err(struct sk_buff *skb, u32 info)
@@ -686,8 +686,6 @@ static int ipip6_rcv(struct sk_buff *skb)
        tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
                                     iph->saddr, iph->daddr, sifindex);
        if (tunnel) {
-               struct pcpu_sw_netstats *tstats;
-
                if (tunnel->parms.iph.protocol != IPPROTO_IPV6 &&
                    tunnel->parms.iph.protocol != 0)
                        goto out;
@@ -724,11 +722,7 @@ static int ipip6_rcv(struct sk_buff *skb)
                        }
                }
 
-               tstats = this_cpu_ptr(tunnel->dev->tstats);
-               u64_stats_update_begin(&tstats->syncp);
-               tstats->rx_packets++;
-               tstats->rx_bytes += skb->len;
-               u64_stats_update_end(&tstats->syncp);
+               dev_sw_netstats_rx_add(tunnel->dev, skb->len);
 
                netif_rx(skb);
 
@@ -1463,7 +1457,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
                dev->tstats = NULL;
                return err;
        }
-       dev_hold_track(dev, &tunnel->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &tunnel->dev_tracker, GFP_KERNEL);
        return 0;
 }
 
index e64e427..4a4b0e4 100644 (file)
@@ -73,11 +73,11 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        struct rt6_info *rt = (struct rt6_info *)xdst->route;
 
        xdst->u.dst.dev = dev;
-       dev_hold_track(dev, &xdst->u.dst.dev_tracker, GFP_ATOMIC);
+       netdev_hold(dev, &xdst->u.dst.dev_tracker, GFP_ATOMIC);
 
        xdst->u.rt6.rt6i_idev = in6_dev_get(dev);
        if (!xdst->u.rt6.rt6i_idev) {
-               dev_put_track(dev, &xdst->u.dst.dev_tracker);
+               netdev_put(dev, &xdst->u.dst.dev_tracker);
                return -ENODEV;
        }
 
index 7f555d2..da7fe94 100644 (file)
@@ -224,7 +224,7 @@ static int llc_ui_release(struct socket *sock)
        } else {
                release_sock(sk);
        }
-       dev_put_track(llc->dev, &llc->dev_tracker);
+       netdev_put(llc->dev, &llc->dev_tracker);
        sock_put(sk);
        llc_sk_free(sk);
 out:
index f7896f2..881efbf 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
  */
 
 #include <linux/ieee80211.h>
@@ -438,7 +438,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta = NULL;
-       const struct ieee80211_cipher_scheme *cs = NULL;
        struct ieee80211_key *key;
        int err;
 
@@ -456,23 +455,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                if (WARN_ON_ONCE(fips_enabled))
                        return -EINVAL;
                break;
-       case WLAN_CIPHER_SUITE_CCMP:
-       case WLAN_CIPHER_SUITE_CCMP_256:
-       case WLAN_CIPHER_SUITE_AES_CMAC:
-       case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-       case WLAN_CIPHER_SUITE_BIP_GMAC_128:
-       case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-       case WLAN_CIPHER_SUITE_GCMP:
-       case WLAN_CIPHER_SUITE_GCMP_256:
-               break;
        default:
-               cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type);
                break;
        }
 
        key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len,
-                                 params->key, params->seq_len, params->seq,
-                                 cs);
+                                 params->key, params->seq_len, params->seq);
        if (IS_ERR(key))
                return PTR_ERR(key);
 
@@ -537,9 +525,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                break;
        }
 
-       if (sta)
-               sta->cipher_scheme = cs;
-
        err = ieee80211_key_link(key, sdata, sta);
 
  out_unlock:
@@ -548,33 +533,53 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        return err;
 }
 
+static struct ieee80211_key *
+ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
+                    u8 key_idx, bool pairwise, const u8 *mac_addr)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct sta_info *sta;
+
+       if (mac_addr) {
+               sta = sta_info_get_bss(sdata, mac_addr);
+               if (!sta)
+                       return NULL;
+
+               if (pairwise && key_idx < NUM_DEFAULT_KEYS)
+                       return rcu_dereference_check_key_mtx(local,
+                                                            sta->ptk[key_idx]);
+
+               if (!pairwise &&
+                   key_idx < NUM_DEFAULT_KEYS +
+                             NUM_DEFAULT_MGMT_KEYS +
+                             NUM_DEFAULT_BEACON_KEYS)
+                       return rcu_dereference_check_key_mtx(local,
+                                                            sta->deflink.gtk[key_idx]);
+
+               return NULL;
+       }
+
+       if (key_idx < NUM_DEFAULT_KEYS +
+                     NUM_DEFAULT_MGMT_KEYS +
+                     NUM_DEFAULT_BEACON_KEYS)
+               return rcu_dereference_check_key_mtx(local,
+                                                    sdata->keys[key_idx]);
+
+       return NULL;
+}
+
 static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
                             u8 key_idx, bool pairwise, const u8 *mac_addr)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
-       struct sta_info *sta;
-       struct ieee80211_key *key = NULL;
+       struct ieee80211_key *key;
        int ret;
 
        mutex_lock(&local->sta_mtx);
        mutex_lock(&local->key_mtx);
 
-       if (mac_addr) {
-               ret = -ENOENT;
-
-               sta = sta_info_get_bss(sdata, mac_addr);
-               if (!sta)
-                       goto out_unlock;
-
-               if (pairwise)
-                       key = key_mtx_dereference(local, sta->ptk[key_idx]);
-               else
-                       key = key_mtx_dereference(local,
-                                                 sta->deflink.gtk[key_idx]);
-       } else
-               key = key_mtx_dereference(local, sdata->keys[key_idx]);
-
+       key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr);
        if (!key) {
                ret = -ENOENT;
                goto out_unlock;
@@ -597,10 +602,9 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                                              struct key_params *params))
 {
        struct ieee80211_sub_if_data *sdata;
-       struct sta_info *sta = NULL;
        u8 seq[6] = {0};
        struct key_params params;
-       struct ieee80211_key *key = NULL;
+       struct ieee80211_key *key;
        u64 pn64;
        u32 iv32;
        u16 iv16;
@@ -611,20 +615,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 
        rcu_read_lock();
 
-       if (mac_addr) {
-               sta = sta_info_get_bss(sdata, mac_addr);
-               if (!sta)
-                       goto out;
-
-               if (pairwise && key_idx < NUM_DEFAULT_KEYS)
-                       key = rcu_dereference(sta->ptk[key_idx]);
-               else if (!pairwise &&
-                        key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
-                        NUM_DEFAULT_BEACON_KEYS)
-                       key = rcu_dereference(sta->deflink.gtk[key_idx]);
-       } else
-               key = rcu_dereference(sdata->keys[key_idx]);
-
+       key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr);
        if (!key)
                goto out;
 
@@ -1207,9 +1198,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
                                params->crypto.control_port_over_nl80211;
        sdata->control_port_no_preauth =
                                params->crypto.control_port_no_preauth;
-       sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local,
-                                                       &params->crypto,
-                                                       sdata->vif.type);
 
        list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
                vlan->control_port_protocol =
@@ -1220,10 +1208,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
                        params->crypto.control_port_over_nl80211;
                vlan->control_port_no_preauth =
                        params->crypto.control_port_no_preauth;
-               vlan->encrypt_headroom =
-                       ieee80211_cs_headroom(sdata->local,
-                                             &params->crypto,
-                                             vlan->vif.type);
        }
 
        sdata->vif.bss_conf.dtim_period = params->dtim_period;
index 86ef0a4..1cf3315 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
  */
 
 #ifndef IEEE80211_I_H
@@ -944,7 +944,6 @@ struct ieee80211_sub_if_data {
        bool control_port_no_encrypt;
        bool control_port_no_preauth;
        bool control_port_over_nl80211;
-       int encrypt_headroom;
 
        atomic_t num_tx_queued;
        struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
@@ -2483,14 +2482,6 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work);
 int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
                              struct cfg80211_csa_settings *csa_settings);
 
-bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs);
-bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n);
-const struct ieee80211_cipher_scheme *
-ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
-                enum nl80211_iftype iftype);
-int ieee80211_cs_headroom(struct ieee80211_local *local,
-                         struct cfg80211_crypto_settings *crypto,
-                         enum nl80211_iftype iftype);
 void ieee80211_recalc_dtim(struct ieee80211_local *local,
                           struct ieee80211_sub_if_data *sdata);
 int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
index 4153147..fb8d102 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (c) 2016        Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
  */
 #include <linux/slab.h>
 #include <linux/kernel.h>
@@ -1036,8 +1036,6 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
                 wiphy_name(local->hw.wiphy));
        sdata->wdev.iftype = NL80211_IFTYPE_MONITOR;
 
-       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
-
        ieee80211_set_default_queues(sdata);
 
        ret = drv_add_interface(local, sdata);
@@ -1644,7 +1642,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
        sdata->control_port_no_encrypt = false;
        sdata->control_port_over_nl80211 = false;
        sdata->control_port_no_preauth = false;
-       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
        sdata->vif.bss_conf.idle = true;
        sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
 
@@ -2116,8 +2113,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
        sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
        sdata->user_power_level = local->user_power_level;
 
-       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
-
        /* setup type-dependent data */
        ieee80211_setup_sdata(sdata, type);
 
index 0fcf8ae..c3476de 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright 2015-2017 Intel Deutschland GmbH
- * Copyright 2018-2020  Intel Corporation
+ * Copyright 2018-2020, 2022  Intel Corporation
  */
 
 #include <linux/if_ether.h>
@@ -531,8 +531,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 struct ieee80211_key *
 ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
                    const u8 *key_data,
-                   size_t seq_len, const u8 *seq,
-                   const struct ieee80211_cipher_scheme *cs)
+                   size_t seq_len, const u8 *seq)
 {
        struct ieee80211_key *key;
        int i, j, err;
@@ -675,21 +674,6 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
                        return ERR_PTR(err);
                }
                break;
-       default:
-               if (cs) {
-                       if (seq_len && seq_len != cs->pn_len) {
-                               kfree(key);
-                               return ERR_PTR(-EINVAL);
-                       }
-
-                       key->conf.iv_len = cs->hdr_len;
-                       key->conf.icv_len = cs->mic_len;
-                       for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
-                               for (j = 0; j < seq_len; j++)
-                                       key->u.gen.rx_pn[i][j] =
-                                                       seq[seq_len - j - 1];
-                       key->flags |= KEY_FLAG_CIPHER_SCHEME;
-               }
        }
        memcpy(key->conf.key, key_data, key_len);
        INIT_LIST_HEAD(&key->list);
@@ -1294,7 +1278,7 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
 
        key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
                                  keyconf->keylen, keyconf->key,
-                                 0, NULL, NULL);
+                                 0, NULL);
        if (IS_ERR(key))
                return ERR_CAST(key);
 
index 1e326c8..e994dce 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Copyright 2002-2004, Instant802 Networks, Inc.
  * Copyright 2005, Devicescape Software, Inc.
- * Copyright (C) 2019 Intel Corporation
+ * Copyright (C) 2019, 2022 Intel Corporation
  */
 
 #ifndef IEEE80211_KEY_H
@@ -30,12 +30,10 @@ struct sta_info;
  * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present
  *     in the hardware for TX crypto hardware acceleration.
  * @KEY_FLAG_TAINTED: Key is tainted and packets should be dropped.
- * @KEY_FLAG_CIPHER_SCHEME: This key is for a hardware cipher scheme
  */
 enum ieee80211_internal_key_flags {
        KEY_FLAG_UPLOADED_TO_HARDWARE   = BIT(0),
        KEY_FLAG_TAINTED                = BIT(1),
-       KEY_FLAG_CIPHER_SCHEME          = BIT(2),
 };
 
 enum ieee80211_internal_tkip_state {
@@ -140,8 +138,7 @@ struct ieee80211_key {
 struct ieee80211_key *
 ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
                    const u8 *key_data,
-                   size_t seq_len, const u8 *seq,
-                   const struct ieee80211_cipher_scheme *cs);
+                   size_t seq_len, const u8 *seq);
 /*
  * Insert a key into data structures (sdata, sta if necessary)
  * to make it used, free old key. On failure, also free the new key.
@@ -166,6 +163,8 @@ void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata);
 
 #define key_mtx_dereference(local, ref) \
        rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
+#define rcu_dereference_check_key_mtx(local, ref) \
+       rcu_dereference_check(ref, lockdep_is_held(&((local)->key_mtx)))
 
 void ieee80211_delayed_tailroom_dec(struct work_struct *wk);
 
index 5a385d4..4f3e93c 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2017     Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
  */
 
 #include <net/mac80211.h>
@@ -778,7 +778,7 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 {
        bool have_wep = !fips_enabled; /* FIPS does not permit the use of RC4 */
        bool have_mfp = ieee80211_hw_check(&local->hw, MFP_CAPABLE);
-       int n_suites = 0, r = 0, w = 0;
+       int r = 0, w = 0;
        u32 *suites;
        static const u32 cipher_suites[] = {
                /* keep WEP first, it may be removed below */
@@ -824,10 +824,9 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
                                continue;
                        suites[w++] = suite;
                }
-       } else if (!local->hw.cipher_schemes) {
-               /* If the driver doesn't have cipher schemes, there's nothing
-                * else to do other than assign the (software supported and
-                * perhaps offloaded) cipher suites.
+       } else {
+               /* assign the (software supported and perhaps offloaded)
+                * cipher suites
                 */
                local->hw.wiphy->cipher_suites = cipher_suites;
                local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
@@ -842,58 +841,6 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 
                /* not dynamically allocated, so just return */
                return 0;
-       } else {
-               const struct ieee80211_cipher_scheme *cs;
-
-               cs = local->hw.cipher_schemes;
-
-               /* Driver specifies cipher schemes only (but not cipher suites
-                * including the schemes)
-                *
-                * We start counting ciphers defined by schemes, TKIP, CCMP,
-                * CCMP-256, GCMP, and GCMP-256
-                */
-               n_suites = local->hw.n_cipher_schemes + 5;
-
-               /* check if we have WEP40 and WEP104 */
-               if (have_wep)
-                       n_suites += 2;
-
-               /* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128,
-                * BIP-GMAC-256
-                */
-               if (have_mfp)
-                       n_suites += 4;
-
-               suites = kmalloc_array(n_suites, sizeof(u32), GFP_KERNEL);
-               if (!suites)
-                       return -ENOMEM;
-
-               suites[w++] = WLAN_CIPHER_SUITE_CCMP;
-               suites[w++] = WLAN_CIPHER_SUITE_CCMP_256;
-               suites[w++] = WLAN_CIPHER_SUITE_TKIP;
-               suites[w++] = WLAN_CIPHER_SUITE_GCMP;
-               suites[w++] = WLAN_CIPHER_SUITE_GCMP_256;
-
-               if (have_wep) {
-                       suites[w++] = WLAN_CIPHER_SUITE_WEP40;
-                       suites[w++] = WLAN_CIPHER_SUITE_WEP104;
-               }
-
-               if (have_mfp) {
-                       suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC;
-                       suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256;
-                       suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128;
-                       suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256;
-               }
-
-               for (r = 0; r < local->hw.n_cipher_schemes; r++) {
-                       suites[w++] = cs[r].cipher;
-                       if (WARN_ON(cs[r].pn_len > IEEE80211_MAX_PN_LEN)) {
-                               kfree(suites);
-                               return -EINVAL;
-                       }
-               }
        }
 
        local->hw.wiphy->cipher_suites = suites;
@@ -1168,12 +1115,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        if (local->hw.wiphy->max_scan_ie_len)
                local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
 
-       if (WARN_ON(!ieee80211_cs_list_valid(local->hw.cipher_schemes,
-                                            local->hw.n_cipher_schemes))) {
-               result = -EINVAL;
-               goto fail_workqueue;
-       }
-
        result = ieee80211_init_cipher_suites(local);
        if (result < 0)
                goto fail_workqueue;
index 58ebdcd..45e7c1b 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2008, 2009 open80211s Ltd.
- * Copyright (C) 2019, 2021 Intel Corporation
+ * Copyright (C) 2019, 2021-2022 Intel Corporation
  * Author:     Luis Carlos Cobo <luisca@cozybit.com>
  */
 
@@ -247,13 +247,13 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
                return -EAGAIN;
 
        skb = dev_alloc_skb(local->tx_headroom +
-                           sdata->encrypt_headroom +
+                           IEEE80211_ENCRYPT_HEADROOM +
                            IEEE80211_ENCRYPT_TAILROOM +
                            hdr_len +
                            2 + 15 /* PERR IE */);
        if (!skb)
                return -1;
-       skb_reserve(skb, local->tx_headroom + sdata->encrypt_headroom);
+       skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM);
        mgmt = skb_put_zero(skb, hdr_len);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                          IEEE80211_STYPE_ACTION);
index 58d48dc..6d5ad71 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2021 Intel Corporation
+ * Copyright (C) 2018 - 2022 Intel Corporation
  */
 
 #include <linux/delay.h>
@@ -2496,8 +2496,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        memset(ifmgd->tx_tspec, 0, sizeof(ifmgd->tx_tspec));
        cancel_delayed_work_sync(&ifmgd->tx_tspec_wk);
 
-       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
-
        bss_conf->pwr_reduction = 0;
        bss_conf->tx_pwr_env_num = 0;
        memset(bss_conf->tx_pwr_env, 0, sizeof(bss_conf->tx_pwr_env));
@@ -6071,8 +6069,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        sdata->control_port_over_nl80211 =
                                        req->crypto.control_port_over_nl80211;
        sdata->control_port_no_preauth = req->crypto.control_port_no_preauth;
-       sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto,
-                                                       sdata->vif.type);
 
        /* kick off associate process */
 
index 3c08ae0..a9f4e90 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
  */
 
 #include <linux/jiffies.h>
@@ -1009,43 +1009,20 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
        return -1;
 }
 
-static int ieee80211_get_keyid(struct sk_buff *skb,
-                              const struct ieee80211_cipher_scheme *cs)
+static int ieee80211_get_keyid(struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       __le16 fc;
-       int hdrlen;
-       int minlen;
-       u8 key_idx_off;
-       u8 key_idx_shift;
+       __le16 fc = hdr->frame_control;
+       int hdrlen = ieee80211_hdrlen(fc);
        u8 keyid;
 
-       fc = hdr->frame_control;
-       hdrlen = ieee80211_hdrlen(fc);
-
-       if (cs) {
-               minlen = hdrlen + cs->hdr_len;
-               key_idx_off = hdrlen + cs->key_idx_off;
-               key_idx_shift = cs->key_idx_shift;
-       } else {
-               /* WEP, TKIP, CCMP and GCMP */
-               minlen = hdrlen + IEEE80211_WEP_IV_LEN;
-               key_idx_off = hdrlen + 3;
-               key_idx_shift = 6;
-       }
-
-       if (unlikely(skb->len < minlen))
+       /* WEP, TKIP, CCMP and GCMP */
+       if (unlikely(skb->len < hdrlen + IEEE80211_WEP_IV_LEN))
                return -EINVAL;
 
-       skb_copy_bits(skb, key_idx_off, &keyid, 1);
+       skb_copy_bits(skb, hdrlen + 3, &keyid, 1);
 
-       if (cs)
-               keyid &= cs->key_idx_mask;
-       keyid >>= key_idx_shift;
-
-       /* cs could use more than the usual two bits for the keyid */
-       if (unlikely(keyid >= NUM_DEFAULT_KEYS))
-               return -EINVAL;
+       keyid >>= 6;
 
        return keyid;
 }
@@ -1916,7 +1893,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
        struct ieee80211_key *ptk_idx = NULL;
        int mmie_keyidx = -1;
        __le16 fc;
-       const struct ieee80211_cipher_scheme *cs = NULL;
 
        if (ieee80211_is_ext(hdr->frame_control))
                return RX_CONTINUE;
@@ -1959,8 +1935,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
 
                if (ieee80211_has_protected(fc) &&
                    !(status->flag & RX_FLAG_IV_STRIPPED)) {
-                       cs = rx->sta->cipher_scheme;
-                       keyid = ieee80211_get_keyid(rx->skb, cs);
+                       keyid = ieee80211_get_keyid(rx->skb);
 
                        if (unlikely(keyid < 0))
                                return RX_DROP_UNUSABLE;
@@ -2065,7 +2040,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                    (status->flag & RX_FLAG_IV_STRIPPED))
                        return RX_CONTINUE;
 
-               keyidx = ieee80211_get_keyid(rx->skb, cs);
+               keyidx = ieee80211_get_keyid(rx->skb);
 
                if (unlikely(keyidx < 0))
                        return RX_DROP_UNUSABLE;
@@ -2131,7 +2106,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                result = ieee80211_crypto_gcmp_decrypt(rx);
                break;
        default:
-               result = ieee80211_crypto_hw_decrypt(rx);
+               result = RX_DROP_UNUSABLE;
        }
 
        /* the hdr variable is invalid after the decrypt handlers */
@@ -2945,7 +2920,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                tailroom = IEEE80211_ENCRYPT_TAILROOM;
 
        fwd_skb = skb_copy_expand(skb, local->tx_headroom +
-                                      sdata->encrypt_headroom,
+                                      IEEE80211_ENCRYPT_HEADROOM,
                                  tailroom, GFP_ATOMIC);
        if (!fwd_skb)
                goto out;
index 35c390b..aa6950a 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright 2002-2005, Devicescape Software, Inc.
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright(c) 2020-2021 Intel Corporation
+ * Copyright(c) 2020-2022 Intel Corporation
  */
 
 #ifndef STA_INFO_H
@@ -616,7 +616,6 @@ struct link_sta_info {
  *     taken from HT/VHT capabilities or VHT operating mode notification
  * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
  *     AP only.
- * @cipher_scheme: optional cipher scheme for this station
  * @cparams: CoDel parameters for this station.
  * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED)
  * @fast_tx: TX fastpath information
@@ -700,7 +699,6 @@ struct sta_info {
 #endif
 
        enum ieee80211_smps_mode known_smps_mode;
-       const struct ieee80211_cipher_scheme *cipher_scheme;
 
        struct codel_params cparams;
 
index 0e4efc0..37fe72b 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
  *
  * Transmit and frame generation functions.
  */
@@ -882,7 +882,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx,
                rem -= fraglen;
                tmp = dev_alloc_skb(local->tx_headroom +
                                    frag_threshold +
-                                   tx->sdata->encrypt_headroom +
+                                   IEEE80211_ENCRYPT_HEADROOM +
                                    IEEE80211_ENCRYPT_TAILROOM);
                if (!tmp)
                        return -ENOMEM;
@@ -890,7 +890,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx,
                __skb_queue_tail(&tx->skbs, tmp);
 
                skb_reserve(tmp,
-                           local->tx_headroom + tx->sdata->encrypt_headroom);
+                           local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM);
 
                /* copy control information */
                memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
@@ -1040,8 +1040,6 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
        case WLAN_CIPHER_SUITE_GCMP:
        case WLAN_CIPHER_SUITE_GCMP_256:
                return ieee80211_crypto_gcmp_encrypt(tx);
-       default:
-               return ieee80211_crypto_hw_encrypt(tx);
        }
 
        return TX_DROP;
@@ -2013,7 +2011,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
 
        headroom = local->tx_headroom;
        if (encrypt != ENCRYPT_NO)
-               headroom += sdata->encrypt_headroom;
+               headroom += IEEE80211_ENCRYPT_HEADROOM;
        headroom -= skb_headroom(skb);
        headroom = max_t(int, 0, headroom);
 
@@ -2867,7 +2865,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
         */
 
        if (head_need > 0 || skb_cloned(skb)) {
-               head_need += sdata->encrypt_headroom;
+               head_need += IEEE80211_ENCRYPT_HEADROOM;
                head_need += local->tx_headroom;
                head_need = max_t(int, 0, head_need);
                if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) {
@@ -3128,15 +3126,6 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
                        /* we don't know how to generate IVs for this at all */
                        if (WARN_ON(gen_iv))
                                goto out;
-                       /* pure hardware keys are OK, of course */
-                       if (!(build.key->flags & KEY_FLAG_CIPHER_SCHEME))
-                               break;
-                       /* cipher scheme might require space allocation */
-                       if (iv_spc &&
-                           build.key->conf.iv_len > IEEE80211_FAST_XMIT_MAX_IV)
-                               goto out;
-                       if (iv_spc)
-                               build.hdr_len += build.key->conf.iv_len;
                }
 
                fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
index 1e26b52..9e6c4dc 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017     Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
  *
  * utilities for mac80211
  */
@@ -4212,74 +4212,6 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
        return 0;
 }
 
-bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs)
-{
-       return !(cs == NULL || cs->cipher == 0 ||
-                cs->hdr_len < cs->pn_len + cs->pn_off ||
-                cs->hdr_len <= cs->key_idx_off ||
-                cs->key_idx_shift > 7 ||
-                cs->key_idx_mask == 0);
-}
-
-bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n)
-{
-       int i;
-
-       /* Ensure we have enough iftype bitmap space for all iftype values */
-       WARN_ON((NUM_NL80211_IFTYPES / 8 + 1) > sizeof(cs[0].iftype));
-
-       for (i = 0; i < n; i++)
-               if (!ieee80211_cs_valid(&cs[i]))
-                       return false;
-
-       return true;
-}
-
-const struct ieee80211_cipher_scheme *
-ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
-                enum nl80211_iftype iftype)
-{
-       const struct ieee80211_cipher_scheme *l = local->hw.cipher_schemes;
-       int n = local->hw.n_cipher_schemes;
-       int i;
-       const struct ieee80211_cipher_scheme *cs = NULL;
-
-       for (i = 0; i < n; i++) {
-               if (l[i].cipher == cipher) {
-                       cs = &l[i];
-                       break;
-               }
-       }
-
-       if (!cs || !(cs->iftype & BIT(iftype)))
-               return NULL;
-
-       return cs;
-}
-
-int ieee80211_cs_headroom(struct ieee80211_local *local,
-                         struct cfg80211_crypto_settings *crypto,
-                         enum nl80211_iftype iftype)
-{
-       const struct ieee80211_cipher_scheme *cs;
-       int headroom = IEEE80211_ENCRYPT_HEADROOM;
-       int i;
-
-       for (i = 0; i < crypto->n_ciphers_pairwise; i++) {
-               cs = ieee80211_cs_get(local, crypto->ciphers_pairwise[i],
-                                     iftype);
-
-               if (cs && headroom < cs->hdr_len)
-                       headroom = cs->hdr_len;
-       }
-
-       cs = ieee80211_cs_get(local, crypto->cipher_group, iftype);
-       if (cs && headroom < cs->hdr_len)
-               headroom = cs->hdr_len;
-
-       return headroom;
-}
-
 static bool
 ieee80211_extend_noa_desc(struct ieee80211_noa_data *data, u32 tsf, int i)
 {
index 5fd8a3e..93ec2f3 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright 2002-2004, Instant802 Networks, Inc.
  * Copyright 2008, Jouni Malinen <j@w1.fi>
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2020-2021 Intel Corporation
+ * Copyright (C) 2020-2022 Intel Corporation
  */
 
 #include <linux/netdevice.h>
@@ -778,102 +778,6 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
-static ieee80211_tx_result
-ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
-                           struct sk_buff *skb)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct ieee80211_key *key = tx->key;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       int hdrlen;
-       u8 *pos, iv_len = key->conf.iv_len;
-
-       if (info->control.hw_key &&
-           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
-               /* hwaccel has no need for preallocated head room */
-               return TX_CONTINUE;
-       }
-
-       if (unlikely(skb_headroom(skb) < iv_len &&
-                    pskb_expand_head(skb, iv_len, 0, GFP_ATOMIC)))
-               return TX_DROP;
-
-       hdrlen = ieee80211_hdrlen(hdr->frame_control);
-
-       pos = skb_push(skb, iv_len);
-       memmove(pos, pos + iv_len, hdrlen);
-
-       return TX_CONTINUE;
-}
-
-static inline int ieee80211_crypto_cs_pn_compare(u8 *pn1, u8 *pn2, int len)
-{
-       int i;
-
-       /* pn is little endian */
-       for (i = len - 1; i >= 0; i--) {
-               if (pn1[i] < pn2[i])
-                       return -1;
-               else if (pn1[i] > pn2[i])
-                       return 1;
-       }
-
-       return 0;
-}
-
-static ieee80211_rx_result
-ieee80211_crypto_cs_decrypt(struct ieee80211_rx_data *rx)
-{
-       struct ieee80211_key *key = rx->key;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-       const struct ieee80211_cipher_scheme *cs = NULL;
-       int hdrlen = ieee80211_hdrlen(hdr->frame_control);
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-       int data_len;
-       u8 *rx_pn;
-       u8 *skb_pn;
-       u8 qos_tid;
-
-       if (!rx->sta || !rx->sta->cipher_scheme ||
-           !(status->flag & RX_FLAG_DECRYPTED))
-               return RX_DROP_UNUSABLE;
-
-       if (!ieee80211_is_data(hdr->frame_control))
-               return RX_CONTINUE;
-
-       cs = rx->sta->cipher_scheme;
-
-       data_len = rx->skb->len - hdrlen - cs->hdr_len;
-
-       if (data_len < 0)
-               return RX_DROP_UNUSABLE;
-
-       if (ieee80211_is_data_qos(hdr->frame_control))
-               qos_tid = ieee80211_get_tid(hdr);
-       else
-               qos_tid = 0;
-
-       if (skb_linearize(rx->skb))
-               return RX_DROP_UNUSABLE;
-
-       rx_pn = key->u.gen.rx_pn[qos_tid];
-       skb_pn = rx->skb->data + hdrlen + cs->pn_off;
-
-       if (ieee80211_crypto_cs_pn_compare(skb_pn, rx_pn, cs->pn_len) <= 0)
-               return RX_DROP_UNUSABLE;
-
-       memcpy(rx_pn, skb_pn, cs->pn_len);
-
-       /* remove security header and MIC */
-       if (pskb_trim(rx->skb, rx->skb->len - cs->mic_len))
-               return RX_DROP_UNUSABLE;
-
-       memmove(rx->skb->data + cs->hdr_len, rx->skb->data, hdrlen);
-       skb_pull(rx->skb, cs->hdr_len);
-
-       return RX_CONTINUE;
-}
-
 static void bip_aad(struct sk_buff *skb, u8 *aad)
 {
        __le16 mask_fc;
@@ -1212,38 +1116,3 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
 
        return RX_CONTINUE;
 }
-
-ieee80211_tx_result
-ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
-{
-       struct sk_buff *skb;
-       struct ieee80211_tx_info *info = NULL;
-       ieee80211_tx_result res;
-
-       skb_queue_walk(&tx->skbs, skb) {
-               info  = IEEE80211_SKB_CB(skb);
-
-               /* handle hw-only algorithm */
-               if (!info->control.hw_key)
-                       return TX_DROP;
-
-               if (tx->key->flags & KEY_FLAG_CIPHER_SCHEME) {
-                       res = ieee80211_crypto_cs_encrypt(tx, skb);
-                       if (res != TX_CONTINUE)
-                               return res;
-               }
-       }
-
-       ieee80211_tx_set_protected(tx);
-
-       return TX_CONTINUE;
-}
-
-ieee80211_rx_result
-ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx)
-{
-       if (rx->sta && rx->sta->cipher_scheme)
-               return ieee80211_crypto_cs_decrypt(rx);
-
-       return RX_DROP_UNUSABLE;
-}
index af32722..a9a81ab 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright (C) 2022 Intel Corporation
  */
 
 #ifndef WPA_H
@@ -39,10 +40,6 @@ ieee80211_tx_result
 ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx);
 ieee80211_rx_result
 ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx);
-ieee80211_tx_result
-ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx);
-ieee80211_rx_result
-ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx);
 
 ieee80211_tx_result
 ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx);
index b498dac..2f61d5b 100644 (file)
@@ -115,7 +115,7 @@ error_master_upper_dev_unlink:
 error_unlock:
        rtnl_unlock();
 error_put:
-       dev_put_track(vport->dev, &vport->dev_tracker);
+       netdev_put(vport->dev, &vport->dev_tracker);
 error_free_vport:
        ovs_vport_free(vport);
        return ERR_PTR(err);
@@ -137,7 +137,7 @@ static void vport_netdev_free(struct rcu_head *rcu)
 {
        struct vport *vport = container_of(rcu, struct vport, rcu);
 
-       dev_put_track(vport->dev, &vport->dev_tracker);
+       netdev_put(vport->dev, &vport->dev_tracker);
        ovs_vport_free(vport);
 }
 
@@ -173,7 +173,7 @@ void ovs_netdev_tunnel_destroy(struct vport *vport)
         */
        if (vport->dev->reg_state == NETREG_REGISTERED)
                rtnl_delete_link(vport->dev);
-       dev_put_track(vport->dev, &vport->dev_tracker);
+       netdev_put(vport->dev, &vport->dev_tracker);
        vport->dev = NULL;
        rtnl_unlock();
 
index ca6e92a..d08c472 100644 (file)
@@ -3134,7 +3134,7 @@ static int packet_release(struct socket *sock)
        packet_cached_dev_reset(po);
 
        if (po->prot_hook.dev) {
-               dev_put_track(po->prot_hook.dev, &po->prot_hook.dev_tracker);
+               netdev_put(po->prot_hook.dev, &po->prot_hook.dev_tracker);
                po->prot_hook.dev = NULL;
        }
        spin_unlock(&po->bind_lock);
@@ -3235,15 +3235,15 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex,
                WRITE_ONCE(po->num, proto);
                po->prot_hook.type = proto;
 
-               dev_put_track(po->prot_hook.dev, &po->prot_hook.dev_tracker);
+               netdev_put(po->prot_hook.dev, &po->prot_hook.dev_tracker);
 
                if (unlikely(unlisted)) {
                        po->prot_hook.dev = NULL;
                        WRITE_ONCE(po->ifindex, -1);
                        packet_cached_dev_reset(po);
                } else {
-                       dev_hold_track(dev, &po->prot_hook.dev_tracker,
-                                      GFP_ATOMIC);
+                       netdev_hold(dev, &po->prot_hook.dev_tracker,
+                                   GFP_ATOMIC);
                        po->prot_hook.dev = dev;
                        WRITE_ONCE(po->ifindex, dev ? dev->ifindex : 0);
                        packet_cached_dev_assign(po, dev);
@@ -4167,8 +4167,8 @@ static int packet_notifier(struct notifier_block *this,
                                if (msg == NETDEV_UNREGISTER) {
                                        packet_cached_dev_reset(po);
                                        WRITE_ONCE(po->ifindex, -1);
-                                       dev_put_track(po->prot_hook.dev,
-                                                     &po->prot_hook.dev_tracker);
+                                       netdev_put(po->prot_hook.dev,
+                                                  &po->prot_hook.dev_tracker);
                                        po->prot_hook.dev = NULL;
                                }
                                spin_unlock(&po->bind_lock);
index ebb92fb..a1d70cf 100644 (file)
@@ -79,7 +79,7 @@ static void tcf_mirred_release(struct tc_action *a)
 
        /* last reference to action, no need to lock */
        dev = rcu_dereference_protected(m->tcfm_dev, 1);
-       dev_put_track(dev, &m->tcfm_dev_tracker);
+       netdev_put(dev, &m->tcfm_dev_tracker);
 }
 
 static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
@@ -181,7 +181,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                mac_header_xmit = dev_is_mac_header_xmit(ndev);
                odev = rcu_replace_pointer(m->tcfm_dev, ndev,
                                          lockdep_is_held(&m->tcf_lock));
-               dev_put_track(odev, &m->tcfm_dev_tracker);
+               netdev_put(odev, &m->tcfm_dev_tracker);
                netdev_tracker_alloc(ndev, &m->tcfm_dev_tracker, GFP_ATOMIC);
                m->tcfm_mac_header_xmit = mac_header_xmit;
        }
@@ -402,7 +402,7 @@ static int mirred_device_event(struct notifier_block *unused,
                list_for_each_entry(m, &mirred_list, tcfm_list) {
                        spin_lock_bh(&m->tcf_lock);
                        if (tcf_mirred_dev_dereference(m) == dev) {
-                               dev_put_track(dev, &m->tcfm_dev_tracker);
+                               netdev_put(dev, &m->tcfm_dev_tracker);
                                /* Note : no rcu grace period necessary, as
                                 * net_device are already rcu protected.
                                 */
index e3c0e8e..bf87b50 100644 (file)
@@ -1292,7 +1292,7 @@ err_out5:
        if (ops->destroy)
                ops->destroy(sch);
 err_out3:
-       dev_put_track(dev, &sch->dev_tracker);
+       netdev_put(dev, &sch->dev_tracker);
        qdisc_free(sch);
 err_out2:
        module_put(ops->owner);
index dba0b3e..cc6eabe 100644 (file)
@@ -541,7 +541,7 @@ static void dev_watchdog(struct timer_list *t)
        spin_unlock(&dev->tx_global_lock);
 
        if (release)
-               dev_put_track(dev, &dev->watchdog_dev_tracker);
+               netdev_put(dev, &dev->watchdog_dev_tracker);
 }
 
 void __netdev_watchdog_up(struct net_device *dev)
@@ -551,7 +551,8 @@ void __netdev_watchdog_up(struct net_device *dev)
                        dev->watchdog_timeo = 5*HZ;
                if (!mod_timer(&dev->watchdog_timer,
                               round_jiffies(jiffies + dev->watchdog_timeo)))
-                       dev_hold_track(dev, &dev->watchdog_dev_tracker, GFP_ATOMIC);
+                       netdev_hold(dev, &dev->watchdog_dev_tracker,
+                                   GFP_ATOMIC);
        }
 }
 EXPORT_SYMBOL_GPL(__netdev_watchdog_up);
@@ -565,7 +566,7 @@ static void dev_watchdog_down(struct net_device *dev)
 {
        netif_tx_lock_bh(dev);
        if (del_timer(&dev->watchdog_timer))
-               dev_put_track(dev, &dev->watchdog_dev_tracker);
+               netdev_put(dev, &dev->watchdog_dev_tracker);
        netif_tx_unlock_bh(dev);
 }
 
@@ -975,7 +976,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
        sch->enqueue = ops->enqueue;
        sch->dequeue = ops->dequeue;
        sch->dev_queue = dev_queue;
-       dev_hold_track(dev, &sch->dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &sch->dev_tracker, GFP_KERNEL);
        refcount_set(&sch->refcnt, 1);
 
        return sch;
@@ -1067,7 +1068,7 @@ static void qdisc_destroy(struct Qdisc *qdisc)
                ops->destroy(qdisc);
 
        module_put(ops->owner);
-       dev_put_track(qdisc_dev(qdisc), &qdisc->dev_tracker);
+       netdev_put(qdisc_dev(qdisc), &qdisc->dev_tracker);
 
        trace_qdisc_destroy(qdisc);
 
index 7055ed1..4c3bf6d 100644 (file)
@@ -120,7 +120,8 @@ static int smc_pnet_remove_by_pnetid(struct net *net, char *pnet_name)
                    smc_pnet_match(pnetelem->pnet_name, pnet_name)) {
                        list_del(&pnetelem->list);
                        if (pnetelem->type == SMC_PNET_ETH && pnetelem->ndev) {
-                               dev_put_track(pnetelem->ndev, &pnetelem->dev_tracker);
+                               netdev_put(pnetelem->ndev,
+                                          &pnetelem->dev_tracker);
                                pr_warn_ratelimited("smc: net device %s "
                                                    "erased user defined "
                                                    "pnetid %.16s\n",
@@ -196,7 +197,7 @@ static int smc_pnet_add_by_ndev(struct net_device *ndev)
        list_for_each_entry_safe(pnetelem, tmp_pe, &pnettable->pnetlist, list) {
                if (pnetelem->type == SMC_PNET_ETH && !pnetelem->ndev &&
                    !strncmp(pnetelem->eth_name, ndev->name, IFNAMSIZ)) {
-                       dev_hold_track(ndev, &pnetelem->dev_tracker, GFP_ATOMIC);
+                       netdev_hold(ndev, &pnetelem->dev_tracker, GFP_ATOMIC);
                        pnetelem->ndev = ndev;
                        rc = 0;
                        pr_warn_ratelimited("smc: adding net device %s with "
@@ -227,7 +228,7 @@ static int smc_pnet_remove_by_ndev(struct net_device *ndev)
        mutex_lock(&pnettable->lock);
        list_for_each_entry_safe(pnetelem, tmp_pe, &pnettable->pnetlist, list) {
                if (pnetelem->type == SMC_PNET_ETH && pnetelem->ndev == ndev) {
-                       dev_put_track(pnetelem->ndev, &pnetelem->dev_tracker);
+                       netdev_put(pnetelem->ndev, &pnetelem->dev_tracker);
                        pnetelem->ndev = NULL;
                        rc = 0;
                        pr_warn_ratelimited("smc: removing net device %s with "
index 474f763..8cc42ae 100644 (file)
@@ -64,7 +64,7 @@ void switchdev_deferred_process(void)
 
        while ((dfitem = switchdev_deferred_dequeue())) {
                dfitem->func(dfitem->dev, dfitem->data);
-               dev_put_track(dfitem->dev, &dfitem->dev_tracker);
+               netdev_put(dfitem->dev, &dfitem->dev_tracker);
                kfree(dfitem);
        }
 }
@@ -91,7 +91,7 @@ static int switchdev_deferred_enqueue(struct net_device *dev,
        dfitem->dev = dev;
        dfitem->func = func;
        memcpy(dfitem->data, data, data_len);
-       dev_hold_track(dev, &dfitem->dev_tracker, GFP_ATOMIC);
+       netdev_hold(dev, &dfitem->dev_tracker, GFP_ATOMIC);
        spin_lock_bh(&deferred_lock);
        list_add_tail(&dfitem->list, &deferred);
        spin_unlock_bh(&deferred_lock);
index 932c87b..35cac77 100644 (file)
@@ -788,7 +788,7 @@ int tipc_attach_loopback(struct net *net)
        if (!dev)
                return -ENODEV;
 
-       dev_hold_track(dev, &tn->loopback_pt.dev_tracker, GFP_KERNEL);
+       netdev_hold(dev, &tn->loopback_pt.dev_tracker, GFP_KERNEL);
        tn->loopback_pt.dev = dev;
        tn->loopback_pt.type = htons(ETH_P_TIPC);
        tn->loopback_pt.func = tipc_loopback_rcv_pkt;
@@ -801,7 +801,7 @@ void tipc_detach_loopback(struct net *net)
        struct tipc_net *tn = tipc_net(net);
 
        dev_remove_pack(&tn->loopback_pt);
-       dev_put_track(net->loopback_dev, &tn->loopback_pt.dev_tracker);
+       netdev_put(net->loopback_dev, &tn->loopback_pt.dev_tracker);
 }
 
 /* Caller should hold rtnl_lock to protect the bearer */
index 2206e6f..3453e00 100644 (file)
@@ -302,7 +302,7 @@ static void __unix_remove_socket(struct sock *sk)
 
 static void __unix_insert_socket(struct sock *sk)
 {
-       WARN_ON(!sk_unhashed(sk));
+       DEBUG_NET_WARN_ON_ONCE(!sk_unhashed(sk));
        sk_add_node(sk, &unix_socket_table[sk->sk_hash]);
 }
 
@@ -554,9 +554,9 @@ static void unix_sock_destructor(struct sock *sk)
                u->oob_skb = NULL;
        }
 #endif
-       WARN_ON(refcount_read(&sk->sk_wmem_alloc));
-       WARN_ON(!sk_unhashed(sk));
-       WARN_ON(sk->sk_socket);
+       DEBUG_NET_WARN_ON_ONCE(refcount_read(&sk->sk_wmem_alloc));
+       DEBUG_NET_WARN_ON_ONCE(!sk_unhashed(sk));
+       DEBUG_NET_WARN_ON_ONCE(sk->sk_socket);
        if (!sock_flag(sk, SOCK_DEAD)) {
                pr_info("Attempt to release alive unix socket: %p\n", sk);
                return;
index 35c7e89..637ca88 100644 (file)
@@ -275,7 +275,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
                xso->dev = NULL;
                xso->dir = 0;
                xso->real_dev = NULL;
-               dev_put_track(dev, &xso->dev_tracker);
+               netdev_put(dev, &xso->dev_tracker);
 
                if (err != -EOPNOTSUPP)
                        return err;