Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorDavid S. Miller <davem@davemloft.net>
Sun, 30 Oct 2016 16:42:58 +0000 (12:42 -0400)
committerDavid S. Miller <davem@davemloft.net>
Sun, 30 Oct 2016 16:42:58 +0000 (12:42 -0400)
Mostly simple overlapping changes.

For example, David Ahern's adjacency list revamp in 'net-next'
conflicted with an adjacency list traversal bug fix in 'net'.

Signed-off-by: David S. Miller <davem@davemloft.net>
640 files changed:
Documentation/devicetree/bindings/net/dsa/marvell.txt
Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
Documentation/devicetree/bindings/net/smsc-lan91c111.txt
Documentation/devicetree/bindings/net/ti,dp83867.txt
Documentation/networking/batman-adv.txt
Documentation/networking/mac80211_hwsim/README
MAINTAINERS
arch/arm/boot/dts/dra72-evm-revc.dts
arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
arch/arm/mach-pxa/idp.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/stargate2.c
arch/arm64/configs/defconfig
arch/m68k/emu/nfeth.c
arch/mn10300/unit-asb2303/include/unit/smc91111.h
arch/um/drivers/net_kern.c
drivers/acpi/event.c
drivers/char/pcmcia/synclink_cs.c
drivers/firewire/net.c
drivers/hsi/clients/ssi_protocol.c
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/roce_gid_mgmt.c
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/nes/nes.h
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/isdn/hysdn/hysdn_net.c
drivers/media/dvb-core/dvb_net.c
drivers/message/fusion/mptlan.c
drivers/misc/sgi-xp/xpnet.c
drivers/net/appletalk/ipddp.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/cris/eth_v10.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/global2.c
drivers/net/dsa/mv88e6xxx/global2.h
drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
drivers/net/ethernet/3com/3c509.c
drivers/net/ethernet/3com/3c515.c
drivers/net/ethernet/3com/3c574_cs.c
drivers/net/ethernet/3com/3c589_cs.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/3com/typhoon.c
drivers/net/ethernet/8390/8390.c
drivers/net/ethernet/8390/8390p.c
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/8390/axnet_cs.c
drivers/net/ethernet/8390/etherh.c
drivers/net/ethernet/8390/hydra.c
drivers/net/ethernet/8390/mac8390.c
drivers/net/ethernet/8390/mcf8390.c
drivers/net/ethernet/8390/ne2k-pci.c
drivers/net/ethernet/8390/pcnet_cs.c
drivers/net/ethernet/8390/smc-ultra.c
drivers/net/ethernet/8390/wd.c
drivers/net/ethernet/8390/zorro8390.c
drivers/net/ethernet/adaptec/starfire.c
drivers/net/ethernet/adi/bfin_mac.c
drivers/net/ethernet/agere/et131x.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/alteon/acenic.c
drivers/net/ethernet/altera/altera_tse.h
drivers/net/ethernet/altera/altera_tse_main.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/amd/a2065.c
drivers/net/ethernet/amd/am79c961a.c
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/ariadne.c
drivers/net/ethernet/amd/atarilance.c
drivers/net/ethernet/amd/au1000_eth.c
drivers/net/ethernet/amd/declance.c
drivers/net/ethernet/amd/hplance.c
drivers/net/ethernet/amd/lance.c
drivers/net/ethernet/amd/mvme147.c
drivers/net/ethernet/amd/ni65.c
drivers/net/ethernet/amd/nmclan_cs.c
drivers/net/ethernet/amd/pcnet32.c
drivers/net/ethernet/amd/sun3lance.c
drivers/net/ethernet/amd/sunlance.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/amd/xgbe/xgbe-main.c
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
drivers/net/ethernet/apm/xgene/xgene_enet_main.h
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
drivers/net/ethernet/apple/bmac.c
drivers/net/ethernet/apple/mace.c
drivers/net/ethernet/apple/macmace.c
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/atheros/alx/hw.h
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/atheros/atlx/atl1.c
drivers/net/ethernet/atheros/atlx/atl2.c
drivers/net/ethernet/atheros/atlx/atl2.h
drivers/net/ethernet/aurora/nb8800.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/sb1250-mac.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/calxeda/xgmac.c
drivers/net/ethernet/cavium/liquidio/lio_main.c
drivers/net/ethernet/cavium/liquidio/octeon_network.h
drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/chelsio/cxgb/common.h
drivers/net/ethernet/chelsio/cxgb/cxgb2.c
drivers/net/ethernet/chelsio/cxgb/pm3393.c
drivers/net/ethernet/chelsio/cxgb/vsc7326.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/cirrus/cs89x0.c
drivers/net/ethernet/cirrus/ep93xx_eth.c
drivers/net/ethernet/cirrus/mac89x0.c
drivers/net/ethernet/cisco/enic/enic_main.c
drivers/net/ethernet/cisco/enic/enic_res.h
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/dec/tulip/de2104x.c
drivers/net/ethernet/dec/tulip/de4x5.c
drivers/net/ethernet/dec/tulip/dmfe.c
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/dec/tulip/uli526x.c
drivers/net/ethernet/dec/tulip/winbond-840.c
drivers/net/ethernet/dec/tulip/xircom_cb.c
drivers/net/ethernet/dlink/dl2k.c
drivers/net/ethernet/dlink/sundance.c
drivers/net/ethernet/dnet.c
drivers/net/ethernet/ec_bhf.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/fealnx.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_mpc52xx.c
drivers/net/ethernet/freescale/fman/mac.c
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/fs_enet/fs_enet.h
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/fujitsu/fmvj18x_cs.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/hisilicon/hisi_femac.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/hp/hp100.c
drivers/net/ethernet/i825xx/82596.c
drivers/net/ethernet/i825xx/ether1.c
drivers/net/ethernet/i825xx/lib82596.c
drivers/net/ethernet/i825xx/sun3_82586.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/emac/core.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/e100.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_client.c
drivers/net/ethernet/intel/i40e/i40e_client.h
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
drivers/net/ethernet/intel/i40evf/i40e_txrx.c
drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
drivers/net/ethernet/intel/i40evf/i40evf.h
drivers/net/ethernet/intel/i40evf/i40evf_main.c
drivers/net/ethernet/intel/igb/e1000_defines.h
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igbvf/defines.h
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/korina.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/marvell/skge.h
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlxsw/Kconfig
drivers/net/ethernet/mellanox/mlxsw/cmd.h
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/core.h
drivers/net/ethernet/mellanox/mlxsw/item.h
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/pci.h
drivers/net/ethernet/mellanox/mlxsw/pci_hw.h [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/resources.h [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/mellanox/mlxsw/switchx2.c
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/micrel/ksz884x.c
drivers/net/ethernet/microchip/enc28j60.c
drivers/net/ethernet/moxa/moxart_ether.c
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/natsemi/jazzsonic.c
drivers/net/ethernet/natsemi/macsonic.c
drivers/net/ethernet/natsemi/natsemi.c
drivers/net/ethernet/natsemi/ns83820.c
drivers/net/ethernet/natsemi/xtsonic.c
drivers/net/ethernet/neterion/s2io.c
drivers/net/ethernet/neterion/vxge/vxge-config.h
drivers/net/ethernet/neterion/vxge/vxge-main.c
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfp_net_offload.c
drivers/net/ethernet/netx-eth.c
drivers/net/ethernet/nuvoton/w90p910_ether.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/packetengines/hamachi.c
drivers/net/ethernet/packetengines/yellowfin.c
drivers/net/ethernet/pasemi/pasemi_mac.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/qlogic/qed/qed_l2.c
drivers/net/ethernet/qlogic/qed/qed_roce.c
drivers/net/ethernet/qlogic/qed/qed_sp.h
drivers/net/ethernet/qlogic/qed/qed_spq.c
drivers/net/ethernet/qlogic/qed/qed_sriov.c
drivers/net/ethernet/qlogic/qed/qed_sriov.h
drivers/net/ethernet/qlogic/qed/qed_vf.c
drivers/net/ethernet/qlogic/qed/qed_vf.h
drivers/net/ethernet/qlogic/qede/qede.h
drivers/net/ethernet/qlogic/qede/qede_ethtool.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/qualcomm/emac/emac.c
drivers/net/ethernet/qualcomm/qca_framing.h
drivers/net/ethernet/qualcomm/qca_spi.c
drivers/net/ethernet/rdc/r6040.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/8139too.c
drivers/net/ethernet/realtek/atp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
drivers/net/ethernet/seeq/ether3.c
drivers/net/ethernet/seeq/sgiseeq.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sgi/ioc3-eth.c
drivers/net/ethernet/sgi/meth.c
drivers/net/ethernet/silan/sc92031.c
drivers/net/ethernet/sis/sis190.c
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/smsc/epic100.c
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/smsc/smc9194.c
drivers/net/ethernet/smsc/smc91c92_cs.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smc91x.h
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/sun/ldmvsw.c
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/sun/sunbmac.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/sun/sunqe.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/sun/sunvnet_common.c
drivers/net/ethernet/sun/sunvnet_common.h
drivers/net/ethernet/synopsys/dwc_eth_qos.c
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/tehuti/tehuti.h
drivers/net/ethernet/ti/cpmac.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/ethernet/ti/tlan.c
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/tile/tilepro.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/toshiba/ps3_gelic_net.h
drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
drivers/net/ethernet/toshiba/spider_net.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/tundra/tsi108_eth.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/wiznet/w5100.c
drivers/net/ethernet/wiznet/w5300.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xircom/xirc2ps_cs.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/fddi/skfp/skfddi.c
drivers/net/fjes/Makefile
drivers/net/fjes/fjes.h
drivers/net/fjes/fjes_debugfs.c [new file with mode: 0644]
drivers/net/fjes/fjes_ethtool.c
drivers/net/fjes/fjes_hw.c
drivers/net/fjes/fjes_hw.h
drivers/net/fjes/fjes_main.c
drivers/net/fjes/fjes_trace.c [new file with mode: 0644]
drivers/net/fjes/fjes_trace.h [new file with mode: 0644]
drivers/net/geneve.c
drivers/net/gtp.c
drivers/net/hippi/rrunner.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/macsec.c
drivers/net/macvlan.c
drivers/net/ntb_netdev.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/aquantia.c
drivers/net/phy/at803x.c
drivers/net/phy/broadcom.c
drivers/net/phy/dp83867.c
drivers/net/phy/mscc.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/phy_led_triggers.c [new file with mode: 0644]
drivers/net/plip/plip.c
drivers/net/rionet.c
drivers/net/sb1000.c
drivers/net/slip/slip.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/asix_devices.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/catc.c
drivers/net/usb/cdc-phonet.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/kaweth.c
drivers/net/usb/lan78xx.c
drivers/net/usb/pegasus.c
drivers/net/usb/r8152.c
drivers/net/usb/rtl8150.c
drivers/net/usb/sierra_net.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/usbnet.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wan/c101.c
drivers/net/wan/cosa.c
drivers/net/wan/dscc4.c
drivers/net/wan/farsync.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wan/hdlc.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/hostess_sv11.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wan/lmc/lmc_main.c
drivers/net/wan/n2.c
drivers/net/wan/pc300too.c
drivers/net/wan/pci200syn.c
drivers/net/wan/sbni.c
drivers/net/wan/sealevel.c
drivers/net/wan/wanxl.c
drivers/net/wan/x25_asy.c
drivers/net/wimax/i2400m/netdev.c
drivers/net/wireless/Kconfig
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/wil6210/netdev.c
drivers/net/wireless/atmel/atmel.c
drivers/net/wireless/broadcom/b43/main.c
drivers/net/wireless/broadcom/b43legacy/main.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/cisco/airo.c
drivers/net/wireless/intel/ipw2x00/ipw2100.c
drivers/net/wireless/intel/ipw2x00/ipw2200.c
drivers/net/wireless/intel/ipw2x00/libipw.h
drivers/net/wireless/intel/ipw2x00/libipw_module.c
drivers/net/wireless/intersil/hostap/hostap_main.c
drivers/net/wireless/intersil/orinoco/main.c
drivers/net/wireless/intersil/prism54/islpci_dev.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/marvell/libertas/main.c
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/wl3501_cs.c
drivers/net/wireless/zydas/zd1201.c
drivers/net/xen-netback/interface.c
drivers/net/xen-netfront.c
drivers/s390/net/ctcm_main.c
drivers/s390/net/lcs.c
drivers/s390/net/netiucv.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/scsi/pmcraid.c
drivers/staging/octeon/ethernet.c
drivers/staging/rtl8188eu/os_dep/mon.c
drivers/staging/rtl8192e/rtl8192e/rtl_core.c
drivers/staging/rtl8192u/r8192U_core.c
drivers/staging/slicoss/slicoss.c
drivers/staging/unisys/include/iochannel.h
drivers/staging/unisys/visornic/visornic_main.c
drivers/staging/wlan-ng/p80211netdev.c
drivers/target/target_core_user.c
drivers/thermal/thermal_core.c
drivers/tty/n_gsm.c
drivers/tty/synclink.c
drivers/tty/synclink_gt.c
drivers/tty/synclinkmp.c
drivers/usb/gadget/function/f_phonet.c
drivers/usb/gadget/function/u_ether.c
fs/dlm/netlink.c
fs/quota/netlink.c
include/dt-bindings/net/mscc-phy-vsc8531.h [deleted file]
include/linux/bpf.h
include/linux/bpf_verifier.h
include/linux/brcmphy.h
include/linux/drbd_genl.h
include/linux/fddidevice.h
include/linux/genl_magic_func.h
include/linux/hdlc.h
include/linux/hippidevice.h
include/linux/ieee80211.h
include/linux/netdevice.h
include/linux/phy.h
include/linux/phy_led_triggers.h [new file with mode: 0644]
include/linux/qed/qed_eth_if.h
include/linux/skbuff.h
include/linux/smc91x.h
include/net/cfg80211.h
include/net/genetlink.h
include/net/ieee80211_radiotap.h
include/net/inet_connection_sock.h
include/net/lwtunnel.h
include/net/mac80211.h
include/net/netlink.h
include/net/raw.h
include/net/rawv6.h
include/net/sctp/structs.h
include/net/sock.h
include/net/tc_act/tc_mirred.h
include/net/tc_act/tc_skbedit.h
include/net/udp.h
include/uapi/linux/bpf.h
include/uapi/linux/genetlink.h
include/uapi/linux/if_ether.h
include/uapi/linux/inet_diag.h
include/uapi/linux/nl80211.h
include/uapi/linux/tc_act/tc_skbedit.h
kernel/bpf/core.c
kernel/bpf/helpers.c
kernel/bpf/verifier.c
kernel/taskstats.c
kernel/trace/bpf_trace.c
net/802/fddi.c
net/802/hippi.c
net/8021q/vlan.c
net/8021q/vlan_dev.c
net/atm/br2684.c
net/atm/lec.c
net/batman-adv/Kconfig
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bat_v.c
net/batman-adv/bat_v_ogm.c
net/batman-adv/debugfs.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/fragmentation.c
net/batman-adv/fragmentation.h
net/batman-adv/gateway_client.c
net/batman-adv/hash.h
net/batman-adv/icmp_socket.c
net/batman-adv/log.c
net/batman-adv/log.h
net/batman-adv/main.c
net/batman-adv/main.h
net/batman-adv/netlink.c
net/batman-adv/network-coding.c
net/batman-adv/originator.c
net/batman-adv/packet.h
net/batman-adv/send.c
net/batman-adv/soft-interface.c
net/batman-adv/sysfs.c
net/batman-adv/translation-table.c
net/batman-adv/types.h
net/bluetooth/bnep/netdev.c
net/bridge/br_device.c
net/bridge/br_fdb.c
net/caif/cfcnfg.c
net/core/datagram.c
net/core/dev.c
net/core/devlink.c
net/core/drop_monitor.c
net/core/filter.c
net/core/flow_dissector.c
net/core/lwtunnel.c
net/core/net-sysfs.c
net/core/net_namespace.c
net/core/sock.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dsa/slave.c
net/ethernet/eth.c
net/hsr/hsr_device.c
net/hsr/hsr_netlink.c
net/ieee802154/netlink.c
net/ieee802154/nl802154.c
net/ipv4/Kconfig
net/ipv4/Makefile
net/ipv4/fou.c
net/ipv4/inet_diag.c
net/ipv4/ip_tunnel.c
net/ipv4/raw.c
net/ipv4/raw_diag.c [new file with mode: 0644]
net/ipv4/tcp_bbr.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/udp.c
net/ipv6/ila/ila_lwt.c
net/ipv6/ila/ila_xlat.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/raw.c
net/ipv6/sit.c
net/ipv6/udp.c
net/irda/irlan/irlan_eth.c
net/irda/irnetlink.c
net/iucv/af_iucv.c
net/l2tp/l2tp_eth.c
net/l2tp/l2tp_netlink.c
net/mac80211/Makefile
net/mac80211/aes_cmac.c
net/mac80211/aes_cmac.h
net/mac80211/agg-rx.c
net/mac80211/cfg.c
net/mac80211/debugfs.c
net/mac80211/debugfs_netdev.c
net/mac80211/debugfs_sta.c
net/mac80211/fils_aead.c [new file with mode: 0644]
net/mac80211/fils_aead.h [new file with mode: 0644]
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wme.c
net/mac80211/wpa.c
net/mpls/mpls_iptunnel.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netlabel/netlabel_calipso.c
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_unlabeled.c
net/netlink/genetlink.c
net/nfc/netlink.c
net/openvswitch/actions.c
net/openvswitch/datapath.c
net/openvswitch/vport-internal_dev.c
net/openvswitch/vport-netdev.c
net/openvswitch/vport.c
net/openvswitch/vport.h
net/phonet/pep-gprs.c
net/rds/connection.c
net/rds/rds.h
net/rds/threads.c
net/sched/act_bpf.c
net/sched/act_mirred.c
net/sched/act_skbedit.c
net/sched/cls_bpf.c
net/sched/em_meta.c
net/sched/sch_htb.c
net/sched/sch_teql.c
net/sctp/chunk.c
net/sctp/output.c
net/sctp/outqueue.c
net/sunrpc/svcsock.c
net/sunrpc/xprtsock.c
net/switchdev/switchdev.c
net/tipc/netlink.c
net/tipc/netlink_compat.c
net/wimax/stack.c
net/wireless/core.c
net/wireless/core.h
net/wireless/mesh.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/rdev-ops.h
net/wireless/sme.c
net/wireless/trace.h
net/wireless/util.c
net/xfrm/xfrm_state.c
samples/bpf/Makefile
samples/bpf/test_maps.c [deleted file]
tools/include/linux/filter.h
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/.gitignore [new file with mode: 0644]
tools/testing/selftests/bpf/Makefile [new file with mode: 0644]
tools/testing/selftests/bpf/bpf_sys.h [new file with mode: 0644]
tools/testing/selftests/bpf/config [new file with mode: 0644]
tools/testing/selftests/bpf/test_kmod.sh [new file with mode: 0755]
tools/testing/selftests/bpf/test_maps.c [new file with mode: 0644]
tools/testing/selftests/bpf/test_verifier.c [moved from samples/bpf/test_verifier.c with 78% similarity]
tools/testing/selftests/net/.gitignore
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/reuseport_bpf_numa.c [new file with mode: 0644]

index 7629189398aabb80f2b2794b260267a4f6832ed4..32025eb4b31bc80020533b88d038378b30ae342f 100644 (file)
@@ -20,16 +20,35 @@ Required properties:
 Optional properties:
 
 - reset-gpios          : Should be a gpio specifier for a reset line
-
+- interrupt-parent     : Parent interrupt controller
+- interrupts           : Interrupt from the switch
+- interrupt-controller : Indicates the switch is itself an interrupt
+                         controller. This is used for the PHY interrupts.
+#interrupt-cells = <2> : Controller uses two cells, number and flag
+- mdio                 : container of PHY and devices on the switches MDIO
+                         bus
 Example:
 
        mdio {
                #address-cells = <1>;
                #size-cells = <0>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
 
                switch0: switch@0 {
                        compatible = "marvell,mv88e6085";
                        reg = <0>;
                       reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
                };
+               mdio {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       switch1phy0: switch1phy0@0 {
+                               reg = <0>;
+                               interrupt-parent = <&switch0>;
+                               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
        };
index 99c7eb0a00c8f3d07542284e1df4af094d158aee..bdefefc665949225d77e4c5c22cde5dd6b678069 100644 (file)
@@ -6,22 +6,27 @@ Required properties:
                  Documentation/devicetree/bindings/net/phy.txt
 
 Optional properties:
-- vsc8531,vddmac       : The vddmac in mV.
+- vsc8531,vddmac       : The vddmac in mV. Allowed values is listed
+                         in the first row of Table 1 (below).
+                         This property is only used in combination
+                         with the 'edge-slowdown' property.
+                         Default value is 3300.
 - vsc8531,edge-slowdown        : % the edge should be slowed down relative to
-                         the fastest possible edge time. Native sign
-                         need not enter.
+                         the fastest possible edge time.
                          Edge rate sets the drive strength of the MAC
-                         interface output signals.  Changing the drive
-                         strength will affect the edge rate of the output
-                         signal.  The goal of this setting is to help
-                         reduce electrical emission (EMI) by being able
-                         to reprogram drive strength and in effect slow
-                         down the edge rate if desired.  Table 1 shows the
-                         impact to the edge rate per VDDMAC supply for each
-                         drive strength setting.
-                         Ref: Table:1 - Edge rate change below.
-
-Note: see dt-bindings/net/mscc-phy-vsc8531.h for applicable values
+                         interface output signals.  Changing the
+                         drive strength will affect the edge rate of
+                         the output signal.  The goal of this setting
+                         is to help reduce electrical emission (EMI)
+                         by being able to reprogram drive strength
+                         and in effect slow down the edge rate if
+                         desired.
+                         To adjust the edge-slowdown, the 'vddmac'
+                         must be specified. Table 1 lists the
+                         supported edge-slowdown values for a given
+                         'vddmac'.
+                         Default value is 0%.
+                         Ref: Table:1 - Edge rate change (below).
 
 Table: 1 - Edge rate change
 ----------------------------------------------------------------|
@@ -29,23 +34,23 @@ Table: 1 - Edge rate change
 |                                                              |
 | 3300 mV      2500 mV         1800 mV         1500 mV         |
 |---------------------------------------------------------------|
-| Default      Deafult         Default         Default         |
+| 0%           0%              0%              0%              |
 | (Fastest)                    (recommended)   (recommended)   |
 |---------------------------------------------------------------|
-| -2%          -3%             -5%             -6%             |
+| 2%           3%              5%              6%              |
 |---------------------------------------------------------------|
-| -4%          -6%             -9%             -14%            |
+| 4%           6%              9%              14%             |
 |---------------------------------------------------------------|
-| -7%          -10%            -16%            -21%            |
+| 7%           10%             16%             21%             |
 |(recommended) (recommended)                                   |
 |---------------------------------------------------------------|
-| -10%         -14%            -23%            -29%            |
+| 10%          14%             23%             29%             |
 |---------------------------------------------------------------|
-| -17%         -23%            -35%            -42%            |
+| 17%          23%             35%             42%             |
 |---------------------------------------------------------------|
-| -29%         -37%            -52%            -58%            |
+| 29%          37%             52%             58%             |
 |---------------------------------------------------------------|
-| -53%         -63%            -76%            -77%            |
+| 53%          63%             76%             77%             |
 | (slowest)                                                    |
 |---------------------------------------------------------------|
 
@@ -54,5 +59,5 @@ Example:
         vsc8531_0: ethernet-phy@0 {
                 compatible = "ethernet-phy-id0007.0570";
                 vsc8531,vddmac         = <3300>;
-                vsc8531,edge-slowdown  = <21>;
+                vsc8531,edge-slowdown  = <7>;
         };
index e77e167593db2aa585ca1afbb48e4fbac0287384..309e37eb7c7cce4f548d954db0ad665be998d76f 100644 (file)
@@ -13,3 +13,5 @@ Optional properties:
   16-bit access only.
 - power-gpios: GPIO to control the PWRDWN pin
 - reset-gpios: GPIO to control the RESET pin
+- pxa-u16-align4 : Boolean, put in place the workaround the force all
+                  u16 writes to be 32 bits aligned
index 5d21141a68b547104d5f152da0214dc847f4a3e9..85bf945b898f0d156702f16d76be315c9108e1aa 100644 (file)
@@ -9,6 +9,18 @@ Required properties:
        - ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
                for applicable values
 
+Optional property:
+       - ti,min-output-impedance - MAC Interface Impedance control to set
+                                   the programmable output impedance to
+                                   minimum value (35 ohms).
+       - ti,max-output-impedance - MAC Interface Impedance control to set
+                                   the programmable output impedance to
+                                   maximum value (70 ohms).
+
+Note: ti,min-output-impedance and ti,max-output-impedance are mutually
+      exclusive. When both properties are present ti,max-output-impedance
+      takes precedence.
+
 Default child nodes are standard Ethernet PHY device
 nodes as described in Documentation/devicetree/bindings/net/phy.txt
 
index 8a8d3d96f6c6b0fb62e2a4651a6528c6ed321113..ccf94677b240973f35c4cd9e948c96b92163037e 100644 (file)
@@ -32,7 +32,7 @@ compatible interfaces. Once found, it will create  subfolders  in
 the /sys directories of each supported interface, e.g.
 
 # ls /sys/class/net/eth0/batman_adv/
-# iface_status  mesh_iface
+# elp_interval  iface_status  mesh_iface  throughput_override
 
 If an interface does not have the "batman_adv" subfolder it prob-
 ably is not supported. Not supported  interfaces  are:  loopback,
@@ -71,17 +71,19 @@ All  mesh  wide  settings  can be found in batman's own interface
 folder:
 
 # ls /sys/class/net/bat0/mesh/
-#aggregated_ogms        distributed_arp_table  gw_sel_class    orig_interval
-#ap_isolation           fragmentation          hop_penalty     routing_algo
-#bonding                gw_bandwidth           isolation_mark  vlan0
-#bridge_loop_avoidance  gw_mode                log_level
+# aggregated_ogms        fragmentation  isolation_mark  routing_algo
+# ap_isolation           gw_bandwidth   log_level       vlan0
+# bonding                gw_mode        multicast_mode
+# bridge_loop_avoidance  gw_sel_class   network_coding
+# distributed_arp_table  hop_penalty    orig_interval
 
 There is a special folder for debugging information:
 
 # ls /sys/kernel/debug/batman_adv/bat0/
-# bla_backbone_table  log                 transtable_global
-# bla_claim_table     originators         transtable_local
-# gateways            socket
+# bla_backbone_table  log          neighbors          transtable_local
+# bla_claim_table     mcast_flags  originators
+# dat_cache           nc           socket
+# gateways            nc_nodes     transtable_global
 
 Some of the files contain all sort of status information  regard-
 ing  the  mesh  network.  For  example, you can view the table of
@@ -159,13 +161,16 @@ file in debugfs
 The additional debug output is by default disabled. It can be en-
 abled  during run time. Following log_levels are defined:
 
-0 - All  debug  output  disabled
-1 - Enable messages related to routing / flooding / broadcasting
-2 - Enable messages related to route added / changed / deleted
-4 - Enable messages related to translation table operations
-8 - Enable messages related to bridge loop avoidance
-16 - Enable messaged related to DAT, ARP snooping and parsing
-31 - Enable all messages
+  0 - All  debug  output  disabled
+  1 - Enable messages related to routing / flooding / broadcasting
+  2 - Enable messages related to route added / changed / deleted
+  4 - Enable messages related to translation table operations
+  8 - Enable messages related to bridge loop avoidance
+ 16 - Enable messages related to DAT, ARP snooping and parsing
+ 32 - Enable messages related to network coding
+ 64 - Enable messages related to multicast
+128 - Enable messages related to throughput meter
+255 - Enable all messages
 
 The debug output can be changed at runtime  using  the  file
 /sys/class/net/bat0/mesh/log_level. e.g.
index 24ac91d56698d626fb266556c5b0c3b9fd212fa9..3566a725d19c7dd704b929206f2a0aad81a10dfa 100644 (file)
@@ -60,7 +60,7 @@ modprobe mac80211_hwsim
 hostapd hostapd.conf
 
 # Run wpa_supplicant (station) for wlan1
-wpa_supplicant -Dwext -iwlan1 -c wpa_supplicant.conf
+wpa_supplicant -Dnl80211 -iwlan1 -c wpa_supplicant.conf
 
 
 More test cases are available in hostap.git:
index 4012c2f98617115901fbf906866bad1adec069ec..e5c17a951b7db1962bed7ac160572d80a765911f 100644 (file)
@@ -2530,6 +2530,8 @@ L:        netdev@vger.kernel.org
 L:     linux-kernel@vger.kernel.org
 S:     Supported
 F:     kernel/bpf/
+F:     tools/testing/selftests/bpf/
+F:     lib/test_bpf.c
 
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:     Michael Chan <michael.chan@broadcom.com>
@@ -8443,7 +8445,6 @@ F:        include/uapi/linux/net_namespace.h
 F:     tools/net/
 F:     tools/testing/selftests/net/
 F:     lib/random32.c
-F:     lib/test_bpf.c
 
 NETWORKING [IPv4/IPv6]
 M:     "David S. Miller" <davem@davemloft.net>
index 064b322a7a042e5b845b58aed03f37dabee115fd..3b23b32e1b307ba7e9eec0c9f98336b5624ed056 100644 (file)
 &davinci_mdio {
        dp83867_0: ethernet-phy@2 {
                reg = <2>;
-               ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
-               ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+               ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+               ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
                ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+               ti,min-output-impedance;
        };
 
        dp83867_1: ethernet-phy@3 {
                reg = <3>;
-               ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
-               ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+               ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+               ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
                ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+               ti,min-output-imepdance;
        };
 };
index 5c1fcab4a6f78d9f340f67b1805427933cea5ad6..1552db00cc592e0a17465c702b74428310b343b0 100644 (file)
 
                        switch0: switch0@0 {
                                compatible = "marvell,mv88e6085";
+                               pinctrl-0 = <&pinctrl_gpio_switch0>;
+                               pinctrl-names = "default";
                                #address-cells = <1>;
                                #size-cells = <0>;
                                reg = <0>;
                                dsa,member = <0 0>;
+                               interrupt-parent = <&gpio0>;
+                               interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
 
                                ports {
                                        #address-cells = <1>;
                                        port@0 {
                                                reg = <0>;
                                                label = "lan0";
+                                               phy-handle = <&switch0phy0>;
                                        };
 
                                        port@1 {
                                                reg = <1>;
                                                label = "lan1";
+                                               phy-handle = <&switch0phy1>;
                                        };
 
                                        port@2 {
                                                reg = <2>;
                                                label = "lan2";
+                                               phy-handle = <&switch0phy2>;
                                        };
 
                                        switch0port5: port@5 {
                                                };
                                        };
                                };
+                               mdio {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       switch0phy0: switch0phy0@0 {
+                                               reg = <0>;
+                                               interrupt-parent = <&switch0>;
+                                               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+                                       switch0phy1: switch1phy0@1 {
+                                               reg = <1>;
+                                               interrupt-parent = <&switch0>;
+                                               interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;                                   };
+                                       switch0phy2: switch1phy0@2 {
+                                               reg = <2>;
+                                               interrupt-parent = <&switch0>;
+                                               interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+                               };
                        };
                };
 
 
                        switch1: switch1@0 {
                                compatible = "marvell,mv88e6085";
+                               pinctrl-0 = <&pinctrl_gpio_switch1>;
+                               pinctrl-names = "default";
                                #address-cells = <1>;
                                #size-cells = <0>;
                                reg = <0>;
                                dsa,member = <0 1>;
+                               interrupt-parent = <&gpio0>;
+                               interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
 
                                ports {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                        switch1phy0: switch1phy0@0 {
                                                reg = <0>;
+                                               interrupt-parent = <&switch1>;
+                                               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
                                        };
                                        switch1phy1: switch1phy0@1 {
                                                reg = <1>;
+                                               interrupt-parent = <&switch1>;
+                                               interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
                                        };
                                        switch1phy2: switch1phy0@2 {
                                                reg = <2>;
+                                               interrupt-parent = <&switch1>;
+                                               interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
                                        };
                                };
                        };
                >;
        };
 
+       pinctrl_gpio_switch0: pinctrl-gpio-switch0 {
+               fsl,pins = <
+                       VF610_PAD_PTB5__GPIO_27         0x219d
+               >;
+       };
+
+       pinctrl_gpio_switch1: pinctrl-gpio-switch1 {
+               fsl,pins = <
+                       VF610_PAD_PTB4__GPIO_26         0x219d
+               >;
+       };
+
        pinctrl_i2c_mux_reset: pinctrl-i2c-mux-reset {
                fsl,pins = <
                         VF610_PAD_PTE14__GPIO_119      0x31c2
index 66070acaa888cc5778f5651592691c34a0adfca5..d1db32b1a2c613cbaf326f8300a24bd439bc91f2 100644 (file)
@@ -85,6 +85,7 @@ static struct resource smc91x_resources[] = {
 static struct smc91x_platdata smc91x_platdata = {
        .flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
                 SMC91X_USE_DMA | SMC91X_NOWAIT,
+       .pxa_u16_align4 = true,
 };
 
 static struct platform_device smc91x_device = {
index 40964069a17caf10889f4d4505740d1666441278..a2d851a3a546c592fa7191365914b6b08a33de56 100644 (file)
@@ -140,6 +140,7 @@ static struct resource smc91x_resources[] = {
 static struct smc91x_platdata mainstone_smc91x_info = {
        .flags  = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
                  SMC91X_NOWAIT | SMC91X_USE_DMA,
+       .pxa_u16_align4 = true,
 };
 
 static struct platform_device smc91x_device = {
index 702f4f14b708ccb4ca80da7e7ef3da9595b2a784..7b6610e9dae46cc9e981b819f5326a909bf53e68 100644 (file)
@@ -673,6 +673,7 @@ static struct resource smc91x_resources[] = {
 static struct smc91x_platdata stargate2_smc91x_info = {
        .flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT
        | SMC91X_NOWAIT | SMC91X_USE_DMA,
+       .pxa_u16_align4 = true,
 };
 
 static struct platform_device smc91x_device = {
index dab2cb0c1f1c933e24a3f5e11d1586a26cb14771..6be08113a96d6b4227afb82d339b2f7ed48ea68d 100644 (file)
@@ -257,6 +257,7 @@ CONFIG_GPIO_DWAPB=y
 CONFIG_GPIO_PL061=y
 CONFIG_GPIO_RCAR=y
 CONFIG_GPIO_XGENE=y
+CONFIG_GPIO_XGENE_SB=y
 CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_MAX77620=y
index a0985fd088d1c8a0381dfe75420c1e2d25b8d88c..fc4be028c4189ee9ec93265b844633411a945eb4 100644 (file)
@@ -184,7 +184,6 @@ static const struct net_device_ops nfeth_netdev_ops = {
        .ndo_start_xmit         = nfeth_xmit,
        .ndo_tx_timeout         = nfeth_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
index dd456e9c513fa9651190f09b02edfee98db4359a..dd4e2946438e449220668f837b129b9a57a2bd60 100644 (file)
@@ -30,7 +30,7 @@
 
 #if SMC_CAN_USE_16BIT
 #define SMC_inw(a, r)          inw((unsigned long) ((a) + (r)))
-#define SMC_outw(v, a, r)      outw(v, (unsigned long) ((a) + (r)))
+#define SMC_outw(lp, v, a, r)  outw(v, (unsigned long) ((a) + (r)))
 #define SMC_insw(a, r, p, l)   insw((unsigned long) ((a) + (r)), (p), (l))
 #define SMC_outsw(a, r, p, l)  outsw((unsigned long) ((a) + (r)), (p), (l))
 #endif
index 2cd5b6874c7bb65fa75e6f6c686fc72a6d8aff0c..1669240c7a25f443cee1a32c0a07f90595858605 100644 (file)
@@ -256,13 +256,6 @@ static void uml_net_tx_timeout(struct net_device *dev)
        netif_wake_queue(dev);
 }
 
-static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
-{
-       dev->mtu = new_mtu;
-
-       return 0;
-}
-
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void uml_net_poll_controller(struct net_device *dev)
 {
@@ -374,7 +367,6 @@ static const struct net_device_ops uml_netdev_ops = {
        .ndo_set_rx_mode        = uml_net_set_multicast_list,
        .ndo_tx_timeout         = uml_net_tx_timeout,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = uml_net_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = uml_net_poll_controller,
index e24ea4e796e4b920cdc437f3f76a69eb391b85c7..7fceb3b4691b0f5d4b42043d42ec422a60319051 100644 (file)
@@ -82,8 +82,8 @@ static const struct genl_multicast_group acpi_event_mcgrps[] = {
        { .name = ACPI_GENL_MCAST_GROUP_NAME, },
 };
 
-static struct genl_family acpi_event_genl_family = {
-       .id = GENL_ID_GENERATE,
+static struct genl_family acpi_event_genl_family __ro_after_init = {
+       .module = THIS_MODULE,
        .name = ACPI_GENL_FAMILY_NAME,
        .version = ACPI_GENL_VERSION,
        .maxattr = ACPI_GENL_ATTR_MAX,
@@ -144,7 +144,7 @@ int acpi_bus_generate_netlink_event(const char *device_class,
 
 EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
 
-static int acpi_event_genetlink_init(void)
+static int __init acpi_event_genetlink_init(void)
 {
        return genl_register_family(&acpi_event_genl_family);
 }
index d28922df01d754d88e91ca8d34054ce4375c0781..a7dd5f4f2c5a66a536e0cfd9e7a83a1a17255bfa 100644 (file)
@@ -4248,7 +4248,6 @@ static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size)
 static const struct net_device_ops hdlcdev_ops = {
        .ndo_open       = hdlcdev_open,
        .ndo_stop       = hdlcdev_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = hdlcdev_ioctl,
        .ndo_tx_timeout = hdlcdev_tx_timeout,
index 309311b1faae18752a9bf24b0d350933aad4627c..363fc5ec1a4eb20ee70e17ac611dd1b917a0624c 100644 (file)
@@ -1349,15 +1349,6 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
        return NETDEV_TX_OK;
 }
 
-static int fwnet_change_mtu(struct net_device *net, int new_mtu)
-{
-       if (new_mtu < 68)
-               return -EINVAL;
-
-       net->mtu = new_mtu;
-       return 0;
-}
-
 static const struct ethtool_ops fwnet_ethtool_ops = {
        .get_link       = ethtool_op_get_link,
 };
@@ -1366,7 +1357,6 @@ static const struct net_device_ops fwnet_netdev_ops = {
        .ndo_open       = fwnet_open,
        .ndo_stop       = fwnet_stop,
        .ndo_start_xmit = fwnet_tx,
-       .ndo_change_mtu = fwnet_change_mtu,
 };
 
 static void fwnet_init_dev(struct net_device *net)
@@ -1435,7 +1425,6 @@ static int fwnet_probe(struct fw_unit *unit,
        struct net_device *net;
        bool allocated_netdev = false;
        struct fwnet_device *dev;
-       unsigned max_mtu;
        int ret;
        union fwnet_hwaddr *ha;
 
@@ -1474,13 +1463,9 @@ static int fwnet_probe(struct fw_unit *unit,
                goto out;
        dev->local_fifo = dev->handler.offset;
 
-       /*
-        * Use the RFC 2734 default 1500 octets or the maximum payload
-        * as initial MTU
-        */
-       max_mtu = (1 << (card->max_receive + 1))
-                 - sizeof(struct rfc2734_header) - IEEE1394_GASP_HDR_SIZE;
-       net->mtu = min(1500U, max_mtu);
+       net->mtu = 1500U;
+       net->min_mtu = ETH_MIN_MTU;
+       net->max_mtu = 0xfff;
 
        /* Set our hardware address while we're at it */
        ha = (union fwnet_hwaddr *)net->dev_addr;
index 6031cd1465565b35d8832d445ad15fc60b4c37ee..7ef819680acda13077f773c5fe65f12f7349cbb4 100644 (file)
@@ -960,15 +960,6 @@ static int ssip_pn_stop(struct net_device *dev)
        return 0;
 }
 
-static int ssip_pn_set_mtu(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu > SSIP_MAX_MTU || new_mtu < PHONET_MIN_MTU)
-               return -EINVAL;
-       dev->mtu = new_mtu;
-
-       return 0;
-}
-
 static void ssip_xmit_work(struct work_struct *work)
 {
        struct ssi_protocol *ssi =
@@ -1060,7 +1051,6 @@ static const struct net_device_ops ssip_pn_ops = {
        .ndo_open       = ssip_pn_open,
        .ndo_stop       = ssip_pn_stop,
        .ndo_start_xmit = ssip_pn_xmit,
-       .ndo_change_mtu = ssip_pn_set_mtu,
 };
 
 static void ssip_pn_setup(struct net_device *dev)
@@ -1136,6 +1126,10 @@ static int ssi_protocol_probe(struct device *dev)
                goto out1;
        }
 
+       /* MTU range: 6 - 65535 */
+       ssi->netdev->min_mtu = PHONET_MIN_MTU;
+       ssi->netdev->max_mtu = SSIP_MAX_MTU;
+
        SET_NETDEV_DEV(ssi->netdev, dev);
        netif_carrier_off(ssi->netdev);
        err = register_netdev(ssi->netdev);
index 19d499dcab764bc74307b3bd3617cd7657874792..0c0bea091de86c70b84f454ce0f50da90c7f4bd5 100644 (file)
@@ -127,14 +127,7 @@ void ib_cache_release_one(struct ib_device *device);
 static inline bool rdma_is_upper_dev_rcu(struct net_device *dev,
                                         struct net_device *upper)
 {
-       struct net_device *_upper = NULL;
-       struct list_head *iter;
-
-       netdev_for_each_all_upper_dev_rcu(dev, _upper, iter)
-               if (_upper == upper)
-                       break;
-
-       return _upper == upper;
+       return netdev_has_upper_dev_all_rcu(dev, upper);
 }
 
 int addr_init(void);
index 06556c34606deb38e8906d08327a7d024f38079e..3a64a0881882eb98a033d3a82296ad9b36ac600d 100644 (file)
@@ -437,6 +437,28 @@ static void callback_for_addr_gid_device_scan(struct ib_device *device,
                          &parsed->gid_attr);
 }
 
+struct upper_list {
+       struct list_head list;
+       struct net_device *upper;
+};
+
+static int netdev_upper_walk(struct net_device *upper, void *data)
+{
+       struct upper_list *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+       struct list_head *upper_list = data;
+
+       if (!entry) {
+               pr_info("roce_gid_mgmt: couldn't allocate entry to delete ndev\n");
+               return 0;
+       }
+
+       list_add_tail(&entry->list, upper_list);
+       dev_hold(upper);
+       entry->upper = upper;
+
+       return 0;
+}
+
 static void handle_netdev_upper(struct ib_device *ib_dev, u8 port,
                                void *cookie,
                                void (*handle_netdev)(struct ib_device *ib_dev,
@@ -444,30 +466,12 @@ static void handle_netdev_upper(struct ib_device *ib_dev, u8 port,
                                                      struct net_device *ndev))
 {
        struct net_device *ndev = (struct net_device *)cookie;
-       struct upper_list {
-               struct list_head list;
-               struct net_device *upper;
-       };
-       struct net_device *upper;
-       struct list_head *iter;
        struct upper_list *upper_iter;
        struct upper_list *upper_temp;
        LIST_HEAD(upper_list);
 
        rcu_read_lock();
-       netdev_for_each_all_upper_dev_rcu(ndev, upper, iter) {
-               struct upper_list *entry = kmalloc(sizeof(*entry),
-                                                  GFP_ATOMIC);
-
-               if (!entry) {
-                       pr_info("roce_gid_mgmt: couldn't allocate entry to delete ndev\n");
-                       continue;
-               }
-
-               list_add_tail(&entry->list, &upper_list);
-               dev_hold(upper);
-               entry->upper = upper;
-       }
+       netdev_walk_all_upper_dev_rcu(ndev, netdev_upper_walk, &upper_list);
        rcu_read_unlock();
 
        handle_netdev(ib_dev, port, ndev);
index 35cbb17bec12d93771917bfd92aa537a031443a7..2baa45a8e4019615e55ae6595704e8ffee90d8a5 100644 (file)
@@ -65,7 +65,6 @@ MODULE_DESCRIPTION("NetEffect RNIC Low-level iWARP Driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 
-int max_mtu = 9000;
 int interrupt_mod_interval = 0;
 
 /* Interoperability */
index e7430c9254d3812b0ec8d08c110337058bd270c9..85acd0843b503807e92eafb26bce1cf60abc55a7 100644 (file)
@@ -83,6 +83,8 @@
 #define NES_FIRST_QPN           64
 #define NES_SW_CONTEXT_ALIGN    1024
 
+#define NES_MAX_MTU            9000
+
 #define NES_NIC_MAX_NICS        16
 #define NES_MAX_ARP_TABLE_SIZE  4096
 
@@ -169,8 +171,6 @@ do { \
 #include "nes_cm.h"
 #include "nes_mgt.h"
 
-extern int max_mtu;
-#define max_frame_len (max_mtu+ETH_HLEN)
 extern int interrupt_mod_interval;
 extern int nes_if_count;
 extern int mpa_version;
index 2b27d1351cf7df44c6803fe79315bf277b071826..7f8597d6738bb93d31f8b22bedb87bf20decac60 100644 (file)
@@ -981,20 +981,16 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct nes_vnic *nesvnic = netdev_priv(netdev);
        struct nes_device *nesdev = nesvnic->nesdev;
-       int ret = 0;
        u8 jumbomode = 0;
        u32 nic_active;
        u32 nic_active_bit;
        u32 uc_all_active;
        u32 mc_all_active;
 
-       if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
-               return -EINVAL;
-
        netdev->mtu = new_mtu;
        nesvnic->max_frame_size = new_mtu + VLAN_ETH_HLEN;
 
-       if (netdev->mtu > 1500) {
+       if (netdev->mtu > ETH_DATA_LEN) {
                jumbomode=1;
        }
        nes_nic_init_timer_defaults(nesdev, jumbomode);
@@ -1020,7 +1016,7 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
                nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
        }
 
-       return ret;
+       return 0;
 }
 
 
@@ -1658,7 +1654,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
 
        netdev->watchdog_timeo = NES_TX_TIMEOUT;
        netdev->irq = nesdev->pcidev->irq;
-       netdev->mtu = ETH_DATA_LEN;
+       netdev->max_mtu = NES_MAX_MTU;
        netdev->hard_header_len = ETH_HLEN;
        netdev->addr_len = ETH_ALEN;
        netdev->type = ARPHRD_ETHER;
index b58d9dca5c934eb69c9f62b623216d7856999105..c50794fb92db4cf5454507b5c35ecdc4ccf8511f 100644 (file)
@@ -292,6 +292,25 @@ static struct net_device *ipoib_get_master_net_dev(struct net_device *dev)
        return dev;
 }
 
+struct ipoib_walk_data {
+       const struct sockaddr *addr;
+       struct net_device *result;
+};
+
+static int ipoib_upper_walk(struct net_device *upper, void *_data)
+{
+       struct ipoib_walk_data *data = _data;
+       int ret = 0;
+
+       if (ipoib_is_dev_match_addr_rcu(data->addr, upper)) {
+               dev_hold(upper);
+               data->result = upper;
+               ret = 1;
+       }
+
+       return ret;
+}
+
 /**
  * Find a net_device matching the given address, which is an upper device of
  * the given net_device.
@@ -304,27 +323,21 @@ static struct net_device *ipoib_get_master_net_dev(struct net_device *dev)
 static struct net_device *ipoib_get_net_dev_match_addr(
                const struct sockaddr *addr, struct net_device *dev)
 {
-       struct net_device *upper,
-                         *result = NULL;
-       struct list_head *iter;
+       struct ipoib_walk_data data = {
+               .addr = addr,
+       };
 
        rcu_read_lock();
        if (ipoib_is_dev_match_addr_rcu(addr, dev)) {
                dev_hold(dev);
-               result = dev;
+               data.result = dev;
                goto out;
        }
 
-       netdev_for_each_all_upper_dev_rcu(dev, upper, iter) {
-               if (ipoib_is_dev_match_addr_rcu(addr, upper)) {
-                       dev_hold(upper);
-                       result = upper;
-                       break;
-               }
-       }
+       netdev_walk_all_upper_dev_rcu(dev, ipoib_upper_walk, &data);
 out:
        rcu_read_unlock();
-       return result;
+       return data.result;
 }
 
 /* returns the number of IPoIB netdevs on top a given ipoib device matching a
@@ -2016,6 +2029,7 @@ static struct net_device *ipoib_add_port(const char *format,
        /* MTU will be reset when mcast join happens */
        priv->dev->mtu  = IPOIB_UD_MTU(priv->max_ib_mtu);
        priv->mcast_mtu  = priv->admin_mtu = priv->dev->mtu;
+       priv->dev->max_mtu = IPOIB_CM_MTU;
 
        priv->dev->neigh_priv_len = sizeof(struct ipoib_neigh);
 
index 5609deee7cd3f7891076dd474493bcfa91c7ad87..b93a4e9a8d3449e4428e558a8c31c6d0014d8a16 100644 (file)
@@ -232,7 +232,6 @@ static const struct net_device_ops hysdn_netdev_ops = {
        .ndo_open               = net_open,
        .ndo_stop               = net_close,
        .ndo_start_xmit         = net_send_packet,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 9914f69a4a02b82bbd3717746d0080aa1454d370..0da622f5fe69d33609464b5841ee1e08fd66b1fe 100644 (file)
@@ -1198,7 +1198,6 @@ static const struct net_device_ops dvb_netdev_ops = {
        .ndo_start_xmit         = dvb_net_tx,
        .ndo_set_rx_mode        = dvb_net_set_multicast_list,
        .ndo_set_mac_address    = dvb_net_set_mac,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
@@ -1209,6 +1208,7 @@ static void dvb_net_setup(struct net_device *dev)
        dev->header_ops         = &dvb_header_ops;
        dev->netdev_ops         = &dvb_netdev_ops;
        dev->mtu                = 4096;
+       dev->max_mtu            = 4096;
 
        dev->flags |= IFF_NOARP;
 }
index 6955c9e22d571a335864b6c701e40ee32079dfe1..55dd71bbdc2aabcd8bf3a1a36291165c3d96eded 100644 (file)
@@ -548,16 +548,6 @@ mpt_lan_close(struct net_device *dev)
        return 0;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
-mpt_lan_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < MPT_LAN_MIN_MTU) || (new_mtu > MPT_LAN_MAX_MTU))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /* Tx timeout handler. */
 static void
@@ -1304,7 +1294,6 @@ static const struct net_device_ops mpt_netdev_ops = {
        .ndo_open       = mpt_lan_open,
        .ndo_stop       = mpt_lan_close,
        .ndo_start_xmit = mpt_lan_sdu_send,
-       .ndo_change_mtu = mpt_lan_change_mtu,
        .ndo_tx_timeout = mpt_lan_tx_timeout,
 };
 
@@ -1375,6 +1364,10 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
        dev->netdev_ops = &mpt_netdev_ops;
        dev->watchdog_timeo = MPT_LAN_TX_TIMEOUT;
 
+       /* MTU range: 96 - 65280 */
+       dev->min_mtu = MPT_LAN_MIN_MTU;
+       dev->max_mtu = MPT_LAN_MAX_MTU;
+
        dlprintk((KERN_INFO MYNAM ": Finished registering dev "
                "and setting initial values\n"));
 
index 557f9782c53c59f4e741204cebcf1a1bf2023109..0c26eaf5f62be580784fba38f94901b52b62db2d 100644 (file)
@@ -118,6 +118,8 @@ static DEFINE_SPINLOCK(xpnet_broadcast_lock);
  * now, the default is 64KB.
  */
 #define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
+/* 68 comes from min TCP+IP+MAC header */
+#define XPNET_MIN_MTU 68
 /* 32KB has been determined to be the ideal */
 #define XPNET_DEF_MTU (0x8000UL)
 
@@ -330,22 +332,6 @@ xpnet_dev_stop(struct net_device *dev)
        return 0;
 }
 
-static int
-xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
-{
-       /* 68 comes from min TCP+IP+MAC header */
-       if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {
-               dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "
-                       "between 68 and %ld\n", dev->name, new_mtu,
-                       XPNET_MAX_MTU);
-               return -EINVAL;
-       }
-
-       dev->mtu = new_mtu;
-       dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);
-       return 0;
-}
-
 /*
  * Notification that the other end has received the message and
  * DMA'd the skb information.  At this point, they are done with
@@ -519,7 +505,6 @@ static const struct net_device_ops xpnet_netdev_ops = {
        .ndo_open               = xpnet_dev_open,
        .ndo_stop               = xpnet_dev_stop,
        .ndo_start_xmit         = xpnet_dev_hard_start_xmit,
-       .ndo_change_mtu         = xpnet_dev_change_mtu,
        .ndo_tx_timeout         = xpnet_dev_tx_timeout,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
@@ -555,6 +540,8 @@ xpnet_init(void)
 
        xpnet_device->netdev_ops = &xpnet_netdev_ops;
        xpnet_device->mtu = XPNET_DEF_MTU;
+       xpnet_device->min_mtu = XPNET_MIN_MTU;
+       xpnet_device->max_mtu = XPNET_MAX_MTU;
 
        /*
         * Multicast assumes the LSB of the first octet is set for multicast
index e90c6a7333d76b4f11e3fccfdcad094be141108e..31f89f1c61233365fd3153ca5f30f171b03ead5e 100644 (file)
@@ -59,7 +59,6 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 static const struct net_device_ops ipddp_netdev_ops = {
        .ndo_start_xmit         = ipddp_xmit,
        .ndo_do_ioctl           = ipddp_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 551f0f8dead3945cf1516aeff01afe6c74117072..c80b023092dde89f6b361e3879e06d70a9d3ad6f 100644 (file)
@@ -950,13 +950,61 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
        dev_queue_xmit(skb);
 }
 
+struct alb_walk_data {
+       struct bonding *bond;
+       struct slave *slave;
+       u8 *mac_addr;
+       bool strict_match;
+};
+
+static int alb_upper_dev_walk(struct net_device *upper, void *_data)
+{
+       struct alb_walk_data *data = _data;
+       bool strict_match = data->strict_match;
+       struct bonding *bond = data->bond;
+       struct slave *slave = data->slave;
+       u8 *mac_addr = data->mac_addr;
+       struct bond_vlan_tag *tags;
+
+       if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
+               if (strict_match &&
+                   ether_addr_equal_64bits(mac_addr,
+                                           upper->dev_addr)) {
+                       alb_send_lp_vid(slave, mac_addr,
+                                       vlan_dev_vlan_proto(upper),
+                                       vlan_dev_vlan_id(upper));
+               } else if (!strict_match) {
+                       alb_send_lp_vid(slave, upper->dev_addr,
+                                       vlan_dev_vlan_proto(upper),
+                                       vlan_dev_vlan_id(upper));
+               }
+       }
+
+       /* If this is a macvlan device, then only send updates
+        * when strict_match is turned off.
+        */
+       if (netif_is_macvlan(upper) && !strict_match) {
+               tags = bond_verify_device_path(bond->dev, upper, 0);
+               if (IS_ERR_OR_NULL(tags))
+                       BUG();
+               alb_send_lp_vid(slave, upper->dev_addr,
+                               tags[0].vlan_proto, tags[0].vlan_id);
+               kfree(tags);
+       }
+
+       return 0;
+}
+
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
                                      bool strict_match)
 {
        struct bonding *bond = bond_get_bond_by_slave(slave);
-       struct net_device *upper;
-       struct list_head *iter;
-       struct bond_vlan_tag *tags;
+       struct alb_walk_data data = {
+               .strict_match = strict_match,
+               .mac_addr = mac_addr,
+               .slave = slave,
+               .bond = bond,
+       };
 
        /* send untagged */
        alb_send_lp_vid(slave, mac_addr, 0, 0);
@@ -965,33 +1013,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
         * for that device.
         */
        rcu_read_lock();
-       netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
-               if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
-                       if (strict_match &&
-                           ether_addr_equal_64bits(mac_addr,
-                                                   upper->dev_addr)) {
-                               alb_send_lp_vid(slave, mac_addr,
-                                               vlan_dev_vlan_proto(upper),
-                                               vlan_dev_vlan_id(upper));
-                       } else if (!strict_match) {
-                               alb_send_lp_vid(slave, upper->dev_addr,
-                                               vlan_dev_vlan_proto(upper),
-                                               vlan_dev_vlan_id(upper));
-                       }
-               }
-
-               /* If this is a macvlan device, then only send updates
-                * when strict_match is turned off.
-                */
-               if (netif_is_macvlan(upper) && !strict_match) {
-                       tags = bond_verify_device_path(bond->dev, upper, 0);
-                       if (IS_ERR_OR_NULL(tags))
-                               BUG();
-                       alb_send_lp_vid(slave, upper->dev_addr,
-                                       tags[0].vlan_proto, tags[0].vlan_id);
-                       kfree(tags);
-               }
-       }
+       netdev_walk_all_upper_dev_rcu(bond->dev, alb_upper_dev_walk, &data);
        rcu_read_unlock();
 }
 
index 5fa36ebc06409aeed7d1477d9775ffd7460ecc6f..c9944d86d0457beea1adf29b218a284892892d28 100644 (file)
@@ -2270,22 +2270,23 @@ re_arm:
        }
 }
 
+static int bond_upper_dev_walk(struct net_device *upper, void *data)
+{
+       __be32 ip = *((__be32 *)data);
+
+       return ip == bond_confirm_addr(upper, 0, ip);
+}
+
 static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
 {
-       struct net_device *upper;
-       struct list_head *iter;
        bool ret = false;
 
        if (ip == bond_confirm_addr(bond->dev, 0, ip))
                return true;
 
        rcu_read_lock();
-       netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
-               if (ip == bond_confirm_addr(upper, 0, ip)) {
-                       ret = true;
-                       break;
-               }
-       }
+       if (netdev_walk_all_upper_dev_rcu(bond->dev, bond_upper_dev_walk, &ip))
+               ret = true;
        rcu_read_unlock();
 
        return ret;
index 221f5f011ff9e6bb64d07d36aef80bbd749f14ed..e128826aa117857b6ac36f9f1f273c1d9eab9044 100644 (file)
@@ -264,7 +264,6 @@ static const struct net_device_ops e100_netdev_ops = {
        .ndo_do_ioctl           = e100_ioctl,
        .ndo_set_mac_address    = e100_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_config         = e100_set_config,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = e100_netpoll,
index 883fd9809dd20f4c961d6e3bab407ee160a36c32..72b9dac29901b7772ff87795a44dcdb724ecd268 100644 (file)
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/if_bridge.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/jiffies.h>
 #include <linux/list.h>
 #include <linux/mdio.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_mdio.h>
 #include <linux/netdevice.h>
 #include <linux/gpio/consumer.h>
@@ -323,6 +327,164 @@ static int mv88e6xxx_serdes_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
                                        reg, val);
 }
 
+static void mv88e6xxx_g1_irq_mask(struct irq_data *d)
+{
+       struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+       unsigned int n = d->hwirq;
+
+       chip->g1_irq.masked |= (1 << n);
+}
+
+static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)
+{
+       struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+       unsigned int n = d->hwirq;
+
+       chip->g1_irq.masked &= ~(1 << n);
+}
+
+static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
+{
+       struct mv88e6xxx_chip *chip = dev_id;
+       unsigned int nhandled = 0;
+       unsigned int sub_irq;
+       unsigned int n;
+       u16 reg;
+       int err;
+
+       mutex_lock(&chip->reg_lock);
+       err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &reg);
+       mutex_unlock(&chip->reg_lock);
+
+       if (err)
+               goto out;
+
+       for (n = 0; n < chip->g1_irq.nirqs; ++n) {
+               if (reg & (1 << n)) {
+                       sub_irq = irq_find_mapping(chip->g1_irq.domain, n);
+                       handle_nested_irq(sub_irq);
+                       ++nhandled;
+               }
+       }
+out:
+       return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
+
+static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)
+{
+       struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+
+       mutex_lock(&chip->reg_lock);
+}
+
+static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d)
+{
+       struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+       u16 mask = GENMASK(chip->g1_irq.nirqs, 0);
+       u16 reg;
+       int err;
+
+       err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &reg);
+       if (err)
+               goto out;
+
+       reg &= ~mask;
+       reg |= (~chip->g1_irq.masked & mask);
+
+       err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg);
+       if (err)
+               goto out;
+
+out:
+       mutex_unlock(&chip->reg_lock);
+}
+
+static struct irq_chip mv88e6xxx_g1_irq_chip = {
+       .name                   = "mv88e6xxx-g1",
+       .irq_mask               = mv88e6xxx_g1_irq_mask,
+       .irq_unmask             = mv88e6xxx_g1_irq_unmask,
+       .irq_bus_lock           = mv88e6xxx_g1_irq_bus_lock,
+       .irq_bus_sync_unlock    = mv88e6xxx_g1_irq_bus_sync_unlock,
+};
+
+static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d,
+                                      unsigned int irq,
+                                      irq_hw_number_t hwirq)
+{
+       struct mv88e6xxx_chip *chip = d->host_data;
+
+       irq_set_chip_data(irq, d->host_data);
+       irq_set_chip_and_handler(irq, &chip->g1_irq.chip, handle_level_irq);
+       irq_set_noprobe(irq);
+
+       return 0;
+}
+
+static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {
+       .map    = mv88e6xxx_g1_irq_domain_map,
+       .xlate  = irq_domain_xlate_twocell,
+};
+
+static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
+{
+       int irq, virq;
+
+       for (irq = 0; irq < 16; irq++) {
+               virq = irq_find_mapping(chip->g2_irq.domain, irq);
+               irq_dispose_mapping(virq);
+       }
+
+       irq_domain_remove(chip->g2_irq.domain);
+}
+
+static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
+{
+       int err, irq;
+       u16 reg;
+
+       chip->g1_irq.nirqs = chip->info->g1_irqs;
+       chip->g1_irq.domain = irq_domain_add_simple(
+               NULL, chip->g1_irq.nirqs, 0,
+               &mv88e6xxx_g1_irq_domain_ops, chip);
+       if (!chip->g1_irq.domain)
+               return -ENOMEM;
+
+       for (irq = 0; irq < chip->g1_irq.nirqs; irq++)
+               irq_create_mapping(chip->g1_irq.domain, irq);
+
+       chip->g1_irq.chip = mv88e6xxx_g1_irq_chip;
+       chip->g1_irq.masked = ~0;
+
+       err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &reg);
+       if (err)
+               goto out;
+
+       reg &= ~GENMASK(chip->g1_irq.nirqs, 0);
+
+       err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg);
+       if (err)
+               goto out;
+
+       /* Reading the interrupt status clears (most of) them */
+       err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &reg);
+       if (err)
+               goto out;
+
+       err = request_threaded_irq(chip->irq, NULL,
+                                  mv88e6xxx_g1_irq_thread_fn,
+                                  IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+                                  dev_name(chip->dev), chip);
+       if (err)
+               goto out;
+
+       return 0;
+
+out:
+       mv88e6xxx_g1_irq_free(chip);
+
+       return err;
+}
+
 int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
 {
        int i;
@@ -477,9 +639,8 @@ static void mv88e6xxx_ppu_state_init(struct mv88e6xxx_chip *chip)
 {
        mutex_init(&chip->ppu_mutex);
        INIT_WORK(&chip->ppu_work, mv88e6xxx_ppu_reenable_work);
-       init_timer(&chip->ppu_timer);
-       chip->ppu_timer.data = (unsigned long)chip;
-       chip->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
+       setup_timer(&chip->ppu_timer, mv88e6xxx_ppu_reenable_timer,
+                   (unsigned long)chip);
 }
 
 static void mv88e6xxx_ppu_state_destroy(struct mv88e6xxx_chip *chip)
@@ -2701,7 +2862,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
        return mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, 0x0000);
 }
 
-int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
+static int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
 {
        int err;
 
@@ -2770,7 +2931,11 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
        /* Enable the PHY Polling Unit if present, don't discard any packets,
         * and mask all interrupt sources.
         */
-       reg = 0;
+       err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &reg);
+       if (err < 0)
+               return err;
+
+       reg &= ~GLOBAL_CONTROL_PPU_ENABLE;
        if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU) ||
            mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU_ACTIVE))
                reg |= GLOBAL_CONTROL_PPU_ENABLE;
@@ -2875,10 +3040,6 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
 
        mutex_lock(&chip->reg_lock);
 
-       err = mv88e6xxx_switch_reset(chip);
-       if (err)
-               goto unlock;
-
        /* Setup Switch Port Registers */
        for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
                err = mv88e6xxx_setup_port(chip, i);
@@ -3326,6 +3487,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 8,
                .flags = MV88E6XXX_FLAGS_FAMILY_6097,
                .ops = &mv88e6085_ops,
        },
@@ -3339,6 +3501,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 8,
                .flags = MV88E6XXX_FLAGS_FAMILY_6095,
                .ops = &mv88e6095_ops,
        },
@@ -3352,6 +3515,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6165,
                .ops = &mv88e6123_ops,
        },
@@ -3365,6 +3529,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6185,
                .ops = &mv88e6131_ops,
        },
@@ -3378,6 +3543,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6165,
                .ops = &mv88e6161_ops,
        },
@@ -3391,6 +3557,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6165,
                .ops = &mv88e6165_ops,
        },
@@ -3404,6 +3571,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6351,
                .ops = &mv88e6171_ops,
        },
@@ -3417,6 +3585,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6352,
                .ops = &mv88e6172_ops,
        },
@@ -3430,6 +3599,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6351,
                .ops = &mv88e6175_ops,
        },
@@ -3443,6 +3613,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6352,
                .ops = &mv88e6176_ops,
        },
@@ -3456,6 +3627,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 8,
                .flags = MV88E6XXX_FLAGS_FAMILY_6185,
                .ops = &mv88e6185_ops,
        },
@@ -3469,6 +3641,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6352,
                .ops = &mv88e6240_ops,
        },
@@ -3482,6 +3655,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 8,
                .flags = MV88E6XXX_FLAGS_FAMILY_6320,
                .ops = &mv88e6320_ops,
        },
@@ -3495,6 +3669,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 8,
                .flags = MV88E6XXX_FLAGS_FAMILY_6320,
                .ops = &mv88e6321_ops,
        },
@@ -3508,6 +3683,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6351,
                .ops = &mv88e6350_ops,
        },
@@ -3521,6 +3697,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6351,
                .ops = &mv88e6351_ops,
        },
@@ -3534,6 +3711,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .port_base_addr = 0x10,
                .global1_addr = 0x1b,
                .age_time_coeff = 15000,
+               .g1_irqs = 9,
                .flags = MV88E6XXX_FLAGS_FAMILY_6352,
                .ops = &mv88e6352_ops,
        },
@@ -3667,6 +3845,12 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
        if (err)
                goto free;
 
+       mutex_lock(&chip->reg_lock);
+       err = mv88e6xxx_switch_reset(chip);
+       mutex_unlock(&chip->reg_lock);
+       if (err)
+               goto free;
+
        mv88e6xxx_phy_init(chip);
 
        err = mv88e6xxx_mdio_register(chip, NULL);
@@ -3837,17 +4021,56 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
            !of_property_read_u32(np, "eeprom-length", &eeprom_len))
                chip->eeprom_len = eeprom_len;
 
+       mutex_lock(&chip->reg_lock);
+       err = mv88e6xxx_switch_reset(chip);
+       mutex_unlock(&chip->reg_lock);
+       if (err)
+               goto out;
+
+       chip->irq = of_irq_get(np, 0);
+       if (chip->irq == -EPROBE_DEFER) {
+               err = chip->irq;
+               goto out;
+       }
+
+       if (chip->irq > 0) {
+               /* Has to be performed before the MDIO bus is created,
+                * because the PHYs will link there interrupts to these
+                * interrupt controllers
+                */
+               mutex_lock(&chip->reg_lock);
+               err = mv88e6xxx_g1_irq_setup(chip);
+               mutex_unlock(&chip->reg_lock);
+
+               if (err)
+                       goto out;
+
+               if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT)) {
+                       err = mv88e6xxx_g2_irq_setup(chip);
+                       if (err)
+                               goto out_g1_irq;
+               }
+       }
+
        err = mv88e6xxx_mdio_register(chip, np);
        if (err)
-               return err;
+               goto out_g2_irq;
 
        err = mv88e6xxx_register_switch(chip, np);
-       if (err) {
-               mv88e6xxx_mdio_unregister(chip);
-               return err;
-       }
+       if (err)
+               goto out_mdio;
 
        return 0;
+
+out_mdio:
+       mv88e6xxx_mdio_unregister(chip);
+out_g2_irq:
+       if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT))
+               mv88e6xxx_g2_irq_free(chip);
+out_g1_irq:
+       mv88e6xxx_g1_irq_free(chip);
+out:
+       return err;
 }
 
 static void mv88e6xxx_remove(struct mdio_device *mdiodev)
@@ -3858,6 +4081,10 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
        mv88e6xxx_phy_destroy(chip);
        mv88e6xxx_unregister_switch(chip);
        mv88e6xxx_mdio_unregister(chip);
+
+       if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT))
+               mv88e6xxx_g2_irq_free(chip);
+       mv88e6xxx_g1_irq_free(chip);
 }
 
 static const struct of_device_id mv88e6xxx_of_match[] = {
index cf686e7506a927594c8b3c5e9d7db19fea802e4c..1a0b13521d1378aa404f2a472812fba972a7c7a3 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C)
+ * Marvell 88E6xxx Switch Global 2 Registers support (device address
+ * 0x1C)
  *
  * Copyright (c) 2008 Marvell Semiconductor
  *
@@ -11,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/irqdomain.h>
 #include "mv88e6xxx.h"
 #include "global2.h"
 
@@ -417,6 +419,141 @@ int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
        return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
 }
 
+static void mv88e6xxx_g2_irq_mask(struct irq_data *d)
+{
+       struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+       unsigned int n = d->hwirq;
+
+       chip->g2_irq.masked |= (1 << n);
+}
+
+static void mv88e6xxx_g2_irq_unmask(struct irq_data *d)
+{
+       struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+       unsigned int n = d->hwirq;
+
+       chip->g2_irq.masked &= ~(1 << n);
+}
+
+static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id)
+{
+       struct mv88e6xxx_chip *chip = dev_id;
+       unsigned int nhandled = 0;
+       unsigned int sub_irq;
+       unsigned int n;
+       int err;
+       u16 reg;
+
+       mutex_lock(&chip->reg_lock);
+       err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, &reg);
+       mutex_unlock(&chip->reg_lock);
+       if (err)
+               goto out;
+
+       for (n = 0; n < 16; ++n) {
+               if (reg & (1 << n)) {
+                       sub_irq = irq_find_mapping(chip->g2_irq.domain, n);
+                       handle_nested_irq(sub_irq);
+                       ++nhandled;
+               }
+       }
+out:
+       return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
+
+static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d)
+{
+       struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+
+       mutex_lock(&chip->reg_lock);
+}
+
+static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d)
+{
+       struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+
+       mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked);
+
+       mutex_unlock(&chip->reg_lock);
+}
+
+static struct irq_chip mv88e6xxx_g2_irq_chip = {
+       .name                   = "mv88e6xxx-g2",
+       .irq_mask               = mv88e6xxx_g2_irq_mask,
+       .irq_unmask             = mv88e6xxx_g2_irq_unmask,
+       .irq_bus_lock           = mv88e6xxx_g2_irq_bus_lock,
+       .irq_bus_sync_unlock    = mv88e6xxx_g2_irq_bus_sync_unlock,
+};
+
+static int mv88e6xxx_g2_irq_domain_map(struct irq_domain *d,
+                                      unsigned int irq,
+                                      irq_hw_number_t hwirq)
+{
+       struct mv88e6xxx_chip *chip = d->host_data;
+
+       irq_set_chip_data(irq, d->host_data);
+       irq_set_chip_and_handler(irq, &chip->g2_irq.chip, handle_level_irq);
+       irq_set_noprobe(irq);
+
+       return 0;
+}
+
+static const struct irq_domain_ops mv88e6xxx_g2_irq_domain_ops = {
+       .map    = mv88e6xxx_g2_irq_domain_map,
+       .xlate  = irq_domain_xlate_twocell,
+};
+
+void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
+{
+       int irq, virq;
+
+       for (irq = 0; irq < 16; irq++) {
+               virq = irq_find_mapping(chip->g2_irq.domain, irq);
+               irq_dispose_mapping(virq);
+       }
+
+       irq_domain_remove(chip->g2_irq.domain);
+}
+
+int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
+{
+       int device_irq;
+       int err, irq;
+
+       if (!chip->dev->of_node)
+               return -EINVAL;
+
+       chip->g2_irq.domain = irq_domain_add_simple(
+               chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
+       if (!chip->g2_irq.domain)
+               return -ENOMEM;
+
+       for (irq = 0; irq < 16; irq++)
+               irq_create_mapping(chip->g2_irq.domain, irq);
+
+       chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
+       chip->g2_irq.masked = ~0;
+
+       device_irq = irq_find_mapping(chip->g1_irq.domain,
+                                     GLOBAL_STATUS_IRQ_DEVICE);
+       if (device_irq < 0) {
+               err = device_irq;
+               goto out;
+       }
+
+       err = devm_request_threaded_irq(chip->dev, device_irq, NULL,
+                                       mv88e6xxx_g2_irq_thread_fn,
+                                       IRQF_ONESHOT, "mv88e6xxx-g1", chip);
+       if (err)
+               goto out;
+
+       return 0;
+out:
+       mv88e6xxx_g2_irq_free(chip);
+
+       return err;
+}
+
 int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
 {
        u16 reg;
index c4bb9035ee3adc291ae140920147ed0e635575e1..1eb3ddd2155121adfd276b3af7e2b7294e00b82f 100644 (file)
@@ -33,6 +33,8 @@ int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
 int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
                              struct ethtool_eeprom *eeprom, u8 *data);
 int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip);
+void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip);
 
 #else /* !CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
 
@@ -83,6 +85,15 @@ static inline int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
        return -EOPNOTSUPP;
 }
 
+static inline int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
+{
+}
+
 #endif /* CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
 
 #endif /* _MV88E6XXX_GLOBAL2_H */
index e572121c196e3bf5ff7cb808f6c036e35328e6e7..6f48e5886b2adbbae021576cf2bf51c59f901059 100644 (file)
@@ -13,6 +13,7 @@
 #define __MV88E6XXX_H
 
 #include <linux/if_vlan.h>
+#include <linux/irq.h>
 #include <linux/gpio/consumer.h>
 
 #ifndef UINT64_MAX
 #define GLOBAL_STATUS_PPU_INITIALIZING (0x1 << 14)
 #define GLOBAL_STATUS_PPU_DISABLED     (0x2 << 14)
 #define GLOBAL_STATUS_PPU_POLLING      (0x3 << 14)
+#define GLOBAL_STATUS_IRQ_AVB          8
+#define GLOBAL_STATUS_IRQ_DEVICE       7
+#define GLOBAL_STATUS_IRQ_STATS                6
+#define GLOBAL_STATUS_IRQ_VTU_PROBLEM  5
+#define GLOBAL_STATUS_IRQ_VTU_DONE     4
+#define GLOBAL_STATUS_IRQ_ATU_PROBLEM  3
+#define GLOBAL_STATUS_IRQ_ATU_DONE     2
+#define GLOBAL_STATUS_IRQ_TCAM_DONE    1
+#define GLOBAL_STATUS_IRQ_EEPROM_DONE  0
 #define GLOBAL_MAC_01          0x01
 #define GLOBAL_MAC_23          0x02
 #define GLOBAL_MAC_45          0x03
@@ -417,6 +427,7 @@ enum mv88e6xxx_cap {
         * The device contains a second set of global 16-bit registers.
         */
        MV88E6XXX_CAP_GLOBAL2,
+       MV88E6XXX_CAP_G2_INT,           /* (0x00) Interrupt Status */
        MV88E6XXX_CAP_G2_MGMT_EN_2X,    /* (0x02) MGMT Enable Register 2x */
        MV88E6XXX_CAP_G2_MGMT_EN_0X,    /* (0x03) MGMT Enable Register 0x */
        MV88E6XXX_CAP_G2_IRL_CMD,       /* (0x09) Ingress Rate Command */
@@ -464,6 +475,7 @@ enum mv88e6xxx_cap {
 #define MV88E6XXX_FLAG_G1_VTU_FID      BIT_ULL(MV88E6XXX_CAP_G1_VTU_FID)
 
 #define MV88E6XXX_FLAG_GLOBAL2         BIT_ULL(MV88E6XXX_CAP_GLOBAL2)
+#define MV88E6XXX_FLAG_G2_INT          BIT_ULL(MV88E6XXX_CAP_G2_INT)
 #define MV88E6XXX_FLAG_G2_MGMT_EN_2X   BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_2X)
 #define MV88E6XXX_FLAG_G2_MGMT_EN_0X   BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_0X)
 #define MV88E6XXX_FLAG_G2_IRL_CMD      BIT_ULL(MV88E6XXX_CAP_G2_IRL_CMD)
@@ -524,6 +536,7 @@ enum mv88e6xxx_cap {
        (MV88E6XXX_FLAG_G1_ATU_FID |    \
         MV88E6XXX_FLAG_G1_VTU_FID |    \
         MV88E6XXX_FLAG_GLOBAL2 |       \
+        MV88E6XXX_FLAG_G2_INT |        \
         MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
         MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
         MV88E6XXX_FLAG_G2_POT |        \
@@ -536,6 +549,7 @@ enum mv88e6xxx_cap {
 
 #define MV88E6XXX_FLAGS_FAMILY_6185    \
        (MV88E6XXX_FLAG_GLOBAL2 |       \
+        MV88E6XXX_FLAG_G2_INT |        \
         MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
         MV88E6XXX_FLAGS_MULTI_CHIP |   \
         MV88E6XXX_FLAG_PPU |           \
@@ -561,6 +575,7 @@ enum mv88e6xxx_cap {
         MV88E6XXX_FLAG_G1_ATU_FID |    \
         MV88E6XXX_FLAG_G1_VTU_FID |    \
         MV88E6XXX_FLAG_GLOBAL2 |       \
+        MV88E6XXX_FLAG_G2_INT |        \
         MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
         MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
         MV88E6XXX_FLAG_G2_POT |        \
@@ -578,6 +593,7 @@ enum mv88e6xxx_cap {
         MV88E6XXX_FLAG_G1_ATU_FID |    \
         MV88E6XXX_FLAG_G1_VTU_FID |    \
         MV88E6XXX_FLAG_GLOBAL2 |       \
+        MV88E6XXX_FLAG_G2_INT |        \
         MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
         MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
         MV88E6XXX_FLAG_G2_POT |        \
@@ -602,6 +618,7 @@ struct mv88e6xxx_info {
        unsigned int port_base_addr;
        unsigned int global1_addr;
        unsigned int age_time_coeff;
+       unsigned int g1_irqs;
        unsigned long long flags;
        const struct mv88e6xxx_ops *ops;
 };
@@ -628,6 +645,13 @@ struct mv88e6xxx_priv_port {
        struct net_device *bridge_dev;
 };
 
+struct mv88e6xxx_irq {
+       u16 masked;
+       struct irq_chip chip;
+       struct irq_domain *domain;
+       unsigned int nirqs;
+};
+
 struct mv88e6xxx_chip {
        const struct mv88e6xxx_info *info;
 
@@ -677,6 +701,13 @@ struct mv88e6xxx_chip {
 
        /* And the MDIO bus itself */
        struct mii_bus *mdio_bus;
+
+       /* There can be two interrupt controllers, which are chained
+        * off a GPIO as interrupt source
+        */
+       struct mv88e6xxx_irq g1_irq;
+       struct mv88e6xxx_irq g2_irq;
+       int irq;
 };
 
 struct mv88e6xxx_bus_ops {
index 91ada52f776b67b84be5c02d1daff13fe85b8e0d..9f9a5f440e2f71f656299b41a6828b70a30898d8 100644 (file)
@@ -508,7 +508,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_get_stats          = el3_get_stats,
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = el3_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index b26e038b4a0e904861262cc6c0bcf570d3a2d6d0..b9f4c463e516c34e538e78ccce5a7c0efcf7c818 100644 (file)
@@ -570,7 +570,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_tx_timeout         = corkscrew_timeout,
        .ndo_get_stats          = corkscrew_get_stats,
        .ndo_set_rx_mode        = set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index b88afd7593074d83bd878882d3fc31a4306dd654..9359a37fedc075fe82474e0a42726bfd9c22e3b3 100644 (file)
@@ -254,7 +254,6 @@ static const struct net_device_ops el3_netdev_ops = {
        .ndo_get_stats          = el3_get_stats,
        .ndo_do_ioctl           = el3_ioctl,
        .ndo_set_rx_mode        = set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 71396e4b87e399f757d27828adc97c2a00db8660..e28254a0059971c3432ea3726f35d8f831780e49 100644 (file)
@@ -188,7 +188,6 @@ static const struct net_device_ops el3_netdev_ops = {
        .ndo_set_config         = el3_config,
        .ndo_get_stats          = el3_get_stats,
        .ndo_set_rx_mode        = set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 9133e7926da53050c0614c15924655eb0330dae5..3ecf61382269d0a190ccb3aca80308cedf1f9e56 100644 (file)
@@ -1062,7 +1062,6 @@ static const struct net_device_ops boomrang_netdev_ops = {
        .ndo_do_ioctl           = vortex_ioctl,
 #endif
        .ndo_set_rx_mode        = set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1080,7 +1079,6 @@ static const struct net_device_ops vortex_netdev_ops = {
        .ndo_do_ioctl           = vortex_ioctl,
 #endif
        .ndo_set_rx_mode        = set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 8f8418d2ac4ad07016c37e6d5cb255e2b9709b85..506b507b415810cd9833782615cc9b575a82278e 100644 (file)
@@ -2255,7 +2255,6 @@ static const struct net_device_ops typhoon_netdev_ops = {
        .ndo_get_stats          = typhoon_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int
index 5db1f55abef44fe9bf155d577c7aabcc521fadb8..a43544af257b562f43f1525e06891b2cdf18889a 100644 (file)
@@ -64,7 +64,6 @@ const struct net_device_ops ei_netdev_ops = {
        .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ei_poll,
 #endif
index e8fc2e87e840f40e73b1cc14434342e1cbace64e..46d2257c4430bedad7975d7f198570be2c3ab284 100644 (file)
@@ -69,7 +69,6 @@ const struct net_device_ops eip_netdev_ops = {
        .ndo_set_rx_mode        = eip_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = eip_poll,
 #endif
index 39ca9350d1b22d0d153f377e86a41212fa12d380..b0a3b85fc6f8d346f3a7d421b094b491d022dd12 100644 (file)
@@ -536,7 +536,6 @@ static const struct net_device_ops ax_netdev_ops = {
        .ndo_set_rx_mode        = ax_ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ax_ei_poll,
 #endif
index 4ea717d68c957a38704ec403ccc80712274bc0a9..1d84a0544ace95224906572bc5a50919819763da 100644 (file)
@@ -134,7 +134,6 @@ static const struct net_device_ops axnet_netdev_ops = {
        .ndo_tx_timeout         = axnet_tx_timeout,
        .ndo_get_stats          = get_stats,
        .ndo_set_rx_mode        = set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index d686b9cac29f0b4ac2805455b6ba8f1f99017a74..11cbf22ad2017b28015344deac45ce229d149950 100644 (file)
@@ -654,7 +654,6 @@ static const struct net_device_ops etherh_netdev_ops = {
        .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = __ei_poll,
 #endif
index 0fe19d609c2ecbf0d84881f2f0960916eb4c010c..8ae249195301962f22c2abcc0e04f21e136cd812 100644 (file)
@@ -105,7 +105,6 @@ static const struct net_device_ops hydra_netdev_ops = {
        .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = __ei_poll,
 #endif
index b9283901136e974a9ad4207cae898cb492207700..9497f18eaba02d5f9caa16619123065441c46f06 100644 (file)
@@ -483,7 +483,6 @@ static const struct net_device_ops mac8390_netdev_ops = {
        .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = __ei_poll,
 #endif
index e1c055574a119256694b49150bbc7728d3306b7f..4bb967bc879e33dd2da16dad864159d671316719 100644 (file)
@@ -308,7 +308,6 @@ static const struct net_device_ops mcf8390_netdev_ops = {
        .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = __ei_poll,
 #endif
index 57e97910c72811ac9e5c24428cd3e3500dd089dd..07355302443d8d4dcefe3ef0fb89a4e426a7526f 100644 (file)
@@ -209,7 +209,6 @@ static const struct net_device_ops ne2k_netdev_ops = {
        .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = ei_poll,
 #endif
index 2f79d29f17f2f0fae388f9cd4b4d9da201793775..63079a6e20d94910748b49787e84dbca0cd6df4b 100644 (file)
@@ -227,7 +227,6 @@ static const struct net_device_ops pcnet_netdev_ops = {
        .ndo_do_ioctl           = ei_ioctl,
        .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 139385dcdaa753db90e14c6265fa1d0c117acb15..364b6514f65fa61b68780aa996b6747f4581f4f0 100644 (file)
@@ -195,7 +195,6 @@ static const struct net_device_ops ultra_netdev_ops = {
        .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ultra_poll,
 #endif
index dd7d816bde52680b793880ab27e0c00454125a7c..ad019cbc698f6ea8ec9fbd648015e6630a6b5f82 100644 (file)
@@ -156,7 +156,6 @@ static const struct net_device_ops wd_netdev_ops = {
        .ndo_set_rx_mode        = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ei_poll,
 #endif
index 8308728fad0511c74f0164488a59e09ef2ea8194..6d93956b293b4b0fc62c47dd64eaeb345265b8b7 100644 (file)
@@ -284,7 +284,6 @@ static const struct net_device_ops zorro8390_netdev_ops = {
        .ndo_set_rx_mode        = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = __ei_poll,
 #endif
index 8af2c88d5b33038bccaa94a3100864782fb2a963..4a9a16e25666199d14b8ac3704d0870500bb7df4 100644 (file)
@@ -634,7 +634,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_get_stats          = get_stats,
        .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = netdev_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef VLAN_SUPPORT
index 00f9ee3fc3e5c4dee20a820bcd0a066bdeb02b2a..88164529b52a2a44207b71b49c86297067b71718 100644 (file)
@@ -1571,7 +1571,6 @@ static const struct net_device_ops bfin_mac_netdev_ops = {
        .ndo_set_rx_mode        = bfin_mac_set_multicast_list,
        .ndo_do_ioctl           = bfin_mac_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = bfin_mac_poll_controller,
 #endif
index 906683851c7d2257f7f3484ff6fff627702087fb..831bab352f8e6a99b0ee3ce519e8b7f7cbd466d0 100644 (file)
@@ -176,6 +176,8 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver for the ET1310 by Agere S
 #define NUM_FBRS               2
 
 #define MAX_PACKETS_HANDLED    256
+#define ET131X_MIN_MTU         64
+#define ET131X_MAX_MTU         9216
 
 #define ALCATEL_MULTICAST_PKT  0x01000000
 #define ALCATEL_BROADCAST_PKT  0x02000000
@@ -3869,9 +3871,6 @@ static int et131x_change_mtu(struct net_device *netdev, int new_mtu)
        int result = 0;
        struct et131x_adapter *adapter = netdev_priv(netdev);
 
-       if (new_mtu < 64 || new_mtu > 9216)
-               return -EINVAL;
-
        et131x_disable_txrx(netdev);
 
        netdev->mtu = new_mtu;
@@ -3958,6 +3957,8 @@ static int et131x_pci_setup(struct pci_dev *pdev,
 
        netdev->watchdog_timeo = ET131X_TX_TIMEOUT;
        netdev->netdev_ops     = &et131x_netdev_ops;
+       netdev->min_mtu        = ET131X_MIN_MTU;
+       netdev->max_mtu        = ET131X_MAX_MTU;
 
        SET_NETDEV_DEV(netdev, &pdev->dev);
        netdev->ethtool_ops = &et131x_ethtool_ops;
index 6ffdff68bfc477a426acc065db88c38f446b4e21..af27f9dbedf2e366c4948449046f03c4d3625fb8 100644 (file)
@@ -773,7 +773,6 @@ static const struct net_device_ops emac_netdev_ops = {
        .ndo_tx_timeout         = emac_timeout,
        .ndo_set_rx_mode        = emac_set_rx_mode,
        .ndo_do_ioctl           = emac_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = emac_set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index b90a26b13fdf22a61b08b311a4f53dbd77f81a6b..a5c1e290677a44bf8445c065c2e1cb154d714830 100644 (file)
@@ -474,6 +474,8 @@ static int acenic_probe_one(struct pci_dev *pdev,
        dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
 
        dev->watchdog_timeo = 5*HZ;
+       dev->min_mtu = 0;
+       dev->max_mtu = ACE_JUMBO_MTU;
 
        dev->netdev_ops = &ace_netdev_ops;
        dev->ethtool_ops = &ace_ethtool_ops;
@@ -2548,9 +2550,6 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu)
        struct ace_private *ap = netdev_priv(dev);
        struct ace_regs __iomem *regs = ap->regs;
 
-       if (new_mtu > ACE_JUMBO_MTU)
-               return -EINVAL;
-
        writel(new_mtu + ETH_HLEN + 4, &regs->IfMtu);
        dev->mtu = new_mtu;
 
index e0052003d16f75e5fc10c49cdb2079d0c7bfc569..9b640c8fbc28b96a97d2bf1da58d7e6b851b102b 100644 (file)
@@ -443,7 +443,6 @@ struct altera_tse_private {
        /* RX/TX MAC FIFO configs */
        u32 tx_fifo_depth;
        u32 rx_fifo_depth;
-       u32 max_mtu;
 
        /* Hash filter settings */
        u32 hash_filter;
index bda31f308cc2a0b028273298345b5d43b03908b6..8e92084342622732ecdcd4d8e4b164551906c74e 100644 (file)
@@ -994,20 +994,11 @@ static void tse_set_mac(struct altera_tse_private *priv, bool enable)
  */
 static int tse_change_mtu(struct net_device *dev, int new_mtu)
 {
-       struct altera_tse_private *priv = netdev_priv(dev);
-       unsigned int max_mtu = priv->max_mtu;
-       unsigned int min_mtu = ETH_ZLEN + ETH_FCS_LEN;
-
        if (netif_running(dev)) {
                netdev_err(dev, "must be stopped to change its MTU\n");
                return -EBUSY;
        }
 
-       if ((new_mtu < min_mtu) || (new_mtu > max_mtu)) {
-               netdev_err(dev, "invalid MTU, max MTU is: %u\n", max_mtu);
-               return -EINVAL;
-       }
-
        dev->mtu = new_mtu;
        netdev_update_features(dev);
 
@@ -1338,11 +1329,13 @@ static int altera_tse_probe(struct platform_device *pdev)
                if (upper_32_bits(priv->rxdescmem_busaddr)) {
                        dev_dbg(priv->device,
                                "SGDMA bus addresses greater than 32-bits\n");
+                       ret = -EINVAL;
                        goto err_free_netdev;
                }
                if (upper_32_bits(priv->txdescmem_busaddr)) {
                        dev_dbg(priv->device,
                                "SGDMA bus addresses greater than 32-bits\n");
+                       ret = -EINVAL;
                        goto err_free_netdev;
                }
        } else if (priv->dmaops &&
@@ -1446,15 +1439,16 @@ static int altera_tse_probe(struct platform_device *pdev)
                of_property_read_bool(pdev->dev.of_node,
                                      "altr,has-supplementary-unicast");
 
+       priv->dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN;
        /* Max MTU is 1500, ETH_DATA_LEN */
-       priv->max_mtu = ETH_DATA_LEN;
+       priv->dev->max_mtu = ETH_DATA_LEN;
 
        /* Get the max mtu from the device tree. Note that the
         * "max-frame-size" parameter is actually max mtu. Definition
         * in the ePAPR v1.1 spec and usage differ, so go with usage.
         */
        of_property_read_u32(pdev->dev.of_node, "max-frame-size",
-                            &priv->max_mtu);
+                            &priv->dev->max_mtu);
 
        /* The DMA buffer size already accounts for an alignment bias
         * to avoid unaligned access exceptions for the NIOS processor,
index bfeaec5bd7b90098076286f4b8763cfbefd6db56..cc8b13ebfa75a8b7c0757ce861589c7b7b075149 100644 (file)
@@ -103,13 +103,6 @@ static int ena_change_mtu(struct net_device *dev, int new_mtu)
        struct ena_adapter *adapter = netdev_priv(dev);
        int ret;
 
-       if ((new_mtu > adapter->max_mtu) || (new_mtu < ENA_MIN_MTU)) {
-               netif_err(adapter, drv, dev,
-                         "Invalid MTU setting. new_mtu: %d\n", new_mtu);
-
-               return -EINVAL;
-       }
-
        ret = ena_com_set_dev_mtu(adapter->ena_dev, new_mtu);
        if (!ret) {
                netif_dbg(adapter, drv, dev, "set MTU to %d\n", new_mtu);
@@ -2755,6 +2748,8 @@ static void ena_set_conf_feat_params(struct ena_adapter *adapter,
        ena_set_dev_offloads(feat, netdev);
 
        adapter->max_mtu = feat->dev_attr.max_mtu;
+       netdev->max_mtu = adapter->max_mtu;
+       netdev->min_mtu = ENA_MIN_MTU;
 }
 
 static int ena_rss_init_default(struct ena_adapter *adapter)
@@ -3018,12 +3013,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        adapter->last_keep_alive_jiffies = jiffies;
 
-       init_timer(&adapter->timer_service);
-       adapter->timer_service.expires = round_jiffies(jiffies + HZ);
-       adapter->timer_service.function = ena_timer_service;
-       adapter->timer_service.data = (unsigned long)adapter;
-
-       add_timer(&adapter->timer_service);
+       setup_timer(&adapter->timer_service, ena_timer_service,
+                   (unsigned long)adapter);
+       mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
 
        dev_info(&pdev->dev, "%s found at mem %lx, mac addr %pM Queues %d\n",
                 DEVICE_NAME, (long)pci_resource_start(pdev, 0),
index a83cd1c4ce1d051885050c6d5b7b257fce562c62..ee4b94e3cda906cd4ed4fa8dcfd8048a7c81ae52 100644 (file)
@@ -665,7 +665,6 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_tx_timeout         = lance_tx_timeout,
        .ndo_set_rx_mode        = lance_set_multicast,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
index fcdf5dda448f9c7acf5a0a537cbbcb0de76b09df..b11e910850f7f03d8ecd30ca02f5fe9a71fa4a1d 100644 (file)
@@ -663,7 +663,6 @@ static const struct net_device_ops am79c961_netdev_ops = {
        .ndo_set_rx_mode        = am79c961_setmulticastlist,
        .ndo_tx_timeout         = am79c961_timeout,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = am79c961_poll_controller,
index f92cc97151ecf6180a53cfd6f5da6a1fe6f6fe39..84b4ffbd084ab5f8192118d54b1ebba23bbf1822 100644 (file)
@@ -1556,9 +1556,6 @@ static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
        struct amd8111e_priv *lp = netdev_priv(dev);
        int err;
 
-       if ((new_mtu < AMD8111E_MIN_MTU) || (new_mtu > AMD8111E_MAX_MTU))
-               return -EINVAL;
-
        if (!netif_running(dev)) {
                /* new_mtu will be used
                 * when device starts netxt time
@@ -1874,6 +1871,8 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
        dev->ethtool_ops = &ops;
        dev->irq =pdev->irq;
        dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
+       dev->min_mtu = AMD8111E_MIN_MTU;
+       dev->max_mtu = AMD8111E_MAX_MTU;
        netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
 
 #if AMD8111E_VLAN_TAG_USED
index 968b7bfac8fcaa9af767c57c474a83b3229b09a0..5fd7b15b0574604e30d5827fc26397fc8603cce7 100644 (file)
@@ -706,7 +706,6 @@ static const struct net_device_ops ariadne_netdev_ops = {
        .ndo_get_stats          = ariadne_get_stats,
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
index d2bc8e5dcd23b21dab55b377961d358b55a29ede..e53ccc3b7d8dcf73eff299469a0dbb677f61058d 100644 (file)
@@ -460,7 +460,6 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_set_mac_address    = lance_set_mac_address,
        .ndo_tx_timeout         = lance_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static unsigned long __init lance_probe1( struct net_device *dev,
index df664187cd8271fd40a441ccebf2de29629b9722..a3c90fe5de00c6b8151893c788b5ad7f36fe6344 100644 (file)
@@ -1103,7 +1103,6 @@ static const struct net_device_ops au1000_netdev_ops = {
        .ndo_tx_timeout         = au1000_tx_timeout,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int au1000_probe(struct platform_device *pdev)
index b799c7ac899b984bbeeacfc55f0d0917c7e2a037..76e5fc7adff519a8ed18b412a5bb42754eba8fec 100644 (file)
@@ -1013,7 +1013,6 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_start_xmit         = lance_start_xmit,
        .ndo_tx_timeout         = lance_tx_timeout,
        .ndo_set_rx_mode        = lance_set_multicast,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 };
index 6c9de117ffc68f2941d20f465161460f806f2d04..c3dbf1c8a2699dabaa0e5178cba241e20e0c6e75 100644 (file)
@@ -72,7 +72,6 @@ static const struct net_device_ops hplance_netdev_ops = {
        .ndo_stop               = hplance_close,
        .ndo_start_xmit         = lance_start_xmit,
        .ndo_set_rx_mode        = lance_set_multicast,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index abb1ba228b26512f020d89f5123faaa1a9a7e3a4..61a641f2314968cda20bd2c76b5de11309efa207 100644 (file)
@@ -461,7 +461,6 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_get_stats          = lance_get_stats,
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = lance_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 0660ac5846bbef3e07d99c25a3c2d63f6eff9e12..0a920448522f350cf3dcf968e064a3715e3f65e1 100644 (file)
@@ -62,7 +62,6 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_start_xmit         = lance_start_xmit,
        .ndo_set_rx_mode        = lance_set_multicast,
        .ndo_tx_timeout         = lance_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 };
index cda53db75f17bdc957bcf3dcce20eda52dd04daa..5985bf220a8da9d426a38d7e593f6daaa3859de0 100644 (file)
@@ -407,7 +407,6 @@ static const struct net_device_ops ni65_netdev_ops = {
        .ndo_start_xmit         = ni65_send_packet,
        .ndo_tx_timeout         = ni65_timeout,
        .ndo_set_rx_mode        = set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 2807e181647bfde7b81b4e6ecd648be2a9c40ef2..113a3b3cc50c9d5f6df5fc2267b79f6cc2828c08 100644 (file)
@@ -427,7 +427,6 @@ static const struct net_device_ops mace_netdev_ops = {
        .ndo_set_config         = mace_config,
        .ndo_get_stats          = mace_get_stats,
        .ndo_set_rx_mode        = set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index c22bf52d3320b4831f944ceef01770264acc3c6b..adc7ab99a2f692b8d71fb27fc1904a1bbc837b46 100644 (file)
@@ -1527,7 +1527,6 @@ static const struct net_device_ops pcnet32_netdev_ops = {
        .ndo_get_stats          = pcnet32_get_stats,
        .ndo_set_rx_mode        = pcnet32_set_multicast_list,
        .ndo_do_ioctl           = pcnet32_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 3d8c6b2cdea4ca5906e0abb09a0523a5aa03b74c..12bb4f1489fc0560ff76dbaa5009a35c80a87362 100644 (file)
@@ -299,7 +299,6 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_start_xmit         = lance_start_xmit,
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_set_mac_address    = NULL,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 9b56b40259dccbfe14bffff5ce246cc71bed17bd..291ca5187f12333e2c13c23adc79903044c78bb5 100644 (file)
@@ -1294,7 +1294,6 @@ static const struct net_device_ops sparc_lance_ops = {
        .ndo_start_xmit         = lance_start_xmit,
        .ndo_set_rx_mode        = lance_set_multicast,
        .ndo_tx_timeout         = lance_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 7f9216db026fa2ee8abe1cf695415ad0be237dc8..c4e668208e0474eed26292626fdfeafbc048314a 100644 (file)
@@ -257,11 +257,6 @@ static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu)
 {
        unsigned int rx_buf_size;
 
-       if (mtu > XGMAC_JUMBO_PACKET_MTU) {
-               netdev_alert(netdev, "MTU exceeds maximum supported value\n");
-               return -EINVAL;
-       }
-
        rx_buf_size = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
        rx_buf_size = clamp_val(rx_buf_size, XGBE_RX_MIN_BUF_SIZE, PAGE_SIZE);
 
index 9de078819aa676525d4fae65a6a47e3df448dc1e..6997f1110ecebaf9e5e203c82146fd918acd01ad 100644 (file)
@@ -613,6 +613,7 @@ static int xgbe_probe(struct platform_device *pdev)
        attr = device_get_dma_attr(dev);
        if (attr == DEV_DMA_NOT_SUPPORTED) {
                dev_err(dev, "DMA is not supported");
+               ret = -ENODEV;
                goto err_io;
        }
        pdata->coherent = (attr == DEV_DMA_COHERENT);
@@ -738,6 +739,8 @@ static int xgbe_probe(struct platform_device *pdev)
        pdata->netdev_features = netdev->features;
 
        netdev->priv_flags |= IFF_UNICAST_FLT;
+       netdev->min_mtu = 0;
+       netdev->max_mtu = XGMAC_JUMBO_PACKET_MTU;
 
        /* Use default watchdog timeout */
        netdev->watchdog_timeo = 0;
index 429f18fc5503ddede288ff0203068a56ce9df3a8..3fc7b0db952bbf404e2182da71da670f566accf1 100644 (file)
@@ -1252,7 +1252,6 @@ static const struct net_device_ops xgene_ndev_ops = {
        .ndo_start_xmit = xgene_enet_start_xmit,
        .ndo_tx_timeout = xgene_enet_timeout,
        .ndo_get_stats64 = xgene_enet_get_stats64,
-       .ndo_change_mtu = eth_change_mtu,
        .ndo_set_mac_address = xgene_enet_set_mac_address,
 };
 
@@ -1381,9 +1380,13 @@ static void xgene_enet_gpiod_get(struct xgene_enet_pdata *pdata)
 {
        struct device *dev = &pdata->pdev->dev;
 
-       if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
+       pdata->sfp_gpio_en = false;
+       if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII ||
+           (!device_property_present(dev, "sfp-gpios") &&
+            !device_property_present(dev, "rxlos-gpios")))
                return;
 
+       pdata->sfp_gpio_en = true;
        pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
        if (IS_ERR(pdata->sfp_rdy))
                pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
index 0cda58f5a840378cd5dfb338114e487ceb787e22..011965b54d1f6ad756ae79770b5c052bac56134a 100644 (file)
@@ -219,6 +219,7 @@ struct xgene_enet_pdata {
        u8 rx_delay;
        bool mdio_driver;
        struct gpio_desc *sfp_rdy;
+       bool sfp_gpio_en;
 };
 
 struct xgene_indirect_ctl {
index 6475f383ba83e253b626d4f481d7ca489a0c8a4b..d1758b072623efdf6fc1155e3705eb10b3b78772 100644 (file)
@@ -415,16 +415,31 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
        xgene_enet_wr_ring_if(pdata, addr, data);
 }
 
+static int xgene_enet_gpio_lookup(struct xgene_enet_pdata *pdata)
+{
+       struct device *dev = &pdata->pdev->dev;
+
+       pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
+       if (IS_ERR(pdata->sfp_rdy))
+               pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
+
+       if (IS_ERR(pdata->sfp_rdy))
+               return -ENODEV;
+
+       return 0;
+}
+
 static void xgene_enet_link_state(struct work_struct *work)
 {
        struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
                                         struct xgene_enet_pdata, link_work);
-       struct gpio_desc *sfp_rdy = pdata->sfp_rdy;
        struct net_device *ndev = pdata->ndev;
        u32 link_status, poll_interval;
 
        link_status = xgene_enet_link_status(pdata);
-       if (link_status && !IS_ERR(sfp_rdy) && !gpiod_get_value(sfp_rdy))
+       if (pdata->sfp_gpio_en && link_status &&
+           (!IS_ERR(pdata->sfp_rdy) || !xgene_enet_gpio_lookup(pdata)) &&
+           !gpiod_get_value(pdata->sfp_rdy))
                link_status = 0;
 
        if (link_status) {
index a65d7a60f116828dc65196d594b1d6a5ecf01a4a..2b2d87089987f9d9fbb0ddf1a4b961e56d791445 100644 (file)
@@ -1237,7 +1237,6 @@ static const struct net_device_ops bmac_netdev_ops = {
        .ndo_start_xmit         = bmac_output,
        .ndo_set_rx_mode        = bmac_set_multicast,
        .ndo_set_mac_address    = bmac_set_address,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index e58a7c73766e9db816a8d4d4dd9d1ed91e39baff..96dd5300e0e5f500844ba980099139e0487b5d20 100644 (file)
@@ -102,7 +102,6 @@ static const struct net_device_ops mace_netdev_ops = {
        .ndo_start_xmit         = mace_xmit_start,
        .ndo_set_rx_mode        = mace_set_multicast,
        .ndo_set_mac_address    = mace_set_address,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 89914ca17a490799b3fa9ec9f54ab87c7cd85a80..857df9c45f04ddc9829b83c8b2744e2306cb2224 100644 (file)
@@ -186,7 +186,6 @@ static const struct net_device_ops mace_netdev_ops = {
        .ndo_tx_timeout         = mace_tx_timeout,
        .ndo_set_rx_mode        = mace_set_multicast,
        .ndo_set_mac_address    = mace_set_address,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index b0da9693f28a130a65e59a007548c773fa422e7f..95d8b3ea7bc3bf06e4fdd3dfe654a8d727963b45 100644 (file)
@@ -633,7 +633,7 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
        if (unlikely(dma_mapping_error(&ndev->dev, addr))) {
                stats->tx_dropped++;
                stats->tx_errors++;
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
        dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], addr, addr);
index 0191477ace5174235baac09787869672437af1fa..e42d7e0947ebe940b3abfb337e6f977e07fccc00 100644 (file)
@@ -351,7 +351,6 @@ struct alx_rrd {
 #define ALX_MAX_JUMBO_PKT_SIZE (9*1024)
 #define ALX_MAX_TSO_PKT_SIZE   (7*1024)
 #define ALX_MAX_FRAME_SIZE     ALX_MAX_JUMBO_PKT_SIZE
-#define ALX_MIN_FRAME_SIZE     (ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN)
 
 #define ALX_MAX_RX_QUEUES      8
 #define ALX_MAX_TX_QUEUES      4
index c0f84b73574d8a1e4abbf0f1f470675657bdade2..eccbacd96201d00b9e7c03926aa07cb25c98badb 100644 (file)
@@ -892,6 +892,9 @@ static int alx_init_sw(struct alx_priv *alx)
        hw->smb_timer = 400;
        hw->mtu = alx->dev->mtu;
        alx->rxbuf_size = ALX_MAX_FRAME_LEN(hw->mtu);
+       /* MTU range: 34 - 9256 */
+       alx->dev->min_mtu = 34;
+       alx->dev->max_mtu = ALX_MAX_FRAME_LEN(ALX_MAX_FRAME_SIZE);
        alx->tx_ringsz = 256;
        alx->rx_ringsz = 512;
        hw->imt = 200;
@@ -994,13 +997,6 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
        struct alx_priv *alx = netdev_priv(netdev);
        int max_frame = ALX_MAX_FRAME_LEN(mtu);
 
-       if ((max_frame < ALX_MIN_FRAME_SIZE) ||
-           (max_frame > ALX_MAX_FRAME_SIZE))
-               return -EINVAL;
-
-       if (netdev->mtu == mtu)
-               return 0;
-
        netdev->mtu = mtu;
        alx->hw.mtu = mtu;
        alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE);
index a3200ea6d7656c58a4dc0fd65f572c8558dc0413..773d3b7d8dd5efeee95b14eb1df6b483b9d80311 100644 (file)
@@ -519,6 +519,26 @@ static int atl1c_set_features(struct net_device *netdev,
        return 0;
 }
 
+static void atl1c_set_max_mtu(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct atl1c_hw *hw = &adapter->hw;
+
+       switch (hw->nic_type) {
+       /* These (GbE) devices support jumbo packets, max_mtu 6122 */
+       case athr_l1c:
+       case athr_l1d:
+       case athr_l1d_2:
+               netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
+                                 (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+               break;
+       /* The 10/100 devices don't support jumbo packets, max_mtu 1500 */
+       default:
+               netdev->max_mtu = ETH_DATA_LEN;
+               break;
+       }
+}
+
 /**
  * atl1c_change_mtu - Change the Maximum Transfer Unit
  * @netdev: network interface device structure
@@ -529,22 +549,9 @@ static int atl1c_set_features(struct net_device *netdev,
 static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct atl1c_adapter *adapter = netdev_priv(netdev);
-       struct atl1c_hw *hw = &adapter->hw;
-       int old_mtu   = netdev->mtu;
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
-
-       /* Fast Ethernet controller doesn't support jumbo packet */
-       if (((hw->nic_type == athr_l2c ||
-             hw->nic_type == athr_l2c_b ||
-             hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) ||
-             max_frame < ETH_ZLEN + ETH_FCS_LEN ||
-             max_frame > MAX_JUMBO_FRAME_SIZE) {
-               if (netif_msg_link(adapter))
-                       dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
-               return -EINVAL;
-       }
+
        /* set MTU */
-       if (old_mtu != new_mtu && netif_running(netdev)) {
+       if (netif_running(netdev)) {
                while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
                        msleep(1);
                netdev->mtu = new_mtu;
@@ -2511,6 +2518,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 
        netdev->netdev_ops = &atl1c_netdev_ops;
        netdev->watchdog_timeo = AT_TX_WATCHDOG;
+       netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
        atl1c_set_ethtool_ops(netdev);
 
        /* TODO: add when ready */
@@ -2613,6 +2621,9 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                dev_err(&pdev->dev, "net device private data init failed\n");
                goto err_sw_init;
        }
+       /* set max MTU */
+       atl1c_set_max_mtu(netdev);
+
        atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE);
 
        /* Init GPHY as early as possible due to power saving issue  */
index 974713b19ab642d66e4c8c5f114739164cbd4669..e96091b652a7ec1baf42d24fc4bf674aabf308d1 100644 (file)
@@ -439,16 +439,10 @@ static int atl1e_set_features(struct net_device *netdev,
 static int atl1e_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct atl1e_adapter *adapter = netdev_priv(netdev);
-       int old_mtu   = netdev->mtu;
        int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
 
-       if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
-                       (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-               netdev_warn(adapter->netdev, "invalid MTU setting\n");
-               return -EINVAL;
-       }
        /* set MTU */
-       if (old_mtu != new_mtu && netif_running(netdev)) {
+       if (netif_running(netdev)) {
                while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
                        msleep(1);
                netdev->mtu = new_mtu;
@@ -2272,6 +2266,10 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
        netdev->netdev_ops = &atl1e_netdev_ops;
 
        netdev->watchdog_timeo = AT_TX_WATCHDOG;
+       /* MTU range: 42 - 8170 */
+       netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
+       netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
+                         (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
        atl1e_set_ethtool_ops(netdev);
 
        netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO |
index 529bca718334acd15395c020a5a0ca4c86b4154a..9aede18aa70f4470a17100e21591d303864c20b9 100644 (file)
@@ -2701,23 +2701,15 @@ static void atl1_reset_dev_task(struct work_struct *work)
 static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct atl1_adapter *adapter = netdev_priv(netdev);
-       int old_mtu = netdev->mtu;
        int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
 
-       if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
-           (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-               if (netif_msg_link(adapter))
-                       dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
-               return -EINVAL;
-       }
-
        adapter->hw.max_frame_size = max_frame;
        adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
        adapter->rx_buffer_len = (max_frame + 7) & ~7;
        adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
 
        netdev->mtu = new_mtu;
-       if ((old_mtu != new_mtu) && netif_running(netdev)) {
+       if (netif_running(netdev)) {
                atl1_down(adapter);
                atl1_up(adapter);
        }
@@ -3031,6 +3023,11 @@ static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* is this valid? see atl1_setup_mac_ctrl() */
        netdev->features |= NETIF_F_RXCSUM;
 
+       /* MTU range: 42 - 10218 */
+       netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
+       netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
+                         (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
        /*
         * patch for some L1 of old version,
         * the final version of L1 may not need these
index 2ff465848b6553ecc0a646421e30cded0e8fb053..6911394115b20e7023d89feb4d757750c50f604d 100644 (file)
@@ -253,7 +253,7 @@ static int atl2_configure(struct atl2_adapter *adapter)
 
        /* set MTU */
        ATL2_WRITE_REG(hw, REG_MTU, adapter->netdev->mtu +
-               ENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE);
+               ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
 
        /* 1590 */
        ATL2_WRITE_REG(hw, REG_TX_CUT_THRESH, 0x177);
@@ -925,15 +925,11 @@ static int atl2_change_mtu(struct net_device *netdev, int new_mtu)
        struct atl2_adapter *adapter = netdev_priv(netdev);
        struct atl2_hw *hw = &adapter->hw;
 
-       if ((new_mtu < 40) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE)))
-               return -EINVAL;
-
        /* set MTU */
-       if (hw->max_frame_size != new_mtu) {
-               netdev->mtu = new_mtu;
-               ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ENET_HEADER_SIZE +
-                       VLAN_SIZE + ETHERNET_FCS_SIZE);
-       }
+       netdev->mtu = new_mtu;
+       hw->max_frame_size = new_mtu;
+       ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ETH_HLEN +
+                      VLAN_HLEN + ETH_FCS_LEN);
 
        return 0;
 }
@@ -1398,6 +1394,8 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        netdev->netdev_ops = &atl2_netdev_ops;
        netdev->ethtool_ops = &atl2_ethtool_ops;
        netdev->watchdog_timeo = 5 * HZ;
+       netdev->min_mtu = 40;
+       netdev->max_mtu = ETH_DATA_LEN + VLAN_HLEN;
        strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
 
        netdev->mem_start = mmio_start;
index 2f27d4c4c3ad4ae5b026983dba7d9478cd1c5430..c64a6bdfa7ae4927da9dc3c38ac4ca5b8956354e 100644 (file)
@@ -228,12 +228,9 @@ static void atl2_force_ps(struct atl2_hw *hw);
 #define AUTONEG_ADVERTISE_SPEED_DEFAULT        0x000F  /* Everything */
 
 /* The size (in bytes) of a ethernet packet */
-#define ENET_HEADER_SIZE               14
 #define MAXIMUM_ETHERNET_FRAME_SIZE    1518    /* with FCS */
 #define MINIMUM_ETHERNET_FRAME_SIZE    64      /* with FCS */
-#define ETHERNET_FCS_SIZE              4
 #define MAX_JUMBO_FRAME_SIZE           0x2000
-#define VLAN_SIZE                                               4
 
 struct tx_pkt_header {
        unsigned pkt_size:11;
index 00c38bf151e6a3a721b09c284e51c15da239c0b7..b59aa3541270de552e32c818efa5cc0b585719c3 100644 (file)
@@ -975,8 +975,10 @@ static int nb8800_open(struct net_device *dev)
        phydev = of_phy_connect(dev, priv->phy_node,
                                nb8800_link_reconfigure, 0,
                                priv->phy_mode);
-       if (!phydev)
+       if (!phydev) {
+               err = -ENODEV;
                goto err_free_irq;
+       }
 
        nb8800_pause_adv(dev);
 
@@ -1032,7 +1034,6 @@ static const struct net_device_ops nb8800_netdev_ops = {
        .ndo_set_mac_address    = nb8800_set_mac_address,
        .ndo_set_rx_mode        = nb8800_set_rx_mode,
        .ndo_do_ioctl           = nb8800_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 17aa33c5567d66306a895e855fbff5486d79d5e0..1df3048a3cdb00b7322e45d95a9efa918a8aec94 100644 (file)
@@ -59,8 +59,8 @@
 #define B44_TX_TIMEOUT                 (5 * HZ)
 
 /* hardware minimum and maximum for a single frame's data payload */
-#define B44_MIN_MTU                    60
-#define B44_MAX_MTU                    1500
+#define B44_MIN_MTU                    ETH_ZLEN
+#define B44_MAX_MTU                    ETH_DATA_LEN
 
 #define B44_RX_RING_SIZE               512
 #define B44_DEF_RX_RING_PENDING                200
@@ -1064,9 +1064,6 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct b44 *bp = netdev_priv(dev);
 
-       if (new_mtu < B44_MIN_MTU || new_mtu > B44_MAX_MTU)
-               return -EINVAL;
-
        if (!netif_running(dev)) {
                /* We'll just catch it later when the
                 * device is up'd.
@@ -2377,6 +2374,8 @@ static int b44_init_one(struct ssb_device *sdev,
        dev->netdev_ops = &b44_netdev_ops;
        netif_napi_add(dev, &bp->napi, b44_poll, 64);
        dev->watchdog_timeo = B44_TX_TIMEOUT;
+       dev->min_mtu = B44_MIN_MTU;
+       dev->max_mtu = B44_MAX_MTU;
        dev->irq = sdev->irq;
        dev->ethtool_ops = &b44_ethtool_ops;
 
index 537090952c45494bfedbd5ae7b374ad54af46681..5c7acef1de2e380beb31c8cc503e35d59db46b63 100644 (file)
@@ -1623,20 +1623,19 @@ static int bcm_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 }
 
 /*
- * calculate actual hardware mtu
+ * adjust mtu, can't be called while device is running
  */
-static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu)
+static int bcm_enet_change_mtu(struct net_device *dev, int new_mtu)
 {
-       int actual_mtu;
+       struct bcm_enet_priv *priv = netdev_priv(dev);
+       int actual_mtu = new_mtu;
 
-       actual_mtu = mtu;
+       if (netif_running(dev))
+               return -EBUSY;
 
        /* add ethernet header + vlan tag size */
        actual_mtu += VLAN_ETH_HLEN;
 
-       if (actual_mtu < 64 || actual_mtu > BCMENET_MAX_MTU)
-               return -EINVAL;
-
        /*
         * setup maximum size before we get overflow mark in
         * descriptor, note that this will not prevent reception of
@@ -1651,22 +1650,7 @@ static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu)
         */
        priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
                                  priv->dma_maxburst * 4);
-       return 0;
-}
 
-/*
- * adjust mtu, can't be called while device is running
- */
-static int bcm_enet_change_mtu(struct net_device *dev, int new_mtu)
-{
-       int ret;
-
-       if (netif_running(dev))
-               return -EBUSY;
-
-       ret = compute_hw_mtu(netdev_priv(dev), new_mtu);
-       if (ret)
-               return ret;
        dev->mtu = new_mtu;
        return 0;
 }
@@ -1756,7 +1740,7 @@ static int bcm_enet_probe(struct platform_device *pdev)
        priv->enet_is_sw = false;
        priv->dma_maxburst = BCMENET_DMA_MAXBURST;
 
-       ret = compute_hw_mtu(priv, dev->mtu);
+       ret = bcm_enet_change_mtu(dev, dev->mtu);
        if (ret)
                goto out;
 
@@ -1889,6 +1873,9 @@ static int bcm_enet_probe(struct platform_device *pdev)
        netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
 
        dev->ethtool_ops = &bcm_enet_ethtool_ops;
+       /* MTU range: 46 - 2028 */
+       dev->min_mtu = ETH_ZLEN - ETH_HLEN;
+       dev->max_mtu = BCMENET_MAX_MTU - VLAN_ETH_HLEN;
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        ret = register_netdev(dev);
@@ -2743,7 +2730,7 @@ static int bcm_enetsw_probe(struct platform_device *pdev)
                priv->dma_chan_width = pd->dma_chan_width;
        }
 
-       ret = compute_hw_mtu(priv, dev->mtu);
+       ret = bcm_enet_change_mtu(dev, dev->mtu);
        if (ret)
                goto out;
 
index b3791b394715d201da29ba5fb8bd18ba78ab9f40..eab49ff4eecd1c2bf6842177492ee62dd5210a59 100644 (file)
@@ -2303,7 +2303,7 @@ bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy)
        if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
                BNX2_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
 
-       if (bp->dev->mtu > 1500) {
+       if (bp->dev->mtu > ETH_DATA_LEN) {
                u32 val;
 
                /* Set extended packet length bit */
@@ -2357,7 +2357,7 @@ bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy)
                bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val);
        }
 
-       if (bp->dev->mtu > 1500) {
+       if (bp->dev->mtu > ETH_DATA_LEN) {
                /* Set extended packet length bit */
                bnx2_write_phy(bp, 0x18, 0x7);
                bnx2_read_phy(bp, 0x18, &val);
@@ -4990,12 +4990,12 @@ bnx2_init_chip(struct bnx2 *bp)
        /* Program the MTU.  Also include 4 bytes for CRC32. */
        mtu = bp->dev->mtu;
        val = mtu + ETH_HLEN + ETH_FCS_LEN;
-       if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
+       if (val > (MAX_ETHERNET_PACKET_SIZE + ETH_HLEN + 4))
                val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
        BNX2_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
 
-       if (mtu < 1500)
-               mtu = 1500;
+       if (mtu < ETH_DATA_LEN)
+               mtu = ETH_DATA_LEN;
 
        bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG, BNX2_RBUF_CONFIG_VAL(mtu));
        bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG2, BNX2_RBUF_CONFIG2_VAL(mtu));
@@ -7901,10 +7901,6 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct bnx2 *bp = netdev_priv(dev);
 
-       if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
-               ((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE))
-               return -EINVAL;
-
        dev->mtu = new_mtu;
        return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size,
                                     false);
@@ -8594,6 +8590,8 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
        dev->features |= dev->hw_features;
        dev->priv_flags |= IFF_UNICAST_FLT;
+       dev->min_mtu = MIN_ETHERNET_PACKET_SIZE;
+       dev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE;
 
        if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
                dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
index 380234d72b958666a3782780cd32bd15707016b1..a09ec47461c903e038f6e3526ceb36e446fa9df0 100644 (file)
@@ -6530,9 +6530,9 @@ struct l2_fhdr {
 #define MII_BNX2_AER_AER_AN_MMD                           0x3800
 #define MII_BNX2_BLK_ADDR_COMBO_IEEEB0          0xffe0
 
-#define MIN_ETHERNET_PACKET_SIZE       60
-#define MAX_ETHERNET_PACKET_SIZE       1514
-#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
+#define MIN_ETHERNET_PACKET_SIZE       (ETH_ZLEN - ETH_HLEN)
+#define MAX_ETHERNET_PACKET_SIZE       ETH_DATA_LEN
+#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9000
 
 #define BNX2_RX_COPY_THRESH            128
 
index 7dd7490fdac1fd1d8429bfcf90fa5a2147769d37..0a23034bbe3ff8d392483e7a5a201caf30c76526 100644 (file)
@@ -1396,9 +1396,9 @@ struct bnx2x {
        int                     tx_ring_size;
 
 /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
-#define ETH_OVREHEAD           (ETH_HLEN + 8 + 8)
-#define ETH_MIN_PACKET_SIZE            60
-#define ETH_MAX_PACKET_SIZE            1500
+#define ETH_OVERHEAD           (ETH_HLEN + 8 + 8)
+#define ETH_MIN_PACKET_SIZE            (ETH_ZLEN - ETH_HLEN)
+#define ETH_MAX_PACKET_SIZE            ETH_DATA_LEN
 #define ETH_MAX_JUMBO_PACKET_SIZE      9600
 /* TCP with Timestamp Option (32) + IPv6 (40) */
 #define ETH_MAX_TPA_HEADER_SIZE                72
index 0a9108cd4c4583e397cbc51d2aace18a8d96fb16..ed42c100968551525fd393212cfb68ed1723e9c0 100644 (file)
@@ -2023,7 +2023,7 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
                        mtu = bp->dev->mtu;
                fp->rx_buf_size = BNX2X_FW_RX_ALIGN_START +
                                  IP_HEADER_ALIGNMENT_PADDING +
-                                 ETH_OVREHEAD +
+                                 ETH_OVERHEAD +
                                  mtu +
                                  BNX2X_FW_RX_ALIGN_END;
                /* Note : rx_buf_size doesn't take into account NET_SKB_PAD */
@@ -4855,12 +4855,6 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
                return -EAGAIN;
        }
 
-       if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) ||
-           ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) {
-               BNX2X_ERR("Can't support requested MTU size\n");
-               return -EINVAL;
-       }
-
        /* This does not race with packet allocation
         * because the actual alloc size is
         * only updated as part of load
index 1fb80100e5e7d753b2ddd8ae741e0120ac161f42..05356efdbf93ee59690a403f34ee3a4765f76890 100644 (file)
@@ -34,12 +34,6 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,
                                             u8 dev_addr, u16 addr, u8 byte_cnt,
                                             u8 *o_buf, u8);
 /********************************************************/
-#define ETH_HLEN                       14
-/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
-#define ETH_OVREHEAD                   (ETH_HLEN + 8 + 8)
-#define ETH_MIN_PACKET_SIZE            60
-#define ETH_MAX_PACKET_SIZE            1500
-#define ETH_MAX_JUMBO_PACKET_SIZE      9600
 #define MDIO_ACCESS_TIMEOUT            1000
 #define WC_LANE_MAX                    4
 #define I2C_SWITCH_WIDTH               2
@@ -1917,7 +1911,7 @@ static int bnx2x_emac_enable(struct link_params *params,
        /* Enable emac for jumbo packets */
        EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
                (EMAC_RX_MTU_SIZE_JUMBO_ENA |
-                (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
+                (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD)));
 
        /* Strip CRC */
        REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
@@ -2314,19 +2308,19 @@ static int bnx2x_bmac1_enable(struct link_params *params,
        REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, wb_data, 2);
 
        /* Set rx mtu */
-       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
        wb_data[1] = 0;
        REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE, wb_data, 2);
 
        bnx2x_update_pfc_bmac1(params, vars);
 
        /* Set tx mtu */
-       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
        wb_data[1] = 0;
        REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE, wb_data, 2);
 
        /* Set cnt max size */
-       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
        wb_data[1] = 0;
        REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2);
 
@@ -2384,18 +2378,18 @@ static int bnx2x_bmac2_enable(struct link_params *params,
        udelay(30);
 
        /* Set RX MTU */
-       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
        wb_data[1] = 0;
        REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE, wb_data, 2);
        udelay(30);
 
        /* Set TX MTU */
-       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
        wb_data[1] = 0;
        REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE, wb_data, 2);
        udelay(30);
        /* Set cnt max size */
-       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD - 2;
+       wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD - 2;
        wb_data[1] = 0;
        REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE, wb_data, 2);
        udelay(30);
@@ -2516,7 +2510,7 @@ static int bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
 
        } else {
                u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
-                             ETH_OVREHEAD)/16;
+                             ETH_OVERHEAD)/16;
                REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
                /* Update threshold */
                REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
index 0cee4c0283f9b35a4d56cff5936d4e541c7da4e5..ab990da677d56a798bc93c6d1db6ee8418b2777e 100644 (file)
@@ -12080,8 +12080,7 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
                                           mtu_size, mtu);
 
                                        /* if valid: update device mtu */
-                                       if (((mtu_size + ETH_HLEN) >=
-                                            ETH_MIN_PACKET_SIZE) &&
+                                       if ((mtu_size >= ETH_MIN_PACKET_SIZE) &&
                                            (mtu_size <=
                                             ETH_MAX_JUMBO_PACKET_SIZE))
                                                bp->dev->mtu = mtu_size;
@@ -13315,6 +13314,10 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
        dev->dcbnl_ops = &bnx2x_dcbnl_ops;
 #endif
 
+       /* MTU range, 46 - 9600 */
+       dev->min_mtu = ETH_MIN_PACKET_SIZE;
+       dev->max_mtu = ETH_MAX_JUMBO_PACKET_SIZE;
+
        /* get_port_hwinfo() will set prtad and mmds properly */
        bp->mdio.prtad = MDIO_PRTAD_NONE;
        bp->mdio.mmds = 0;
index a9f9f3738022a708b0020659d30d2aafacc12cf6..a042da1ff4b90e9aae4f76db71c99c2c4da321d3 100644 (file)
@@ -6290,9 +6290,6 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct bnxt *bp = netdev_priv(dev);
 
-       if (new_mtu < 60 || new_mtu > 9500)
-               return -EINVAL;
-
        if (netif_running(dev))
                bnxt_close_nic(bp, false, false);
 
@@ -6870,6 +6867,10 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
        dev->priv_flags |= IFF_UNICAST_FLT;
 
+       /* MTU range: 60 - 9500 */
+       dev->min_mtu = ETH_ZLEN;
+       dev->max_mtu = 9500;
+
 #ifdef CONFIG_BNXT_SRIOV
        init_waitqueue_head(&bp->sriov_cfg_wait);
 #endif
index f1b81187a20101eca9d491a61c08bf1e4e7af30c..435a2e4739d16d721918b55cc54c855fd3f50a56 100644 (file)
@@ -2147,15 +2147,6 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
        }
 }
 
-static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
-{
-       if (new_mtu >  ENET_PACKET_SIZE)
-               return -EINVAL;
-       _dev->mtu = new_mtu;
-       pr_info("changing the mtu to %d\n", new_mtu);
-       return 0;
-}
-
 static const struct net_device_ops sbmac_netdev_ops = {
        .ndo_open               = sbmac_open,
        .ndo_stop               = sbmac_close,
@@ -2163,7 +2154,6 @@ static const struct net_device_ops sbmac_netdev_ops = {
        .ndo_set_rx_mode        = sbmac_set_rx_mode,
        .ndo_tx_timeout         = sbmac_tx_timeout,
        .ndo_do_ioctl           = sbmac_mii_ioctl,
-       .ndo_change_mtu         = sb1250_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2229,6 +2219,8 @@ static int sbmac_init(struct platform_device *pldev, long long base)
 
        dev->netdev_ops = &sbmac_netdev_ops;
        dev->watchdog_timeo = TX_TIMEOUT;
+       dev->min_mtu = 0;
+       dev->max_mtu = ENET_PACKET_SIZE;
 
        netif_napi_add(dev, &sc->napi, sbmac_poll, 16);
 
index a927a730da10a7a3ef45669740b382e2231410ed..185e9e047aa9adda61ac602caea5f59c3efe2d7e 100644 (file)
@@ -124,7 +124,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 #define TG3_TX_TIMEOUT                 (5 * HZ)
 
 /* hardware minimum and maximum for a single frame's data payload */
-#define TG3_MIN_MTU                    60
+#define TG3_MIN_MTU                    ETH_ZLEN
 #define TG3_MAX_MTU(tp)        \
        (tg3_flag(tp, JUMBO_CAPABLE) ? 9000 : 1500)
 
@@ -14199,9 +14199,6 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
        int err;
        bool reset_phy = false;
 
-       if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
-               return -EINVAL;
-
        if (!netif_running(dev)) {
                /* We'll just catch it later when the
                 * device is up'd.
@@ -17799,6 +17796,10 @@ static int tg3_init_one(struct pci_dev *pdev,
        dev->hw_features |= features;
        dev->priv_flags |= IFF_UNICAST_FLT;
 
+       /* MTU range: 60 - 9000 or 1500, depending on hardware */
+       dev->min_mtu = TG3_MIN_MTU;
+       dev->max_mtu = TG3_MAX_MTU(tp);
+
        if (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A1 &&
            !tg3_flag(tp, TSO_CAPABLE) &&
            !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) {
index f9df4b5ae90e091d7bd440e16d87ef404ab1ba80..b200a783443eb983a87a617cf7620b2227430107 100644 (file)
@@ -3296,9 +3296,6 @@ bnad_change_mtu(struct net_device *netdev, int new_mtu)
        struct bnad *bnad = netdev_priv(netdev);
        u32 rx_count = 0, frame, new_frame;
 
-       if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU)
-               return -EINVAL;
-
        mutex_lock(&bnad->conf_mutex);
 
        mtu = netdev->mtu;
@@ -3465,6 +3462,10 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac)
        netdev->mem_start = bnad->mmio_start;
        netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1;
 
+       /* MTU range: 46 - 9000 */
+       netdev->min_mtu = ETH_ZLEN - ETH_HLEN;
+       netdev->max_mtu = BNAD_JUMBO_MTU;
+
        netdev->netdev_ops = &bnad_netdev_ops;
        bnad_set_ethtool_ops(netdev);
 }
index b32444a3ed79d311fc4047aa10eabc5f630b66cb..e1847ce6308deba39998fcdd81e9d3d272a23873 100644 (file)
 
 #define MACB_RX_BUFFER_SIZE    128
 #define RX_BUFFER_MULTIPLE     64  /* bytes */
-#define RX_RING_SIZE           512 /* must be power of 2 */
-#define RX_RING_BYTES          (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
 
-#define TX_RING_SIZE           128 /* must be power of 2 */
-#define TX_RING_BYTES          (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
+#define DEFAULT_RX_RING_SIZE   512 /* must be power of 2 */
+#define MIN_RX_RING_SIZE       64
+#define MAX_RX_RING_SIZE       8192
+#define RX_RING_BYTES(bp)      (sizeof(struct macb_dma_desc)   \
+                                * (bp)->rx_ring_size)
+
+#define DEFAULT_TX_RING_SIZE   512 /* must be power of 2 */
+#define MIN_TX_RING_SIZE       64
+#define MAX_TX_RING_SIZE       4096
+#define TX_RING_BYTES(bp)      (sizeof(struct macb_dma_desc)   \
+                                * (bp)->tx_ring_size)
 
 /* level of occupied TX descriptors under which we wake up TX process */
-#define MACB_TX_WAKEUP_THRESH  (3 * TX_RING_SIZE / 4)
+#define MACB_TX_WAKEUP_THRESH(bp)      (3 * (bp)->tx_ring_size / 4)
 
 #define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(RXUBR)      \
                                 | MACB_BIT(ISR_ROVR))
@@ -56,7 +63,7 @@
 #define MACB_MAX_TX_LEN                ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1))
 #define GEM_MAX_TX_LEN         ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1))
 
-#define GEM_MTU_MIN_SIZE       68
+#define GEM_MTU_MIN_SIZE       ETH_MIN_MTU
 
 #define MACB_WOL_HAS_MAGIC_PACKET      (0x1 << 0)
 #define MACB_WOL_ENABLED               (0x1 << 1)
 #define MACB_HALT_TIMEOUT      1230
 
 /* Ring buffer accessors */
-static unsigned int macb_tx_ring_wrap(unsigned int index)
+static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
 {
-       return index & (TX_RING_SIZE - 1);
+       return index & (bp->tx_ring_size - 1);
 }
 
 static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue,
                                          unsigned int index)
 {
-       return &queue->tx_ring[macb_tx_ring_wrap(index)];
+       return &queue->tx_ring[macb_tx_ring_wrap(queue->bp, index)];
 }
 
 static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue,
                                       unsigned int index)
 {
-       return &queue->tx_skb[macb_tx_ring_wrap(index)];
+       return &queue->tx_skb[macb_tx_ring_wrap(queue->bp, index)];
 }
 
 static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index)
 {
        dma_addr_t offset;
 
-       offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc);
+       offset = macb_tx_ring_wrap(queue->bp, index) *
+                sizeof(struct macb_dma_desc);
 
        return queue->tx_ring_dma + offset;
 }
 
-static unsigned int macb_rx_ring_wrap(unsigned int index)
+static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index)
 {
-       return index & (RX_RING_SIZE - 1);
+       return index & (bp->rx_ring_size - 1);
 }
 
 static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
 {
-       return &bp->rx_ring[macb_rx_ring_wrap(index)];
+       return &bp->rx_ring[macb_rx_ring_wrap(bp, index)];
 }
 
 static void *macb_rx_buffer(struct macb *bp, unsigned int index)
 {
-       return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index);
+       return bp->rx_buffers + bp->rx_buffer_size *
+              macb_rx_ring_wrap(bp, index);
 }
 
 /* I/O accessors */
@@ -608,7 +617,8 @@ static void macb_tx_error_task(struct work_struct *work)
                         */
                        if (!(ctrl & MACB_BIT(TX_BUF_EXHAUSTED))) {
                                netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
-                                           macb_tx_ring_wrap(tail), skb->data);
+                                           macb_tx_ring_wrap(bp, tail),
+                                           skb->data);
                                bp->stats.tx_packets++;
                                bp->stats.tx_bytes += skb->len;
                        }
@@ -700,7 +710,8 @@ static void macb_tx_interrupt(struct macb_queue *queue)
                        /* First, update TX stats if needed */
                        if (skb) {
                                netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
-                                           macb_tx_ring_wrap(tail), skb->data);
+                                           macb_tx_ring_wrap(bp, tail),
+                                           skb->data);
                                bp->stats.tx_packets++;
                                bp->stats.tx_bytes += skb->len;
                        }
@@ -720,7 +731,7 @@ static void macb_tx_interrupt(struct macb_queue *queue)
        queue->tx_tail = tail;
        if (__netif_subqueue_stopped(bp->dev, queue_index) &&
            CIRC_CNT(queue->tx_head, queue->tx_tail,
-                    TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH)
+                    bp->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp))
                netif_wake_subqueue(bp->dev, queue_index);
 }
 
@@ -731,8 +742,8 @@ static void gem_rx_refill(struct macb *bp)
        dma_addr_t              paddr;
 
        while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail,
-                         RX_RING_SIZE) > 0) {
-               entry = macb_rx_ring_wrap(bp->rx_prepared_head);
+                         bp->rx_ring_size) > 0) {
+               entry = macb_rx_ring_wrap(bp, bp->rx_prepared_head);
 
                /* Make hw descriptor updates visible to CPU */
                rmb();
@@ -759,7 +770,7 @@ static void gem_rx_refill(struct macb *bp)
 
                        bp->rx_skbuff[entry] = skb;
 
-                       if (entry == RX_RING_SIZE - 1)
+                       if (entry == bp->rx_ring_size - 1)
                                paddr |= MACB_BIT(RX_WRAP);
                        macb_set_addr(&(bp->rx_ring[entry]), paddr);
                        bp->rx_ring[entry].ctrl = 0;
@@ -813,7 +824,7 @@ static int gem_rx(struct macb *bp, int budget)
                dma_addr_t addr;
                bool rxused;
 
-               entry = macb_rx_ring_wrap(bp->rx_tail);
+               entry = macb_rx_ring_wrap(bp, bp->rx_tail);
                desc = &bp->rx_ring[entry];
 
                /* Make hw descriptor updates visible to CPU */
@@ -895,8 +906,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
        len = desc->ctrl & bp->rx_frm_len_mask;
 
        netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
-                   macb_rx_ring_wrap(first_frag),
-                   macb_rx_ring_wrap(last_frag), len);
+               macb_rx_ring_wrap(bp, first_frag),
+               macb_rx_ring_wrap(bp, last_frag), len);
 
        /* The ethernet header starts NET_IP_ALIGN bytes into the
         * first buffer. Since the header is 14 bytes, this makes the
@@ -969,12 +980,12 @@ static inline void macb_init_rx_ring(struct macb *bp)
        int i;
 
        addr = bp->rx_buffers_dma;
-       for (i = 0; i < RX_RING_SIZE; i++) {
+       for (i = 0; i < bp->rx_ring_size; i++) {
                bp->rx_ring[i].addr = addr;
                bp->rx_ring[i].ctrl = 0;
                addr += bp->rx_buffer_size;
        }
-       bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
+       bp->rx_ring[bp->rx_ring_size - 1].addr |= MACB_BIT(RX_WRAP);
 }
 
 static int macb_rx(struct macb *bp, int budget)
@@ -1228,7 +1239,7 @@ static unsigned int macb_tx_map(struct macb *bp,
        offset = 0;
        while (len) {
                size = min(len, bp->max_tx_length);
-               entry = macb_tx_ring_wrap(tx_head);
+               entry = macb_tx_ring_wrap(bp, tx_head);
                tx_skb = &queue->tx_skb[entry];
 
                mapping = dma_map_single(&bp->pdev->dev,
@@ -1257,7 +1268,7 @@ static unsigned int macb_tx_map(struct macb *bp,
                offset = 0;
                while (len) {
                        size = min(len, bp->max_tx_length);
-                       entry = macb_tx_ring_wrap(tx_head);
+                       entry = macb_tx_ring_wrap(bp, tx_head);
                        tx_skb = &queue->tx_skb[entry];
 
                        mapping = skb_frag_dma_map(&bp->pdev->dev, frag,
@@ -1295,14 +1306,14 @@ static unsigned int macb_tx_map(struct macb *bp,
         * to set the end of TX queue
         */
        i = tx_head;
-       entry = macb_tx_ring_wrap(i);
+       entry = macb_tx_ring_wrap(bp, i);
        ctrl = MACB_BIT(TX_USED);
        desc = &queue->tx_ring[entry];
        desc->ctrl = ctrl;
 
        do {
                i--;
-               entry = macb_tx_ring_wrap(i);
+               entry = macb_tx_ring_wrap(bp, i);
                tx_skb = &queue->tx_skb[entry];
                desc = &queue->tx_ring[entry];
 
@@ -1311,7 +1322,7 @@ static unsigned int macb_tx_map(struct macb *bp,
                        ctrl |= MACB_BIT(TX_LAST);
                        eof = 0;
                }
-               if (unlikely(entry == (TX_RING_SIZE - 1)))
+               if (unlikely(entry == (bp->tx_ring_size - 1)))
                        ctrl |= MACB_BIT(TX_WRAP);
 
                /* Set TX buffer descriptor */
@@ -1388,7 +1399,8 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        spin_lock_irqsave(&bp->lock, flags);
 
        /* This is a hard error, log it. */
-       if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < count) {
+       if (CIRC_SPACE(queue->tx_head, queue->tx_tail,
+                      bp->tx_ring_size) < count) {
                netif_stop_subqueue(dev, queue_index);
                spin_unlock_irqrestore(&bp->lock, flags);
                netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n",
@@ -1414,7 +1426,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 
-       if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < 1)
+       if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1)
                netif_stop_subqueue(dev, queue_index);
 
 unlock:
@@ -1453,7 +1465,7 @@ static void gem_free_rx_buffers(struct macb *bp)
        if (!bp->rx_skbuff)
                return;
 
-       for (i = 0; i < RX_RING_SIZE; i++) {
+       for (i = 0; i < bp->rx_ring_size; i++) {
                skb = bp->rx_skbuff[i];
 
                if (!skb)
@@ -1478,7 +1490,7 @@ static void macb_free_rx_buffers(struct macb *bp)
 {
        if (bp->rx_buffers) {
                dma_free_coherent(&bp->pdev->dev,
-                                 RX_RING_SIZE * bp->rx_buffer_size,
+                                 bp->rx_ring_size * bp->rx_buffer_size,
                                  bp->rx_buffers, bp->rx_buffers_dma);
                bp->rx_buffers = NULL;
        }
@@ -1491,7 +1503,7 @@ static void macb_free_consistent(struct macb *bp)
 
        bp->macbgem_ops.mog_free_rx_buffers(bp);
        if (bp->rx_ring) {
-               dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES,
+               dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES(bp),
                                  bp->rx_ring, bp->rx_ring_dma);
                bp->rx_ring = NULL;
        }
@@ -1500,7 +1512,7 @@ static void macb_free_consistent(struct macb *bp)
                kfree(queue->tx_skb);
                queue->tx_skb = NULL;
                if (queue->tx_ring) {
-                       dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES,
+                       dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES(bp),
                                          queue->tx_ring, queue->tx_ring_dma);
                        queue->tx_ring = NULL;
                }
@@ -1511,14 +1523,14 @@ static int gem_alloc_rx_buffers(struct macb *bp)
 {
        int size;
 
-       size = RX_RING_SIZE * sizeof(struct sk_buff *);
+       size = bp->rx_ring_size * sizeof(struct sk_buff *);
        bp->rx_skbuff = kzalloc(size, GFP_KERNEL);
        if (!bp->rx_skbuff)
                return -ENOMEM;
-
-       netdev_dbg(bp->dev,
-                  "Allocated %d RX struct sk_buff entries at %p\n",
-                  RX_RING_SIZE, bp->rx_skbuff);
+       else
+               netdev_dbg(bp->dev,
+                          "Allocated %d RX struct sk_buff entries at %p\n",
+                          bp->rx_ring_size, bp->rx_skbuff);
        return 0;
 }
 
@@ -1526,7 +1538,7 @@ static int macb_alloc_rx_buffers(struct macb *bp)
 {
        int size;
 
-       size = RX_RING_SIZE * bp->rx_buffer_size;
+       size = bp->rx_ring_size * bp->rx_buffer_size;
        bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
                                            &bp->rx_buffers_dma, GFP_KERNEL);
        if (!bp->rx_buffers)
@@ -1545,7 +1557,7 @@ static int macb_alloc_consistent(struct macb *bp)
        int size;
 
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-               size = TX_RING_BYTES;
+               size = TX_RING_BYTES(bp);
                queue->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
                                                    &queue->tx_ring_dma,
                                                    GFP_KERNEL);
@@ -1556,13 +1568,13 @@ static int macb_alloc_consistent(struct macb *bp)
                           q, size, (unsigned long)queue->tx_ring_dma,
                           queue->tx_ring);
 
-               size = TX_RING_SIZE * sizeof(struct macb_tx_skb);
+               size = bp->tx_ring_size * sizeof(struct macb_tx_skb);
                queue->tx_skb = kmalloc(size, GFP_KERNEL);
                if (!queue->tx_skb)
                        goto out_err;
        }
 
-       size = RX_RING_BYTES;
+       size = RX_RING_BYTES(bp);
        bp->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
                                         &bp->rx_ring_dma, GFP_KERNEL);
        if (!bp->rx_ring)
@@ -1588,11 +1600,11 @@ static void gem_init_rings(struct macb *bp)
        int i;
 
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-               for (i = 0; i < TX_RING_SIZE; i++) {
-                       macb_set_addr(&(queue->tx_ring[i]), 0);
+               for (i = 0; i < bp->tx_ring_size; i++) {
+                       queue->tx_ring[i].addr = 0;
                        queue->tx_ring[i].ctrl = MACB_BIT(TX_USED);
                }
-               queue->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+               queue->tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
                queue->tx_head = 0;
                queue->tx_tail = 0;
        }
@@ -1609,13 +1621,13 @@ static void macb_init_rings(struct macb *bp)
 
        macb_init_rx_ring(bp);
 
-       for (i = 0; i < TX_RING_SIZE; i++) {
+       for (i = 0; i < bp->tx_ring_size; i++) {
                bp->queues[0].tx_ring[i].addr = 0;
                bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED);
        }
        bp->queues[0].tx_head = 0;
        bp->queues[0].tx_tail = 0;
-       bp->queues[0].tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+       bp->queues[0].tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
 
        bp->rx_tail = 0;
 }
@@ -1986,19 +1998,9 @@ static int macb_close(struct net_device *dev)
 
 static int macb_change_mtu(struct net_device *dev, int new_mtu)
 {
-       struct macb *bp = netdev_priv(dev);
-       u32 max_mtu;
-
        if (netif_running(dev))
                return -EBUSY;
 
-       max_mtu = ETH_DATA_LEN;
-       if (bp->caps & MACB_CAPS_JUMBO)
-               max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN;
-
-       if ((new_mtu > max_mtu) || (new_mtu < GEM_MTU_MIN_SIZE))
-               return -EINVAL;
-
        dev->mtu = new_mtu;
 
        return 0;
@@ -2158,8 +2160,8 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
        regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1))
                        | MACB_GREGS_VERSION;
 
-       tail = macb_tx_ring_wrap(bp->queues[0].tx_tail);
-       head = macb_tx_ring_wrap(bp->queues[0].tx_head);
+       tail = macb_tx_ring_wrap(bp, bp->queues[0].tx_tail);
+       head = macb_tx_ring_wrap(bp, bp->queues[0].tx_head);
 
        regs_buff[0]  = macb_readl(bp, NCR);
        regs_buff[1]  = macb_or_gem_readl(bp, NCFGR);
@@ -2214,6 +2216,56 @@ static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        return 0;
 }
 
+static void macb_get_ringparam(struct net_device *netdev,
+                              struct ethtool_ringparam *ring)
+{
+       struct macb *bp = netdev_priv(netdev);
+
+       ring->rx_max_pending = MAX_RX_RING_SIZE;
+       ring->tx_max_pending = MAX_TX_RING_SIZE;
+
+       ring->rx_pending = bp->rx_ring_size;
+       ring->tx_pending = bp->tx_ring_size;
+}
+
+static int macb_set_ringparam(struct net_device *netdev,
+                             struct ethtool_ringparam *ring)
+{
+       struct macb *bp = netdev_priv(netdev);
+       u32 new_rx_size, new_tx_size;
+       unsigned int reset = 0;
+
+       if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+               return -EINVAL;
+
+       new_rx_size = clamp_t(u32, ring->rx_pending,
+                             MIN_RX_RING_SIZE, MAX_RX_RING_SIZE);
+       new_rx_size = roundup_pow_of_two(new_rx_size);
+
+       new_tx_size = clamp_t(u32, ring->tx_pending,
+                             MIN_TX_RING_SIZE, MAX_TX_RING_SIZE);
+       new_tx_size = roundup_pow_of_two(new_tx_size);
+
+       if ((new_tx_size == bp->tx_ring_size) &&
+           (new_rx_size == bp->rx_ring_size)) {
+               /* nothing to do */
+               return 0;
+       }
+
+       if (netif_running(bp->dev)) {
+               reset = 1;
+               macb_close(bp->dev);
+       }
+
+       bp->rx_ring_size = new_rx_size;
+       bp->tx_ring_size = new_tx_size;
+
+       if (reset)
+               macb_open(bp->dev);
+
+       return 0;
+}
+
 static const struct ethtool_ops macb_ethtool_ops = {
        .get_regs_len           = macb_get_regs_len,
        .get_regs               = macb_get_regs,
@@ -2223,6 +2275,8 @@ static const struct ethtool_ops macb_ethtool_ops = {
        .set_wol                = macb_set_wol,
        .get_link_ksettings     = phy_ethtool_get_link_ksettings,
        .set_link_ksettings     = phy_ethtool_set_link_ksettings,
+       .get_ringparam          = macb_get_ringparam,
+       .set_ringparam          = macb_set_ringparam,
 };
 
 static const struct ethtool_ops gem_ethtool_ops = {
@@ -2235,6 +2289,8 @@ static const struct ethtool_ops gem_ethtool_ops = {
        .get_sset_count         = gem_get_sset_count,
        .get_link_ksettings     = phy_ethtool_get_link_ksettings,
        .set_link_ksettings     = phy_ethtool_set_link_ksettings,
+       .get_ringparam          = macb_get_ringparam,
+       .set_ringparam          = macb_set_ringparam,
 };
 
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2429,6 +2485,9 @@ static int macb_init(struct platform_device *pdev)
        int err;
        u32 val;
 
+       bp->tx_ring_size = DEFAULT_TX_RING_SIZE;
+       bp->rx_ring_size = DEFAULT_RX_RING_SIZE;
+
        /* set the queue register mapping once for all: queue0 has a special
         * register mapping but we don't want to test the queue index then
         * compute the corresponding register offset at run time.
@@ -2793,7 +2852,6 @@ static const struct net_device_ops at91ether_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_do_ioctl           = macb_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = at91ether_poll_controller,
 #endif
@@ -3028,6 +3086,13 @@ static int macb_probe(struct platform_device *pdev)
                goto err_out_free_netdev;
        }
 
+       /* MTU range: 68 - 1500 or 10240 */
+       dev->min_mtu = GEM_MTU_MIN_SIZE;
+       if (bp->caps & MACB_CAPS_JUMBO)
+               dev->max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN;
+       else
+               dev->max_mtu = ETH_DATA_LEN;
+
        mac = of_get_mac_address(np);
        if (mac)
                ether_addr_copy(bp->dev->dev_addr, mac);
index 8bed4b52fef52f0c3a0b9275822c06abd31d648e..1216950c97d15233761c3392f4b4229d6c6068fa 100644 (file)
@@ -811,6 +811,9 @@ struct macb {
        void                    *rx_buffers;
        size_t                  rx_buffer_size;
 
+       unsigned int            rx_ring_size;
+       unsigned int            tx_ring_size;
+
        unsigned int            num_queues;
        unsigned int            queue_mask;
        struct macb_queue       queues[MACB_MAX_QUEUES];
index 63efa0dc45ba61b11f8e1a245513485412e50027..6e723662ee69a526c33d6cfbcd40fc4851193fe3 100644 (file)
@@ -394,7 +394,7 @@ struct xgmac_priv {
 };
 
 /* XGMAC Configuration Settings */
-#define MAX_MTU                        9000
+#define XGMAC_MAX_MTU          9000
 #define PAUSE_TIME             0x400
 
 #define DMA_RX_RING_SZ         256
@@ -1360,20 +1360,6 @@ out:
  */
 static int xgmac_change_mtu(struct net_device *dev, int new_mtu)
 {
-       struct xgmac_priv *priv = netdev_priv(dev);
-       int old_mtu;
-
-       if ((new_mtu < 46) || (new_mtu > MAX_MTU)) {
-               netdev_err(priv->dev, "invalid MTU, max MTU is: %d\n", MAX_MTU);
-               return -EINVAL;
-       }
-
-       old_mtu = dev->mtu;
-
-       /* return early if the buffer sizes will not change */
-       if (old_mtu == new_mtu)
-               return 0;
-
        /* Stop everything, get ready to change the MTU */
        if (!netif_running(dev))
                return 0;
@@ -1804,6 +1790,10 @@ static int xgmac_probe(struct platform_device *pdev)
        ndev->features |= ndev->hw_features;
        ndev->priv_flags |= IFF_UNICAST_FLT;
 
+       /* MTU range: 46 - 9000 */
+       ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
+       ndev->max_mtu = XGMAC_MAX_MTU;
+
        /* Get the MAC address */
        xgmac_get_mac_addr(priv->base, ndev->dev_addr, 0);
        if (!is_valid_ether_addr(ndev->dev_addr))
index afc6f9dc8119630bae6ad8877443f98b2f5e74da..71d01a77896d427cc0faa12af5eba24562eeffb9 100644 (file)
@@ -2868,17 +2868,6 @@ static int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
        struct octnic_ctrl_pkt nctrl;
        int ret = 0;
 
-       /* Limit the MTU to make sure the ethernet packets are between 68 bytes
-        * and 16000 bytes
-        */
-       if ((new_mtu < LIO_MIN_MTU_SIZE) ||
-           (new_mtu > LIO_MAX_MTU_SIZE)) {
-               dev_err(&oct->pci_dev->dev, "Invalid MTU: %d\n", new_mtu);
-               dev_err(&oct->pci_dev->dev, "Valid range %d and %d\n",
-                       LIO_MIN_MTU_SIZE, LIO_MAX_MTU_SIZE);
-               return -EINVAL;
-       }
-
        memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
 
        nctrl.ncmd.u64 = 0;
@@ -3891,6 +3880,10 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
                netdev->hw_features = netdev->hw_features &
                        ~NETIF_F_HW_VLAN_CTAG_RX;
 
+               /* MTU range: 68 - 16000 */
+               netdev->min_mtu = LIO_MIN_MTU_SIZE;
+               netdev->max_mtu = LIO_MAX_MTU_SIZE;
+
                /* Point to the  properties for octeon device to which this
                 * interface belongs.
                 */
index e5d1debd05add28a0a91e8880db929cb2e7a19db..54b9665963235b0631cf3d87f0c5264e9685e101 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/ptp_clock_kernel.h>
 
 #define LIO_MAX_MTU_SIZE (OCTNET_MAX_FRM_SIZE - OCTNET_FRM_HEADER_SIZE)
-#define LIO_MIN_MTU_SIZE 68
+#define LIO_MIN_MTU_SIZE ETH_MIN_MTU
 
 struct oct_nic_stats_resp {
        u64     rh;
index 4ab404f45b215820245ed9f9ad478c7c3961d752..16e12c45904be6d4a24b858d5f4265a78adbc3d9 100644 (file)
@@ -645,16 +645,6 @@ static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
        struct octeon_mgmt *p = netdev_priv(netdev);
        int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM;
 
-       /* Limit the MTU to make sure the ethernet packets are between
-        * 64 bytes and 16383 bytes.
-        */
-       if (size_without_fcs < 64 || size_without_fcs > 16383) {
-               dev_warn(p->dev, "MTU must be between %d and %d.\n",
-                        64 - OCTEON_MGMT_RX_HEADROOM,
-                        16383 - OCTEON_MGMT_RX_HEADROOM);
-               return -EINVAL;
-       }
-
        netdev->mtu = new_mtu;
 
        cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs);
@@ -1491,6 +1481,9 @@ static int octeon_mgmt_probe(struct platform_device *pdev)
        netdev->netdev_ops = &octeon_mgmt_ops;
        netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
 
+       netdev->min_mtu = 64 - OCTEON_MGMT_RX_HEADROOM;
+       netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM;
+
        mac = of_get_mac_address(pdev->dev.of_node);
 
        if (mac)
index 45a13f718863f33a6ccc7f14a37f2f2fc117be84..b192712c93b7bd6bf39b1dd5cf394fbaba8da62b 100644 (file)
@@ -1312,12 +1312,6 @@ static int nicvf_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct nicvf *nic = netdev_priv(netdev);
 
-       if (new_mtu > NIC_HW_MAX_FRS)
-               return -EINVAL;
-
-       if (new_mtu < NIC_HW_MIN_FRS)
-               return -EINVAL;
-
        if (nicvf_update_hw_max_frs(nic, new_mtu))
                return -EINVAL;
        netdev->mtu = new_mtu;
@@ -1630,6 +1624,10 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        netdev->netdev_ops = &nicvf_netdev_ops;
        netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
 
+       /* MTU range: 64 - 9200 */
+       netdev->min_mtu = NIC_HW_MIN_FRS;
+       netdev->max_mtu = NIC_HW_MAX_FRS;
+
        INIT_WORK(&nic->reset_task, nicvf_reset_task);
 
        err = register_netdev(netdev);
index 53b1f947838320ded878c557882b5b05acddeff7..6916c62f2487dd9a9bca381685cea6b4c771ef1f 100644 (file)
@@ -85,6 +85,11 @@ struct t1_rx_mode {
 #define SPEED_INVALID 0xffff
 #define DUPLEX_INVALID 0xff
 
+/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
+#define PM3393_MAX_FRAME_SIZE 9600
+
+#define VSC7326_MAX_MTU 9600
+
 enum {
        CHBT_BOARD_N110,
        CHBT_BOARD_N210,
index f5f1b0b51ebd225c4d82967391e5dedda2a7848f..81d1d0bc7553bfc907e32bf5e42618ab57b68911 100644 (file)
@@ -825,8 +825,6 @@ static int t1_change_mtu(struct net_device *dev, int new_mtu)
 
        if (!mac->ops->set_mtu)
                return -EOPNOTSUPP;
-       if (new_mtu < 68)
-               return -EINVAL;
        if ((ret = mac->ops->set_mtu(mac, new_mtu)))
                return ret;
        dev->mtu = new_mtu;
@@ -1101,6 +1099,22 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
 
                netdev->ethtool_ops = &t1_ethtool_ops;
+
+               switch (bi->board) {
+               case CHBT_BOARD_CHT110:
+               case CHBT_BOARD_N110:
+               case CHBT_BOARD_N210:
+               case CHBT_BOARD_CHT210:
+                       netdev->max_mtu = PM3393_MAX_FRAME_SIZE -
+                                         (ETH_HLEN + ETH_FCS_LEN);
+                       break;
+               case CHBT_BOARD_CHN204:
+                       netdev->max_mtu = VSC7326_MAX_MTU;
+                       break;
+               default:
+                       netdev->max_mtu = ETH_DATA_LEN;
+                       break;
+               }
        }
 
        if (t1_init_sw_modules(adapter, bi) < 0) {
index eb462d7db4276c9931803926a2e00003a20392b8..c27908e66f5edb450354aa133ba8ff4584e0aa2f 100644 (file)
@@ -47,9 +47,6 @@
 
 #define OFFSET(REG_ADDR)    ((REG_ADDR) << 2)
 
-/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
-#define MAX_FRAME_SIZE  9600
-
 #define IPG 12
 #define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
        SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
@@ -331,10 +328,7 @@ static int pm3393_set_mtu(struct cmac *cmac, int mtu)
 {
        int enabled = cmac->instance->enabled;
 
-       /* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
-       mtu += 14 + 4;
-       if (mtu > MAX_FRAME_SIZE)
-               return -EINVAL;
+       mtu += ETH_HLEN + ETH_FCS_LEN;
 
        /* Disable Rx/Tx MAC before configuring it. */
        if (enabled)
index 6f30b6f785539c473670b5c78e10008ce1458fec..bdc895bd2a4606900cb1c078a06ddc2864e912dc 100644 (file)
@@ -11,8 +11,6 @@
 /* 30 minutes for full statistics update */
 #define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
 
-#define MAX_MTU 9600
-
 /* The egress WM value 0x01a01fff should be used only when the
  * interface is down (MAC port disabled). This is a workaround
  * for disabling the T2/MAC flow-control. When the interface is
@@ -452,9 +450,6 @@ static int mac_set_mtu(struct cmac *mac, int mtu)
 {
        int port = mac->instance->index;
 
-       if (mtu > MAX_MTU)
-               return -EINVAL;
-
        /* max_len includes header and FCS */
        vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4);
        return 0;
index 43da891fab97e7f16b572dd67f3fc6aa9020a1fb..092b3c16440bcf2f4f6186cb8af0e1eed8ca1354 100644 (file)
@@ -2531,8 +2531,6 @@ static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
        struct adapter *adapter = pi->adapter;
        int ret;
 
-       if (new_mtu < 81)       /* accommodate SACK */
-               return -EINVAL;
        if ((ret = t3_mac_set_mtu(&pi->mac, new_mtu)))
                return ret;
        dev->mtu = new_mtu;
@@ -3295,6 +3293,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
                netdev->netdev_ops = &cxgb_netdev_ops;
                netdev->ethtool_ops = &cxgb_ethtool_ops;
+               netdev->min_mtu = 81;
+               netdev->max_mtu = ETH_MAX_MTU;
        }
 
        pci_set_drvdata(pdev, adapter);
index 57eb4e1345cb00a49666d1ff147aa4ef971d3d26..c0cc2ee77be73be6bbbf31c7aad02c7f381bc256 100644 (file)
@@ -2502,8 +2502,6 @@ static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
        int ret;
        struct port_info *pi = netdev_priv(dev);
 
-       if (new_mtu < 81 || new_mtu > MAX_MTU)         /* accommodate SACK */
-               return -EINVAL;
        ret = t4_set_rxmode(pi->adapter, pi->adapter->pf, pi->viid, new_mtu, -1,
                            -1, -1, -1, true);
        if (!ret)
@@ -4803,6 +4801,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
                netdev->priv_flags |= IFF_UNICAST_FLT;
 
+               /* MTU range: 81 - 9600 */
+               netdev->min_mtu = 81;
+               netdev->max_mtu = MAX_MTU;
+
                netdev->netdev_ops = &cxgb4_netdev_ops;
 #ifdef CONFIG_CHELSIO_T4_DCB
                netdev->dcbnl_ops = &cxgb4_dcb_ops;
index 49d2debb334e8e56f9544559f28001259e1b74c1..52af62e0ecb6bf01cdeffa0efc15e9870c134de2 100644 (file)
@@ -113,7 +113,7 @@ static int fill_action_fields(struct adapter *adap,
                }
 
                /* Re-direct to specified port in hardware. */
-               if (is_tcf_mirred_redirect(a)) {
+               if (is_tcf_mirred_egress_redirect(a)) {
                        struct net_device *n_dev;
                        unsigned int i, index;
                        bool found = false;
index 100b2cc064a34cafe8faac0e16e9ce44aa1a4f95..5d4da0e8acaa5895c4a649c32608287af1afda74 100644 (file)
@@ -1108,10 +1108,6 @@ static int cxgb4vf_change_mtu(struct net_device *dev, int new_mtu)
        int ret;
        struct port_info *pi = netdev_priv(dev);
 
-       /* accommodate SACK */
-       if (new_mtu < 81)
-               return -EINVAL;
-
        ret = t4vf_set_rxmode(pi->adapter, pi->viid, new_mtu,
                              -1, -1, -1, -1, true);
        if (!ret)
@@ -2966,6 +2962,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
                        netdev->features |= NETIF_F_HIGHDMA;
 
                netdev->priv_flags |= IFF_UNICAST_FLT;
+               netdev->min_mtu = 81;
+               netdev->max_mtu = ETH_MAX_MTU;
 
                netdev->netdev_ops = &cxgb4vf_netdev_ops;
                netdev->ethtool_ops = &cxgb4vf_ethtool_ops;
index c363b58552e9d1f919a9925134442e9f490282ea..3647b28e8de019839e38234ff0a1b495ce4b05fa 100644 (file)
@@ -1266,7 +1266,6 @@ static const struct net_device_ops net_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = net_poll_controller,
 #endif
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index de9f7c97d916d3d8d760282e726cf49f4181a56b..9119af0888210f098d4117b779b25258f83cab04 100644 (file)
@@ -749,7 +749,6 @@ static const struct net_device_ops ep93xx_netdev_ops = {
        .ndo_start_xmit         = ep93xx_xmit,
        .ndo_do_ioctl           = ep93xx_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
index 07719676c305fc0b433f614c9ec8365dad88859f..b600fbbbf679885231e7d4cd5a9628a5deb70382 100644 (file)
@@ -172,7 +172,6 @@ static const struct net_device_ops mac89x0_netdev_ops = {
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_set_mac_address    = set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 /* Probe for the CS8900 card in slot E.  We won't bother looking
index 48f82ab6c25b19811c5088aab0ad37a62f4e922f..f514faf8b7093f883595569efedf338abdaee73c 100644 (file)
@@ -1843,9 +1843,6 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
        struct enic *enic = netdev_priv(netdev);
        int running = netif_running(netdev);
 
-       if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
-               return -EINVAL;
-
        if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
                return -EOPNOTSUPP;
 
@@ -2751,6 +2748,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        netdev->priv_flags |= IFF_UNICAST_FLT;
 
+       /* MTU range: 68 - 9000 */
+       netdev->min_mtu = ENIC_MIN_MTU;
+       netdev->max_mtu = ENIC_MAX_MTU;
+
        err = register_netdev(netdev);
        if (err) {
                dev_err(dev, "Cannot register net device, aborting\n");
index 69f60afd6577ec2d7c5c41540f81fbc59b7049a6..81f98a8b60e903cbbe41716c3e75c9e178e5fe9a 100644 (file)
@@ -30,7 +30,7 @@
 #define ENIC_MIN_RQ_DESCS              64
 #define ENIC_MAX_RQ_DESCS              4096
 
-#define ENIC_MIN_MTU                   68
+#define ENIC_MIN_MTU                   ETH_MIN_MTU
 #define ENIC_MAX_MTU                   9000
 
 #define ENIC_MULTICAST_PERFECT_FILTERS 32
index f45385f5c6e58269d0d3f593b460fb5952a6c5e3..f1a81c52afe38783aad3d4c5ab43f3fdfaaacf08 100644 (file)
@@ -1382,7 +1382,6 @@ static const struct net_device_ops dm9000_netdev_ops = {
        .ndo_tx_timeout         = dm9000_timeout,
        .ndo_set_rx_mode        = dm9000_hash_table,
        .ndo_do_ioctl           = dm9000_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_features       = dm9000_set_features,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
index cadcee645f74e8fe45a6f34e2b7e0bf949ea14e7..90c573b8ccafe027ecf1716c66b545464bd75553 100644 (file)
@@ -1956,7 +1956,6 @@ static const struct net_device_ops de_netdev_ops = {
        .ndo_start_xmit         = de_start_xmit,
        .ndo_get_stats          = de_get_stats,
        .ndo_tx_timeout         = de_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 6620fc861c477eeb38d3c2b9495619b0e65ca63a..51fda3a6b13f85162194e29adb326d7452d71d2e 100644 (file)
@@ -1085,7 +1085,6 @@ static const struct net_device_ops de4x5_netdev_ops = {
     .ndo_get_stats     = de4x5_get_stats,
     .ndo_set_rx_mode   = set_multicast_list,
     .ndo_do_ioctl      = de4x5_ioctl,
-    .ndo_change_mtu    = eth_change_mtu,
     .ndo_set_mac_address= eth_mac_addr,
     .ndo_validate_addr = eth_validate_addr,
 };
index 8ed0fd8b1dda8301a57e4eb9607eeb9d7ccf9102..df499491945601766f528d90657789e62219bfc3 100644 (file)
@@ -352,7 +352,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_stop               = dmfe_stop,
        .ndo_start_xmit         = dmfe_start_xmit,
        .ndo_set_rx_mode        = dmfe_set_filter_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index bbde90bc74fe244f60f925099a77ea50d94084e5..5f1377449b8f79f88eae3789f9ee3b28a39d6e8d 100644 (file)
@@ -1282,7 +1282,6 @@ static const struct net_device_ops tulip_netdev_ops = {
        .ndo_get_stats          = tulip_get_stats,
        .ndo_do_ioctl           = private_ioctl,
        .ndo_set_rx_mode        = set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index e750b5ddc0fbb34436f9df49e9cd62ebc5eb0700..e1c4133b8787b89e8c3b40f55b16b7a0c33e0ec5 100644 (file)
@@ -269,7 +269,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_stop               = uli526x_stop,
        .ndo_start_xmit         = uli526x_start_xmit,
        .ndo_set_rx_mode        = uli526x_set_filter_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 1f62b942385101bc475b7d6219b572aebc267cfb..feda96d585e7b678a0dc2b1f483c8e1e6462eeee 100644 (file)
@@ -353,7 +353,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = netdev_ioctl,
        .ndo_tx_timeout         = tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 0e721cedfa67c1e1b60e3e9bf059c9660d6e78ce..19e4ea15b504ad2dd2555f98530d72da79cb71ac 100644 (file)
@@ -174,7 +174,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_open               = xircom_open,
        .ndo_stop               = xircom_close,
        .ndo_start_xmit         = xircom_start_xmit,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 78f144696d6b335f90e642709864f1683388d44a..8c95a8a81e3c237b61a2d564951819ea88f68eb7 100644 (file)
@@ -76,7 +76,6 @@ static void rio_free_tx (struct net_device *dev, int irq);
 static void tx_error (struct net_device *dev, int tx_status);
 static int receive_packet (struct net_device *dev);
 static void rio_error (struct net_device *dev, int int_status);
-static int change_mtu (struct net_device *dev, int new_mtu);
 static void set_multicast (struct net_device *dev);
 static struct net_device_stats *get_stats (struct net_device *dev);
 static int clear_stats (struct net_device *dev);
@@ -106,7 +105,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_set_rx_mode        = set_multicast,
        .ndo_do_ioctl           = rio_ioctl,
        .ndo_tx_timeout         = rio_tx_timeout,
-       .ndo_change_mtu         = change_mtu,
 };
 
 static int
@@ -230,6 +228,10 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
 #if 0
        dev->features = NETIF_F_IP_CSUM;
 #endif
+       /* MTU range: 68 - 1536 or 8000 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = np->jumbo ? MAX_JUMBO : PACKET_SIZE;
+
        pci_set_drvdata (pdev, dev);
 
        ring_space = pci_alloc_consistent (pdev, TX_TOTAL_SIZE, &ring_dma);
@@ -1198,22 +1200,6 @@ clear_stats (struct net_device *dev)
        return 0;
 }
 
-
-static int
-change_mtu (struct net_device *dev, int new_mtu)
-{
-       struct netdev_private *np = netdev_priv(dev);
-       int max = (np->jumbo) ? MAX_JUMBO : 1536;
-
-       if ((new_mtu < 68) || (new_mtu > max)) {
-               return -EINVAL;
-       }
-
-       dev->mtu = new_mtu;
-
-       return 0;
-}
-
 static void
 set_multicast (struct net_device *dev)
 {
index 79d80090eac8bd52bad4978a8418cc8f9d617737..eab36acfc0d1b7aaa827c2b2c5cac462cb62bde5 100644 (file)
@@ -580,6 +580,10 @@ static int sundance_probe1(struct pci_dev *pdev,
        dev->ethtool_ops = &ethtool_ops;
        dev->watchdog_timeo = TX_TIMEOUT;
 
+       /* MTU range: 68 - 8191 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = 8191;
+
        pci_set_drvdata(pdev, dev);
 
        i = register_netdev(dev);
@@ -713,8 +717,6 @@ err_out_netdev:
 
 static int change_mtu(struct net_device *dev, int new_mtu)
 {
-       if ((new_mtu < 68) || (new_mtu > 8191)) /* Set by RxDMAFrameLen */
-               return -EINVAL;
        if (netif_running(dev))
                return -EBUSY;
        dev->mtu = new_mtu;
index c3b64cdd0decb76f7da6551f3ed95cb9f576318a..2a17c59f69f9fb0208f7bf6c23b88af1f082ea0a 100644 (file)
@@ -767,7 +767,6 @@ static const struct net_device_ops dnet_netdev_ops = {
        .ndo_do_ioctl           = dnet_ioctl,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int dnet_probe(struct platform_device *pdev)
index f7b42483921c5847a883a286d28f7700e10b1d28..57650953ff83e127ecdcb3e606114d619d49db18 100644 (file)
@@ -482,7 +482,6 @@ static const struct net_device_ops ec_bhf_netdev_ops = {
        .ndo_open               = ec_bhf_open,
        .ndo_stop               = ec_bhf_stop,
        .ndo_get_stats64        = ec_bhf_get_stats,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr
 };
index cece8a08edca1de45c4c56f89704ddd8523d7a3f..3f6152cc648c86feb94a85edbe8924bd2a95ea90 100644 (file)
@@ -1406,23 +1406,6 @@ drop:
        return NETDEV_TX_OK;
 }
 
-static int be_change_mtu(struct net_device *netdev, int new_mtu)
-{
-       struct be_adapter *adapter = netdev_priv(netdev);
-       struct device *dev = &adapter->pdev->dev;
-
-       if (new_mtu < BE_MIN_MTU || new_mtu > BE_MAX_MTU) {
-               dev_info(dev, "MTU must be between %d and %d bytes\n",
-                        BE_MIN_MTU, BE_MAX_MTU);
-               return -EINVAL;
-       }
-
-       dev_info(dev, "MTU changed from %d to %d bytes\n",
-                netdev->mtu, new_mtu);
-       netdev->mtu = new_mtu;
-       return 0;
-}
-
 static inline bool be_in_all_promisc(struct be_adapter *adapter)
 {
        return (adapter->if_flags & BE_IF_FLAGS_ALL_PROMISCUOUS) ==
@@ -5216,7 +5199,6 @@ static const struct net_device_ops be_netdev_ops = {
        .ndo_start_xmit         = be_xmit,
        .ndo_set_rx_mode        = be_set_rx_mode,
        .ndo_set_mac_address    = be_mac_addr_set,
-       .ndo_change_mtu         = be_change_mtu,
        .ndo_get_stats64        = be_get_stats64,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_vlan_rx_add_vid    = be_vlan_add_vid,
@@ -5266,6 +5248,10 @@ static void be_netdev_init(struct net_device *netdev)
        netdev->netdev_ops = &be_netdev_ops;
 
        netdev->ethtool_ops = &be_ethtool_ops;
+
+       /* MTU range: 256 - 9000 */
+       netdev->min_mtu = BE_MIN_MTU;
+       netdev->max_mtu = BE_MAX_MTU;
 }
 
 static void be_cleanup(struct be_adapter *adapter)
index c08bd763172a76da6ae68a00d55e06992d6cacdd..6967b287b6e762342eb0f02f0851a4309dea7330 100644 (file)
@@ -472,7 +472,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = mii_ioctl,
        .ndo_tx_timeout         = fealnx_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 5aa9d4ded214cfd96fe9de816593f76298f2d334..01aebc0084a9f7b2c5b4972220a8c19ddaa57ec7 100644 (file)
@@ -1841,11 +1841,11 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
                ret = clk_prepare_enable(fep->clk_ahb);
                if (ret)
                        return ret;
-               if (fep->clk_enet_out) {
-                       ret = clk_prepare_enable(fep->clk_enet_out);
-                       if (ret)
-                               goto failed_clk_enet_out;
-               }
+
+               ret = clk_prepare_enable(fep->clk_enet_out);
+               if (ret)
+                       goto failed_clk_enet_out;
+
                if (fep->clk_ptp) {
                        mutex_lock(&fep->ptp_clk_mutex);
                        ret = clk_prepare_enable(fep->clk_ptp);
@@ -1857,23 +1857,20 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
                        }
                        mutex_unlock(&fep->ptp_clk_mutex);
                }
-               if (fep->clk_ref) {
-                       ret = clk_prepare_enable(fep->clk_ref);
-                       if (ret)
-                               goto failed_clk_ref;
-               }
+
+               ret = clk_prepare_enable(fep->clk_ref);
+               if (ret)
+                       goto failed_clk_ref;
        } else {
                clk_disable_unprepare(fep->clk_ahb);
-               if (fep->clk_enet_out)
-                       clk_disable_unprepare(fep->clk_enet_out);
+               clk_disable_unprepare(fep->clk_enet_out);
                if (fep->clk_ptp) {
                        mutex_lock(&fep->ptp_clk_mutex);
                        clk_disable_unprepare(fep->clk_ptp);
                        fep->ptp_clk_on = false;
                        mutex_unlock(&fep->ptp_clk_mutex);
                }
-               if (fep->clk_ref)
-                       clk_disable_unprepare(fep->clk_ref);
+               clk_disable_unprepare(fep->clk_ref);
        }
 
        return 0;
@@ -3055,7 +3052,6 @@ static const struct net_device_ops fec_netdev_ops = {
        .ndo_stop               = fec_enet_close,
        .ndo_start_xmit         = fec_enet_start_xmit,
        .ndo_set_rx_mode        = set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = fec_timeout,
        .ndo_set_mac_address    = fec_set_mac_address,
index 446ae9d60c71f10f20a45653cc24b21e9c83d14c..aa8cf5d2a53cdf98523d94f5a0200cb5315dbe38 100644 (file)
@@ -802,7 +802,6 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = {
        .ndo_set_mac_address = mpc52xx_fec_set_mac_address,
        .ndo_validate_addr = eth_validate_addr,
        .ndo_do_ioctl = mpc52xx_fec_ioctl,
-       .ndo_change_mtu = eth_change_mtu,
        .ndo_tx_timeout = mpc52xx_fec_tx_timeout,
        .ndo_get_stats = mpc52xx_fec_get_stats,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 8fe6b3e253fa436f0cc87bf8702b827f3b6d9a72..cc5d07cfe535fb9a9cec20f02a9f2e85fedadda2 100644 (file)
@@ -879,13 +879,17 @@ static int mac_probe(struct platform_device *_of_dev)
 
                priv->fixed_link = kzalloc(sizeof(*priv->fixed_link),
                                           GFP_KERNEL);
-               if (!priv->fixed_link)
+               if (!priv->fixed_link) {
+                       err = -ENOMEM;
                        goto _return_dev_set_drvdata;
+               }
 
                priv->phy_node = of_node_get(mac_node);
                phy = of_phy_find_device(priv->phy_node);
-               if (!phy)
+               if (!phy) {
+                       err = -EINVAL;
                        goto _return_dev_set_drvdata;
+               }
 
                priv->fixed_link->link = phy->link;
                priv->fixed_link->speed = phy->speed;
index dc120c148d9766fcf511f100396cb51f4b61a73b..44f50e1687035b019514d55663d95a42b684c344 100644 (file)
@@ -118,22 +118,22 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
                          BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {
 
                        if (sc & BD_ENET_TX_HB) /* No heartbeat */
-                               fep->stats.tx_heartbeat_errors++;
+                               dev->stats.tx_heartbeat_errors++;
                        if (sc & BD_ENET_TX_LC) /* Late collision */
-                               fep->stats.tx_window_errors++;
+                               dev->stats.tx_window_errors++;
                        if (sc & BD_ENET_TX_RL) /* Retrans limit */
-                               fep->stats.tx_aborted_errors++;
+                               dev->stats.tx_aborted_errors++;
                        if (sc & BD_ENET_TX_UN) /* Underrun */
-                               fep->stats.tx_fifo_errors++;
+                               dev->stats.tx_fifo_errors++;
                        if (sc & BD_ENET_TX_CSL)        /* Carrier lost */
-                               fep->stats.tx_carrier_errors++;
+                               dev->stats.tx_carrier_errors++;
 
                        if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
-                               fep->stats.tx_errors++;
+                               dev->stats.tx_errors++;
                                do_restart = 1;
                        }
                } else
-                       fep->stats.tx_packets++;
+                       dev->stats.tx_packets++;
 
                if (sc & BD_ENET_TX_READY) {
                        dev_warn(fep->dev,
@@ -145,7 +145,7 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
                 * but we eventually sent the packet OK.
                 */
                if (sc & BD_ENET_TX_DEF)
-                       fep->stats.collisions++;
+                       dev->stats.collisions++;
 
                /* unmap */
                if (fep->mapped_as_page[dirtyidx])
@@ -212,19 +212,19 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
                 */
                if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
                          BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
-                       fep->stats.rx_errors++;
+                       dev->stats.rx_errors++;
                        /* Frame too long or too short. */
                        if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
-                               fep->stats.rx_length_errors++;
+                               dev->stats.rx_length_errors++;
                        /* Frame alignment */
                        if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
-                               fep->stats.rx_frame_errors++;
+                               dev->stats.rx_frame_errors++;
                        /* CRC Error */
                        if (sc & BD_ENET_RX_CR)
-                               fep->stats.rx_crc_errors++;
+                               dev->stats.rx_crc_errors++;
                        /* FIFO overrun */
                        if (sc & BD_ENET_RX_OV)
-                               fep->stats.rx_crc_errors++;
+                               dev->stats.rx_crc_errors++;
 
                        skbn = fep->rx_skbuff[curidx];
                } else {
@@ -233,9 +233,9 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
                        /*
                         * Process the incoming frame.
                         */
-                       fep->stats.rx_packets++;
+                       dev->stats.rx_packets++;
                        pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */
-                       fep->stats.rx_bytes += pkt_len + 4;
+                       dev->stats.rx_bytes += pkt_len + 4;
 
                        if (pkt_len <= fpi->rx_copybreak) {
                                /* +2 to make IP header L1 cache aligned */
@@ -277,7 +277,7 @@ static int fs_enet_napi(struct napi_struct *napi, int budget)
                                received++;
                                netif_receive_skb(skb);
                        } else {
-                               fep->stats.rx_dropped++;
+                               dev->stats.rx_dropped++;
                                skbn = skb;
                        }
                }
@@ -543,7 +543,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        curidx = bdp - fep->tx_bd_base;
 
        len = skb->len;
-       fep->stats.tx_bytes += len;
+       dev->stats.tx_bytes += len;
        if (nr_frags)
                len -= skb->data_len;
        fep->tx_free -= nr_frags + 1;
@@ -619,7 +619,7 @@ static void fs_timeout(struct net_device *dev)
        unsigned long flags;
        int wake = 0;
 
-       fep->stats.tx_errors++;
+       dev->stats.tx_errors++;
 
        spin_lock_irqsave(&fep->lock, flags);
 
@@ -774,12 +774,6 @@ static int fs_enet_close(struct net_device *dev)
        return 0;
 }
 
-static struct net_device_stats *fs_enet_get_stats(struct net_device *dev)
-{
-       struct fs_enet_private *fep = netdev_priv(dev);
-       return &fep->stats;
-}
-
 /*************************************************************************/
 
 static void fs_get_drvinfo(struct net_device *dev,
@@ -905,14 +899,12 @@ extern void fs_mii_disconnect(struct net_device *dev);
 static const struct net_device_ops fs_enet_netdev_ops = {
        .ndo_open               = fs_enet_open,
        .ndo_stop               = fs_enet_close,
-       .ndo_get_stats          = fs_enet_get_stats,
        .ndo_start_xmit         = fs_enet_start_xmit,
        .ndo_tx_timeout         = fs_timeout,
        .ndo_set_rx_mode        = fs_set_multicast_list,
        .ndo_do_ioctl           = fs_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = fs_enet_netpoll,
 #endif
index fee24c822fada5645a5148e01a35349b0a784b7e..5ce516c8a62a135e9819a435d49a2f2ed26242a8 100644 (file)
@@ -137,7 +137,6 @@ struct fs_enet_private {
        cbd_t __iomem *cur_rx;
        cbd_t __iomem *cur_tx;
        int tx_free;
-       struct net_device_stats stats;
        struct timer_list phy_timer_list;
        const struct phy_info *phy;
        u32 msg_enable;
index 4b4f5bc0e2799cdaea3f1be09fc29e07cbb6b559..409210413f5df4cf7c52a01f73fda6063bb7e39a 100644 (file)
@@ -1338,7 +1338,10 @@ static int gfar_probe(struct platform_device *ofdev)
 
        /* Fill in the dev structure */
        dev->watchdog_timeo = TX_TIMEOUT;
+       /* MTU range: 50 - 9586 */
        dev->mtu = 1500;
+       dev->min_mtu = 50;
+       dev->max_mtu = GFAR_JUMBO_FRAME_SIZE - ETH_HLEN;
        dev->netdev_ops = &gfar_netdev_ops;
        dev->ethtool_ops = &gfar_ethtool_ops;
 
@@ -2592,12 +2595,6 @@ static int gfar_set_mac_address(struct net_device *dev)
 static int gfar_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct gfar_private *priv = netdev_priv(dev);
-       int frame_size = new_mtu + ETH_HLEN;
-
-       if ((frame_size < 64) || (frame_size > GFAR_JUMBO_FRAME_SIZE)) {
-               netif_err(priv, drv, dev, "Invalid MTU setting\n");
-               return -EINVAL;
-       }
 
        while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
                cpu_relax();
index 186ef8f16c802c5b076c41f1568ef582051cb103..786182480a7372a82e61b95bc17a04b115106f3c 100644 (file)
@@ -3681,7 +3681,6 @@ static const struct net_device_ops ucc_geth_netdev_ops = {
        .ndo_start_xmit         = ucc_geth_start_xmit,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ucc_geth_set_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_rx_mode        = ucc_geth_set_multi,
        .ndo_tx_timeout         = ucc_geth_timeout,
        .ndo_do_ioctl           = ucc_geth_ioctl,
index 399cfd217288d9e32b0fd9ba188e974a4663a87e..51c4abc51bf4837156c3579ee663da9def9093fe 100644 (file)
@@ -225,7 +225,6 @@ static const struct net_device_ops fjn_netdev_ops = {
        .ndo_tx_timeout         = fjn_tx_timeout,
        .ndo_set_config         = fjn_config,
        .ndo_set_rx_mode        = set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 39778892b3b3bc77cdd36c38f8688c1141a83543..854befde0a08c9031df92a69c5c9e3709062c188 100644 (file)
@@ -769,7 +769,6 @@ static const struct net_device_ops hip04_netdev_ops = {
        .ndo_set_mac_address    = hip04_set_mac_address,
        .ndo_tx_timeout         = hip04_timeout,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int hip04_alloc_ring(struct net_device *ndev, struct device *d)
@@ -898,7 +897,6 @@ static int hip04_mac_probe(struct platform_device *pdev)
 
        INIT_WORK(&priv->tx_timeout_task, hip04_tx_timeout_task);
 
-       ether_setup(ndev);
        ndev->netdev_ops = &hip04_netdev_ops;
        ndev->ethtool_ops = &hip04_ethtool_ops;
        ndev->watchdog_timeo = TX_TIMEOUT;
index ced185962ef843654d1d1f096c3eb17f5f74fa0b..49863068c59e3cb4ecb4c24128326cbd4c42e37a 100644 (file)
@@ -712,7 +712,6 @@ static const struct net_device_ops hisi_femac_netdev_ops = {
        .ndo_do_ioctl           = hisi_femac_net_ioctl,
        .ndo_set_mac_address    = hisi_femac_set_mac_address,
        .ndo_set_rx_mode        = hisi_femac_net_set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static void hisi_femac_core_reset(struct hisi_femac_priv *priv)
index ec8c738af726323e92c2416a639806462f0bfe4b..55cbb6ce733c642813022401fb643ce657858dec 100644 (file)
@@ -453,8 +453,7 @@ int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu)
        if (mac_cb->mac_type == HNAE_PORT_DEBUG)
                max_frm = MAC_MAX_MTU_DBG;
 
-       if ((new_mtu < MAC_MIN_MTU) || (new_frm > max_frm) ||
-           (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size))
+       if (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size)
                return -EINVAL;
 
        if (!drv->config_max_frame_length)
index dff7b60345d8e94b90a53f16d2c9caadde1b449a..60831a2ac86b154758b03450ddcb9d4a466cee1a 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "hnae.h"
 #include "hns_enet.h"
+#include "hns_dsaf_mac.h"
 
 #define NIC_MAX_Q_PER_VF 16
 #define HNS_NIC_TX_TIMEOUT (5 * HZ)
@@ -1426,10 +1427,6 @@ static int hns_nic_change_mtu(struct net_device *ndev, int new_mtu)
        struct hnae_handle *h = priv->ae_handle;
        int ret;
 
-       /* MTU < 68 is an error and causes problems on some kernels */
-       if (new_mtu < 68)
-               return -EINVAL;
-
        if (!h->dev->ops->set_mtu)
                return -ENOTSUPP;
 
@@ -1992,14 +1989,20 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
                NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
        ndev->vlan_features |= NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO;
 
+       /* MTU range: 68 - 9578 (v1) or 9706 (v2) */
+       ndev->min_mtu = MAC_MIN_MTU;
        switch (priv->enet_ver) {
        case AE_VERSION_2:
                ndev->features |= NETIF_F_TSO | NETIF_F_TSO6;
                ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                        NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
                        NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6;
+               ndev->max_mtu = MAC_MAX_MTU_V2 -
+                               (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
                break;
        default:
+               ndev->max_mtu = MAC_MAX_MTU -
+                               (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
                break;
        }
 
index 631dbc7b4dbb9b95985a8b4a2431cc648ef74644..1a31bee6e72898b64ead40dc505aac07b0cb477d 100644 (file)
@@ -427,7 +427,6 @@ static const struct net_device_ops hp100_bm_netdev_ops = {
        .ndo_start_xmit         = hp100_start_xmit_bm,
        .ndo_get_stats          = hp100_get_stats,
        .ndo_set_rx_mode        = hp100_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -438,7 +437,6 @@ static const struct net_device_ops hp100_netdev_ops = {
        .ndo_start_xmit         = hp100_start_xmit,
        .ndo_get_stats          = hp100_get_stats,
        .ndo_set_rx_mode        = hp100_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index ce235b776793d5505303cb44e1e4e21c92f94351..94588384253300a981f2c8b1564111261398685c 100644 (file)
@@ -1118,7 +1118,6 @@ static const struct net_device_ops i596_netdev_ops = {
        .ndo_start_xmit         = i596_start_xmit,
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = i596_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 5d353c66006829ef08a3ffdef537c825d367f58b..dc983450354bbf3eae79dda14d7c44815cee126d 100644 (file)
@@ -981,7 +981,6 @@ static const struct net_device_ops ether1_netdev_ops = {
        .ndo_set_rx_mode        = ether1_setmulticastlist,
        .ndo_tx_timeout         = ether1_timeout,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
index 3dbc53c21baa4b02a6f4e16fbaab50d9ea09ba17..e86773325cbec65927e946e9992faf493841042a 100644 (file)
@@ -1037,7 +1037,6 @@ static const struct net_device_ops i596_netdev_ops = {
        .ndo_start_xmit         = i596_start_xmit,
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_tx_timeout         = i596_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 21c84cc9c871d5fd66d05b104426cf7252a1000a..8bb15a8c2a4026939f37161629d424963dc0a082 100644 (file)
@@ -337,7 +337,6 @@ static const struct net_device_ops sun3_82586_netdev_ops = {
        .ndo_get_stats          = sun3_82586_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int __init sun3_82586_probe1(struct net_device *dev,int ioaddr)
index 54efa9a5167b86021802b98900e6ff216fa10a73..e9719ba450d7ccf8770eba14ad02773ca5577e7d 100644 (file)
@@ -1981,14 +1981,6 @@ out:
        ehea_update_bcmc_registrations();
 }
 
-static int ehea_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 68) || (new_mtu > EHEA_MAX_PACKET_SIZE))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static void xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe)
 {
        swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT | EHEA_SWQE_CRC;
@@ -2968,7 +2960,6 @@ static const struct net_device_ops ehea_netdev_ops = {
        .ndo_set_mac_address    = ehea_set_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = ehea_set_multicast_list,
-       .ndo_change_mtu         = ehea_change_mtu,
        .ndo_vlan_rx_add_vid    = ehea_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = ehea_vlan_rx_kill_vid,
        .ndo_tx_timeout         = ehea_tx_watchdog,
@@ -3041,6 +3032,10 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
                        NETIF_F_IP_CSUM;
        dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
+       /* MTU range: 68 - 9022 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = EHEA_MAX_PACKET_SIZE;
+
        INIT_WORK(&port->reset_task, ehea_reset_port);
        INIT_DELAYED_WORK(&port->stats_work, ehea_update_stats);
 
index 8f139197f1aae7409934742d630d90b6bf998afd..52a69c925965200e304d447713acb8360f06eeb6 100644 (file)
@@ -1099,9 +1099,6 @@ static int emac_change_mtu(struct net_device *ndev, int new_mtu)
        struct emac_instance *dev = netdev_priv(ndev);
        int ret = 0;
 
-       if (new_mtu < EMAC_MIN_MTU || new_mtu > dev->max_mtu)
-               return -EINVAL;
-
        DBG(dev, "change_mtu(%d)" NL, new_mtu);
 
        if (netif_running(ndev)) {
@@ -2564,7 +2561,7 @@ static int emac_init_config(struct emac_instance *dev)
        if (emac_read_uint_prop(np, "cell-index", &dev->cell_index, 1))
                return -ENXIO;
        if (emac_read_uint_prop(np, "max-frame-size", &dev->max_mtu, 0))
-               dev->max_mtu = 1500;
+               dev->max_mtu = ETH_DATA_LEN;
        if (emac_read_uint_prop(np, "rx-fifo-size", &dev->rx_fifo_size, 0))
                dev->rx_fifo_size = 2048;
        if (emac_read_uint_prop(np, "tx-fifo-size", &dev->tx_fifo_size, 0))
@@ -2718,7 +2715,6 @@ static const struct net_device_ops emac_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = emac_set_mac_address,
        .ndo_start_xmit         = emac_start_xmit,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static const struct net_device_ops emac_gige_netdev_ops = {
@@ -2891,6 +2887,10 @@ static int emac_probe(struct platform_device *ofdev)
                ndev->netdev_ops = &emac_netdev_ops;
        ndev->ethtool_ops = &emac_ethtool_ops;
 
+       /* MTU range: 46 - 1500 or whatever is in OF */
+       ndev->min_mtu = EMAC_MIN_MTU;
+       ndev->max_mtu = dev->max_mtu;
+
        netif_carrier_off(ndev);
 
        err = register_netdev(ndev);
index ebe60719e489cd1fbdc12248ee48eed6d0979fd4..4a81c892fc3142af7e271304a5975c64adff2b88 100644 (file)
@@ -1349,9 +1349,6 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
        int i, rc;
        int need_restart = 0;
 
-       if (new_mtu < IBMVETH_MIN_MTU)
-               return -EINVAL;
-
        for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
                if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size)
                        break;
@@ -1551,6 +1548,9 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
                netdev->hw_features |= NETIF_F_TSO;
        }
 
+       netdev->min_mtu = IBMVETH_MIN_MTU;
+       netdev->max_mtu = ETH_MAX_MTU;
+
        memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN);
 
        if (firmware_has_feature(FW_FEATURE_CMO))
index 5f44c5520fbc86bd9076cc220906e0a4cdee4e90..d54405b4610964967ca5055ab1495f8d1c1675d4 100644 (file)
@@ -902,17 +902,6 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p)
        return 0;
 }
 
-static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu)
-{
-       struct ibmvnic_adapter *adapter = netdev_priv(netdev);
-
-       if (new_mtu > adapter->req_mtu || new_mtu < adapter->min_mtu)
-               return -EINVAL;
-
-       netdev->mtu = new_mtu;
-       return 0;
-}
-
 static void ibmvnic_tx_timeout(struct net_device *dev)
 {
        struct ibmvnic_adapter *adapter = netdev_priv(dev);
@@ -1029,7 +1018,6 @@ static const struct net_device_ops ibmvnic_netdev_ops = {
        .ndo_set_rx_mode        = ibmvnic_set_multi,
        .ndo_set_mac_address    = ibmvnic_set_mac,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = ibmvnic_change_mtu,
        .ndo_tx_timeout         = ibmvnic_tx_timeout,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ibmvnic_netpoll_controller,
@@ -2640,10 +2628,12 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq,
                break;
        case MIN_MTU:
                adapter->min_mtu = be64_to_cpu(crq->query_capability.number);
+               netdev->min_mtu = adapter->min_mtu;
                netdev_dbg(netdev, "min_mtu = %lld\n", adapter->min_mtu);
                break;
        case MAX_MTU:
                adapter->max_mtu = be64_to_cpu(crq->query_capability.number);
+               netdev->max_mtu = adapter->max_mtu;
                netdev_dbg(netdev, "max_mtu = %lld\n", adapter->max_mtu);
                break;
        case MAX_MULTICAST_FILTERS:
@@ -3669,6 +3659,8 @@ static void handle_crq_init_rsp(struct work_struct *work)
 
        netdev->real_num_tx_queues = adapter->req_tx_queues;
        netdev->mtu = adapter->req_mtu;
+       netdev->min_mtu = adapter->min_mtu;
+       netdev->max_mtu = adapter->max_mtu;
 
        if (adapter->failover) {
                adapter->failover = false;
index 068789e694c9b310ca6fd541a2be90f6c5059e36..25c6dfd500b4cde27310305770074deac6487b06 100644 (file)
@@ -2286,14 +2286,6 @@ static int e100_set_mac_address(struct net_device *netdev, void *p)
        return 0;
 }
 
-static int e100_change_mtu(struct net_device *netdev, int new_mtu)
-{
-       if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
-               return -EINVAL;
-       netdev->mtu = new_mtu;
-       return 0;
-}
-
 static int e100_asf(struct nic *nic)
 {
        /* ASF can be enabled from eeprom */
@@ -2834,7 +2826,6 @@ static const struct net_device_ops e100_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = e100_set_multicast_list,
        .ndo_set_mac_address    = e100_set_mac_address,
-       .ndo_change_mtu         = e100_change_mtu,
        .ndo_do_ioctl           = e100_do_ioctl,
        .ndo_tx_timeout         = e100_tx_timeout,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index f42129d09e2c23ba9fdb5cde890d50ecb7166a42..33076fa9800298aa4fb4a19d1feae234a5c20b04 100644 (file)
@@ -1085,6 +1085,10 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
            hw->subsystem_vendor_id != PCI_VENDOR_ID_VMWARE)
                netdev->priv_flags |= IFF_UNICAST_FLT;
 
+       /* MTU range: 46 - 16110 */
+       netdev->min_mtu = ETH_ZLEN - ETH_HLEN;
+       netdev->max_mtu = MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
+
        adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
 
        /* initialize eeprom parameters */
@@ -3549,13 +3553,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
-       int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
-
-       if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
-           (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-               e_err(probe, "Invalid MTU setting\n");
-               return -EINVAL;
-       }
+       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
        /* Adapter-specific max frame size limits. */
        switch (hw->mac_type) {
index 7017281ba2dc6355449c7970e6f4f3dabd3fb65d..8759d9236930fd8942b76c176ff4f4d4137b7555 100644 (file)
@@ -5974,19 +5974,12 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
        int max_frame = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
 
        /* Jumbo frame support */
-       if ((max_frame > (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)) &&
+       if ((new_mtu > ETH_DATA_LEN) &&
            !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
                e_err("Jumbo Frames not supported.\n");
                return -EINVAL;
        }
 
-       /* Supported frame sizes */
-       if ((new_mtu < (VLAN_ETH_ZLEN + ETH_FCS_LEN)) ||
-           (max_frame > adapter->max_hw_frame_size)) {
-               e_err("Unsupported MTU setting\n");
-               return -EINVAL;
-       }
-
        /* Jumbo frame workaround on 82579 and newer requires CRC be stripped */
        if ((adapter->hw.mac.type >= e1000_pch2lan) &&
            !(adapter->flags2 & FLAG2_CRC_STRIPPING) &&
@@ -7187,6 +7180,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                netdev->vlan_features |= NETIF_F_HIGHDMA;
        }
 
+       /* MTU range: 68 - max_hw_frame_size */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = adapter->max_hw_frame_size -
+                         (VLAN_ETH_HLEN + ETH_FCS_LEN);
+
        if (e1000e_enable_mng_pass_thru(&adapter->hw))
                adapter->flags |= FLAG_MNG_PT_ENABLED;
 
index 05629381be6be5de004680f6f27fd5b577851e63..bc5ef6eb3dd6ed82786cfe65b6bd9bebaec6b081 100644 (file)
@@ -706,16 +706,6 @@ static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        return err;
 }
 
-static int fm10k_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu < 68 || new_mtu > FM10K_MAX_JUMBO_FRAME_SIZE)
-               return -EINVAL;
-
-       dev->mtu = new_mtu;
-
-       return 0;
-}
-
 /**
  * fm10k_tx_timeout - Respond to a Tx Hang
  * @netdev: network interface device structure
@@ -1405,7 +1395,6 @@ static const struct net_device_ops fm10k_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_start_xmit         = fm10k_xmit_frame,
        .ndo_set_mac_address    = fm10k_set_mac,
-       .ndo_change_mtu         = fm10k_change_mtu,
        .ndo_tx_timeout         = fm10k_tx_timeout,
        .ndo_vlan_rx_add_vid    = fm10k_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = fm10k_vlan_rx_kill_vid,
@@ -1490,5 +1479,9 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
 
        dev->hw_features |= hw_features;
 
+       /* MTU range: 68 - 15342 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = FM10K_MAX_JUMBO_FRAME_SIZE;
+
        return dev;
 }
index 6d61e443bdf863a4fa9a71df725bf5de57a412c6..5a6f8518b4e1fcc6a3cad42581994e58dbf33ddb 100644 (file)
@@ -608,6 +608,8 @@ struct i40e_q_vector {
        unsigned long hung_detected; /* Set/Reset for hung_detection logic */
 
        cpumask_t affinity_mask;
+       struct irq_affinity_notify affinity_notify;
+
        struct rcu_head rcu;    /* to avoid race with update stats on free */
        char name[I40E_INT_NAME_STR_LEN];
        bool arm_wb_state;
@@ -729,8 +731,6 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
 struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
                                u16 uplink, u32 param1);
 int i40e_vsi_release(struct i40e_vsi *vsi);
-struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type,
-                                struct i40e_vsi *start_vsi);
 #ifdef I40E_FCOE
 void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
                              struct i40e_vsi_context *ctxt,
index 250db0b244b7677107ca1c56df23c23789e80fee..7fe72abc0b4a817afd99d57516b49b573f25bed5 100644 (file)
@@ -287,6 +287,7 @@ void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset)
                        }
                        cdev->client->ops->close(&cdev->lan_info, cdev->client,
                                                 reset);
+                       clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
                        i40e_client_release_qvlist(&cdev->lan_info);
                }
        }
@@ -405,37 +406,6 @@ int i40e_vf_client_capable(struct i40e_pf *pf, u32 vf_id,
        return capable;
 }
 
-/**
- * i40e_vsi_lookup - finds a matching VSI from the PF list starting at start_vsi
- * @pf: board private structure
- * @type: vsi type
- * @start_vsi: a VSI pointer from where to start the search
- *
- * Returns non NULL on success or NULL for failure
- **/
-struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf,
-                                enum i40e_vsi_type type,
-                                struct i40e_vsi *start_vsi)
-{
-       struct i40e_vsi *vsi;
-       int i = 0;
-
-       if (start_vsi) {
-               for (i = 0; i < pf->num_alloc_vsi; i++) {
-                       vsi = pf->vsi[i];
-                       if (vsi == start_vsi)
-                               break;
-               }
-       }
-       for (; i < pf->num_alloc_vsi; i++) {
-               vsi = pf->vsi[i];
-               if (vsi && vsi->type == type)
-                       return vsi;
-       }
-
-       return NULL;
-}
-
 /**
  * i40e_client_add_instance - add a client instance struct to the instance list
  * @pf: pointer to the board struct
@@ -565,7 +535,7 @@ void i40e_client_subtask(struct i40e_pf *pf)
                        if (test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state))
                                continue;
                } else {
-                       dev_warn(&pf->pdev->dev, "This client %s is being instanciated at probe\n",
+                       dev_warn(&pf->pdev->dev, "This client %s is being instantiated at probe\n",
                                 client->name);
                }
 
@@ -575,29 +545,25 @@ void i40e_client_subtask(struct i40e_pf *pf)
                        continue;
 
                if (!existing) {
-                       /* Also up the ref_cnt for no. of instances of this
-                        * client.
-                        */
-                       atomic_inc(&client->ref_cnt);
                        dev_info(&pf->pdev->dev, "Added instance of Client %s to PF%d bus=0x%02x func=0x%02x\n",
                                 client->name, pf->hw.pf_id,
                                 pf->hw.bus.device, pf->hw.bus.func);
                }
 
                mutex_lock(&i40e_client_instance_mutex);
-               /* Send an Open request to the client */
-               atomic_inc(&cdev->ref_cnt);
-               if (client->ops && client->ops->open)
-                       ret = client->ops->open(&cdev->lan_info, client);
-               atomic_dec(&cdev->ref_cnt);
-               if (!ret) {
-                       set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
-               } else {
-                       /* remove client instance */
-                       mutex_unlock(&i40e_client_instance_mutex);
-                       i40e_client_del_instance(pf, client);
-                       atomic_dec(&client->ref_cnt);
-                       continue;
+               if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED,
+                             &cdev->state)) {
+                       /* Send an Open request to the client */
+                       if (client->ops && client->ops->open)
+                               ret = client->ops->open(&cdev->lan_info,
+                                                       client);
+                       if (!ret) {
+                               set_bit(__I40E_CLIENT_INSTANCE_OPENED,
+                                       &cdev->state);
+                       } else {
+                               /* remove client instance */
+                               i40e_client_del_instance(pf, client);
+                       }
                }
                mutex_unlock(&i40e_client_instance_mutex);
        }
@@ -694,10 +660,6 @@ static int i40e_client_release(struct i40e_client *client)
                        continue;
                pf = (struct i40e_pf *)cdev->lan_info.pf;
                if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
-                       if (atomic_read(&cdev->ref_cnt) > 0) {
-                               ret = I40E_ERR_NOT_READY;
-                               goto out;
-                       }
                        if (client->ops && client->ops->close)
                                client->ops->close(&cdev->lan_info, client,
                                                   false);
@@ -710,11 +672,9 @@ static int i40e_client_release(struct i40e_client *client)
                }
                /* delete the client instance from the list */
                list_move(&cdev->list, &cdevs_tmp);
-               atomic_dec(&client->ref_cnt);
                dev_info(&pf->pdev->dev, "Deleted client instance of Client %s\n",
                         client->name);
        }
-out:
        mutex_unlock(&i40e_client_instance_mutex);
 
        /* free the client device and release its vsi */
@@ -1040,17 +1000,10 @@ int i40e_unregister_client(struct i40e_client *client)
                ret = -ENODEV;
                goto out;
        }
-       if (atomic_read(&client->ref_cnt) == 0) {
-               clear_bit(__I40E_CLIENT_REGISTERED, &client->state);
-               list_del(&client->list);
-               pr_info("i40e: Unregistered client %s with return code %d\n",
-                       client->name, ret);
-       } else {
-               ret = I40E_ERR_NOT_READY;
-               pr_err("i40e: Client %s failed unregister - client has open instances\n",
-                      client->name);
-       }
-
+       clear_bit(__I40E_CLIENT_REGISTERED, &client->state);
+       list_del(&client->list);
+       pr_info("i40e: Unregistered client %s with return code %d\n",
+               client->name, ret);
 out:
        mutex_unlock(&i40e_client_mutex);
        return ret;
index 38a6c36a6a0e3bfeeeb422d08ae6240d6dca3cde..528bd79b05fecc68d981ea08b144d9898c6aaaa0 100644 (file)
@@ -203,8 +203,6 @@ struct i40e_client_instance {
        struct i40e_info lan_info;
        struct i40e_client *client;
        unsigned long  state;
-       /* A count of all the in-progress calls to the client */
-       atomic_t ref_cnt;
 };
 
 struct i40e_client {
index 2154a34c1dd804e10c0905ac63718ce642643dec..a47594603d69c75e0e91d0c5a8cd2683e0e852d4 100644 (file)
@@ -1849,7 +1849,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
        else
                hw_link_info->crc_enable = false;
 
-       if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_ENABLE))
+       if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_IS_ENABLED))
                hw_link_info->lse_enable = true;
        else
                hw_link_info->lse_enable = false;
@@ -2494,7 +2494,10 @@ i40e_status i40e_update_link_info(struct i40e_hw *hw)
        if (status)
                return status;
 
-       if (hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) {
+       /* extra checking needed to ensure link info to user is timely */
+       if ((hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) &&
+           ((hw->phy.link_info.link_info & I40E_AQ_LINK_UP) ||
+            !(hw->phy.link_info_old.link_info & I40E_AQ_LINK_UP))) {
                status = i40e_aq_get_phy_capabilities(hw, false, false,
                                                      &abilities, NULL);
                if (status)
index 0c1875b5b16d2d79839cf6f85d5194741ffb697e..0354632fe2f8dddf2729d473b40c51911e939a96 100644 (file)
@@ -1210,24 +1210,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                        dev_info(&pf->pdev->dev,
                                 "dump debug fwdata <cluster_id> <table_id> <index>\n");
                }
-
-       } else if (strncmp(cmd_buf, "msg_enable", 10) == 0) {
-               u32 level;
-               cnt = sscanf(&cmd_buf[10], "%i", &level);
-               if (cnt) {
-                       if (I40E_DEBUG_USER & level) {
-                               pf->hw.debug_mask = level;
-                               dev_info(&pf->pdev->dev,
-                                        "set hw.debug_mask = 0x%08x\n",
-                                        pf->hw.debug_mask);
-                       }
-                       pf->msg_enable = level;
-                       dev_info(&pf->pdev->dev, "set msg_enable = 0x%08x\n",
-                                pf->msg_enable);
-               } else {
-                       dev_info(&pf->pdev->dev, "msg_enable = 0x%08x\n",
-                                pf->msg_enable);
-               }
        } else if (strncmp(cmd_buf, "pfr", 3) == 0) {
                dev_info(&pf->pdev->dev, "debugfs: forcing PFR\n");
                i40e_do_reset_safe(pf, BIT(__I40E_PF_RESET_REQUESTED));
@@ -1644,7 +1626,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                dev_info(&pf->pdev->dev, "  dump desc aq\n");
                dev_info(&pf->pdev->dev, "  dump reset stats\n");
                dev_info(&pf->pdev->dev, "  dump debug fwdata <cluster_id> <table_id> <index>\n");
-               dev_info(&pf->pdev->dev, "  msg_enable [level]\n");
                dev_info(&pf->pdev->dev, "  read <reg>\n");
                dev_info(&pf->pdev->dev, "  write <reg> <value>\n");
                dev_info(&pf->pdev->dev, "  clear_stats vsi [seid]\n");
index 92bc8846f1ba991abea8de574efefb340d121e95..fb4fb524eab22ddfd614b04b86f815961d00aba0 100644 (file)
@@ -104,7 +104,7 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {
  * The PF_STATs are appended to the netdev stats only when ethtool -S
  * is queried on the base PF netdev, not on the VMDq or FCoE netdev.
  */
-static struct i40e_stats i40e_gstrings_stats[] = {
+static const struct i40e_stats i40e_gstrings_stats[] = {
        I40E_PF_STAT("rx_bytes", stats.eth.rx_bytes),
        I40E_PF_STAT("tx_bytes", stats.eth.tx_bytes),
        I40E_PF_STAT("rx_unicast", stats.eth.rx_unicast),
@@ -978,6 +978,10 @@ static u32 i40e_get_msglevel(struct net_device *netdev)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_pf *pf = np->vsi->back;
+       u32 debug_mask = pf->hw.debug_mask;
+
+       if (debug_mask)
+               netdev_info(netdev, "i40e debug_mask: 0x%08X\n", debug_mask);
 
        return pf->msg_enable;
 }
@@ -989,7 +993,8 @@ static void i40e_set_msglevel(struct net_device *netdev, u32 data)
 
        if (I40E_DEBUG_USER & data)
                pf->hw.debug_mask = data;
-       pf->msg_enable = data;
+       else
+               pf->msg_enable = data;
 }
 
 static int i40e_get_regs_len(struct net_device *netdev)
index 31c97e3937a4238f879ac250f96107ac01088f1c..d78a4dc7b00b6190a4a20670151ea1498ac4a43a 100644 (file)
@@ -41,7 +41,7 @@ static const char i40e_driver_string[] =
 
 #define DRV_VERSION_MAJOR 1
 #define DRV_VERSION_MINOR 6
-#define DRV_VERSION_BUILD 16
+#define DRV_VERSION_BUILD 21
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
             __stringify(DRV_VERSION_MINOR) "." \
             __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -93,8 +93,8 @@ MODULE_DEVICE_TABLE(pci, i40e_pci_tbl);
 
 #define I40E_MAX_VF_COUNT 128
 static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+module_param(debug, uint, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX)");
 
 MODULE_AUTHOR("Intel Corporation, <e1000-devel@lists.sourceforge.net>");
 MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver");
@@ -1286,39 +1286,6 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
        return -ENOENT;
 }
 
-/**
- * i40e_rm_default_mac_filter - Remove the default MAC filter set by NVM
- * @vsi: the PF Main VSI - inappropriate for any other VSI
- * @macaddr: the MAC address
- *
- * Remove whatever filter the firmware set up so the driver can manage
- * its own filtering intelligently.
- **/
-static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)
-{
-       struct i40e_aqc_remove_macvlan_element_data element;
-       struct i40e_pf *pf = vsi->back;
-
-       /* Only appropriate for the PF main VSI */
-       if (vsi->type != I40E_VSI_MAIN)
-               return;
-
-       memset(&element, 0, sizeof(element));
-       ether_addr_copy(element.mac_addr, macaddr);
-       element.vlan_tag = 0;
-       /* Ignore error returns, some firmware does it this way... */
-       element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
-       i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
-
-       memset(&element, 0, sizeof(element));
-       ether_addr_copy(element.mac_addr, macaddr);
-       element.vlan_tag = 0;
-       /* ...and some firmware does it this way. */
-       element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
-                       I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
-       i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
-}
-
 /**
  * i40e_add_filter - Add a mac/vlan filter to the VSI
  * @vsi: the VSI to be searched
@@ -2239,13 +2206,8 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)
 static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
        struct i40e_vsi *vsi = np->vsi;
 
-       /* MTU < 68 is an error and causes problems on some kernels */
-       if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER))
-               return -EINVAL;
-
        netdev_info(netdev, "changing MTU from %d to %d\n",
                    netdev->mtu, new_mtu);
        netdev->mtu = new_mtu;
@@ -3321,6 +3283,33 @@ static irqreturn_t i40e_msix_clean_rings(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+/**
+ * i40e_irq_affinity_notify - Callback for affinity changes
+ * @notify: context as to what irq was changed
+ * @mask: the new affinity mask
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * so that we may register to receive changes to the irq affinity masks.
+ **/
+static void i40e_irq_affinity_notify(struct irq_affinity_notify *notify,
+                                    const cpumask_t *mask)
+{
+       struct i40e_q_vector *q_vector =
+               container_of(notify, struct i40e_q_vector, affinity_notify);
+
+       q_vector->affinity_mask = *mask;
+}
+
+/**
+ * i40e_irq_affinity_release - Callback for affinity notifier release
+ * @ref: internal core kernel usage
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * to inform the current notification subscriber that they will no longer
+ * receive notifications.
+ **/
+static void i40e_irq_affinity_release(struct kref *ref) {}
+
 /**
  * i40e_vsi_request_irq_msix - Initialize MSI-X interrupts
  * @vsi: the VSI being configured
@@ -3336,10 +3325,13 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
        int rx_int_idx = 0;
        int tx_int_idx = 0;
        int vector, err;
+       int irq_num;
 
        for (vector = 0; vector < q_vectors; vector++) {
                struct i40e_q_vector *q_vector = vsi->q_vectors[vector];
 
+               irq_num = pf->msix_entries[base + vector].vector;
+
                if (q_vector->tx.ring && q_vector->rx.ring) {
                        snprintf(q_vector->name, sizeof(q_vector->name) - 1,
                                 "%s-%s-%d", basename, "TxRx", rx_int_idx++);
@@ -3354,7 +3346,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
                        /* skip this unused q_vector */
                        continue;
                }
-               err = request_irq(pf->msix_entries[base + vector].vector,
+               err = request_irq(irq_num,
                                  vsi->irq_handler,
                                  0,
                                  q_vector->name,
@@ -3364,9 +3356,13 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
                                 "MSIX request_irq failed, error: %d\n", err);
                        goto free_queue_irqs;
                }
+
+               /* register for affinity change notifications */
+               q_vector->affinity_notify.notify = i40e_irq_affinity_notify;
+               q_vector->affinity_notify.release = i40e_irq_affinity_release;
+               irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
                /* assign the mask for this irq */
-               irq_set_affinity_hint(pf->msix_entries[base + vector].vector,
-                                     &q_vector->affinity_mask);
+               irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
        }
 
        vsi->irqs_ready = true;
@@ -3375,10 +3371,10 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
 free_queue_irqs:
        while (vector) {
                vector--;
-               irq_set_affinity_hint(pf->msix_entries[base + vector].vector,
-                                     NULL);
-               free_irq(pf->msix_entries[base + vector].vector,
-                        &(vsi->q_vectors[vector]));
+               irq_num = pf->msix_entries[base + vector].vector;
+               irq_set_affinity_notifier(irq_num, NULL);
+               irq_set_affinity_hint(irq_num, NULL);
+               free_irq(irq_num, &vsi->q_vectors[vector]);
        }
        return err;
 }
@@ -4017,19 +4013,23 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi)
 
                vsi->irqs_ready = false;
                for (i = 0; i < vsi->num_q_vectors; i++) {
-                       u16 vector = i + base;
+                       int irq_num;
+                       u16 vector;
+
+                       vector = i + base;
+                       irq_num = pf->msix_entries[vector].vector;
 
                        /* free only the irqs that were actually requested */
                        if (!vsi->q_vectors[i] ||
                            !vsi->q_vectors[i]->num_ringpairs)
                                continue;
 
+                       /* clear the affinity notifier in the IRQ descriptor */
+                       irq_set_affinity_notifier(irq_num, NULL);
                        /* clear the affinity_mask in the IRQ descriptor */
-                       irq_set_affinity_hint(pf->msix_entries[vector].vector,
-                                             NULL);
-                       synchronize_irq(pf->msix_entries[vector].vector);
-                       free_irq(pf->msix_entries[vector].vector,
-                                vsi->q_vectors[i]);
+                       irq_set_affinity_hint(irq_num, NULL);
+                       synchronize_irq(irq_num);
+                       free_irq(irq_num, vsi->q_vectors[i]);
 
                        /* Tear down the interrupt queue link list
                         *
@@ -8345,8 +8345,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
 
                i40e_pf_config_rss(pf);
        }
-       dev_info(&pf->pdev->dev, "RSS count/HW max RSS count:  %d/%d\n",
-                pf->alloc_rss_size, pf->rss_size_max);
+       dev_info(&pf->pdev->dev, "User requested queue count/HW max RSS count:  %d/%d\n",
+                vsi->req_queue_pairs, pf->rss_size_max);
        return pf->alloc_rss_size;
 }
 
@@ -8489,15 +8489,6 @@ static int i40e_sw_init(struct i40e_pf *pf)
        int err = 0;
        int size;
 
-       pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE,
-                               (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK));
-       if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) {
-               if (I40E_DEBUG_USER & debug)
-                       pf->hw.debug_mask = debug;
-               pf->msg_enable = netif_msg_init((debug & ~I40E_DEBUG_USER),
-                                               I40E_DEFAULT_MSG_ENABLE);
-       }
-
        /* Set default capability flags */
        pf->flags = I40E_FLAG_RX_CSUM_ENABLED |
                    I40E_FLAG_MSI_ENABLED     |
@@ -9163,12 +9154,6 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
        if (vsi->type == I40E_VSI_MAIN) {
                SET_NETDEV_DEV(netdev, &pf->pdev->dev);
                ether_addr_copy(mac_addr, hw->mac.perm_addr);
-               /* The following steps are necessary to prevent reception
-                * of tagged packets - some older NVM configurations load a
-                * default a MAC-VLAN filter that accepts any tagged packet
-                * which must be replaced by a normal filter.
-                */
-               i40e_rm_default_mac_filter(vsi, mac_addr);
                spin_lock_bh(&vsi->mac_filter_list_lock);
                i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, true);
                spin_unlock_bh(&vsi->mac_filter_list_lock);
@@ -9198,6 +9183,11 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
        i40e_fcoe_config_netdev(netdev, vsi);
 #endif
 
+       /* MTU range: 68 - 9706 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = I40E_MAX_RXBUFFER -
+                         (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
        return 0;
 }
 
@@ -9681,8 +9671,6 @@ static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi)
        pf->vsi[pf->lan_vsi]->tc_config.enabled_tc = 0;
        pf->vsi[pf->lan_vsi]->seid = pf->main_vsi_seid;
        i40e_vsi_config_tc(pf->vsi[pf->lan_vsi], enabled_tc);
-       if (vsi->type == I40E_VSI_MAIN)
-               i40e_rm_default_mac_filter(vsi, pf->hw.mac.perm_addr);
 
        /* assign it some queues */
        ret = i40e_alloc_rings(vsi);
@@ -10806,10 +10794,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        mutex_init(&hw->aq.asq_mutex);
        mutex_init(&hw->aq.arq_mutex);
 
-       if (debug != -1) {
-               pf->msg_enable = pf->hw.debug_mask;
-               pf->msg_enable = debug;
-       }
+       pf->msg_enable = netif_msg_init(debug,
+                                       NETIF_MSG_DRV |
+                                       NETIF_MSG_PROBE |
+                                       NETIF_MSG_LINK);
+       if (debug < -1)
+               pf->hw.debug_mask = debug;
 
        /* do a special CORER for clearing PXE mode once at init */
        if (hw->revision_id == 0 &&
@@ -10951,7 +10941,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        err = i40e_init_pf_dcb(pf);
        if (err) {
                dev_info(&pdev->dev, "DCB init failed %d, disabled\n", err);
-               pf->flags &= ~(I40E_FLAG_DCB_CAPABLE & I40E_FLAG_DCB_ENABLED);
+               pf->flags &= ~(I40E_FLAG_DCB_CAPABLE | I40E_FLAG_DCB_ENABLED);
                /* Continue without DCB enabled */
        }
 #endif /* CONFIG_I40E_DCB */
index 6287bf63c43cae5bb5d1c7e8428ad623aafc66b0..daade4fe80d69e183ccdfc0e3c15eab765e2e848 100644 (file)
@@ -122,7 +122,6 @@ static int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data,
        struct device *dev;
        dma_addr_t dma;
        u32 td_cmd = 0;
-       u16 delay = 0;
        u16 i;
 
        /* find existing FDIR VSI */
@@ -137,15 +136,11 @@ static int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data,
        dev = tx_ring->dev;
 
        /* we need two descriptors to add/del a filter and we can wait */
-       do {
-               if (I40E_DESC_UNUSED(tx_ring) > 1)
-                       break;
+       for (i = I40E_FD_CLEAN_DELAY; I40E_DESC_UNUSED(tx_ring) < 2; i--) {
+               if (!i)
+                       return -EAGAIN;
                msleep_interruptible(1);
-               delay++;
-       } while (delay < I40E_FD_CLEAN_DELAY);
-
-       if (!(I40E_DESC_UNUSED(tx_ring) > 1))
-               return -EAGAIN;
+       }
 
        dma = dma_map_single(dev, raw_packet,
                             I40E_FDIR_MAX_RAW_PACKET_SIZE, DMA_TO_DEVICE);
@@ -335,22 +330,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
        return err ? -EOPNOTSUPP : 0;
 }
 
-/**
- * i40e_add_del_fdir_sctpv4 - Add/Remove SCTPv4 Flow Director filters for
- * a specific flow spec
- * @vsi: pointer to the targeted VSI
- * @fd_data: the flow director data required for the FDir descriptor
- * @add: true adds a filter, false removes it
- *
- * Returns 0 if the filters were successfully added or removed
- **/
-static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
-                                   struct i40e_fdir_filter *fd_data,
-                                   bool add)
-{
-       return -EOPNOTSUPP;
-}
-
 #define I40E_IP_DUMMY_PACKET_LEN 34
 /**
  * i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for
@@ -433,12 +412,6 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
        case UDP_V4_FLOW:
                ret = i40e_add_del_fdir_udpv4(vsi, input, add);
                break;
-       case SCTP_V4_FLOW:
-               ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
-               break;
-       case IPV4_FLOW:
-               ret = i40e_add_del_fdir_ipv4(vsi, input, add);
-               break;
        case IP_USER_FLOW:
                switch (input->ip4_proto) {
                case IPPROTO_TCP:
@@ -447,15 +420,16 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
                case IPPROTO_UDP:
                        ret = i40e_add_del_fdir_udpv4(vsi, input, add);
                        break;
-               case IPPROTO_SCTP:
-                       ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
-                       break;
-               default:
+               case IPPROTO_IP:
                        ret = i40e_add_del_fdir_ipv4(vsi, input, add);
                        break;
+               default:
+                       /* We cannot support masking based on protocol */
+                       goto unsupported_flow;
                }
                break;
        default:
+unsupported_flow:
                dev_info(&pf->pdev->dev, "Could not specify spec type %d\n",
                         input->flow_type);
                ret = -EINVAL;
@@ -1246,7 +1220,6 @@ bool i40e_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
                 * because each write-back erases this info.
                 */
                rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
-               rx_desc->read.hdr_addr = 0;
 
                rx_desc++;
                bi++;
@@ -1767,7 +1740,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
        while (likely(total_rx_packets < budget)) {
                union i40e_rx_desc *rx_desc;
                struct sk_buff *skb;
-               u32 rx_status;
                u16 vlan_tag;
                u8 rx_ptype;
                u64 qword;
@@ -1781,21 +1753,13 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
 
                rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean);
 
-               qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-               rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-                          I40E_RXD_QW1_PTYPE_SHIFT;
-               rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
-                           I40E_RXD_QW1_STATUS_SHIFT;
-
-               if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
-                       break;
-
                /* status_error_len will always be zero for unused descriptors
                 * because it's cleared in cleanup, and overlaps with hdr_addr
                 * which is always zero because packet split isn't used, if the
                 * hardware wrote DD then it will be non-zero
                 */
-               if (!rx_desc->wb.qword1.status_error_len)
+               if (!i40e_test_staterr(rx_desc,
+                                      BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
                        break;
 
                /* This memory barrier is needed to keep us from reading
@@ -1829,6 +1793,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
                /* probably a little skewed due to removing CRC */
                total_rx_bytes += skb->len;
 
+               qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+               rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+                          I40E_RXD_QW1_PTYPE_SHIFT;
+
                /* populate checksum, VLAN, and protocol */
                i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
 
@@ -2025,12 +1993,25 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
 
        /* If work not completed, return budget and polling will return */
        if (!clean_complete) {
+               const cpumask_t *aff_mask = &q_vector->affinity_mask;
+               int cpu_id = smp_processor_id();
+
+               /* It is possible that the interrupt affinity has changed but,
+                * if the cpu is pegged at 100%, polling will never exit while
+                * traffic continues and the interrupt will be stuck on this
+                * cpu.  We check to make sure affinity is correct before we
+                * continue to poll, otherwise we must stop polling so the
+                * interrupt can move to the correct cpu.
+                */
+               if (likely(cpumask_test_cpu(cpu_id, aff_mask) ||
+                          !(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))) {
 tx_only:
-               if (arm_wb) {
-                       q_vector->tx.ring[0].tx_stats.tx_force_wb++;
-                       i40e_enable_wb_on_itr(vsi, q_vector);
+                       if (arm_wb) {
+                               q_vector->tx.ring[0].tx_stats.tx_force_wb++;
+                               i40e_enable_wb_on_itr(vsi, q_vector);
+                       }
+                       return budget;
                }
-               return budget;
        }
 
        if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
@@ -2038,11 +2019,18 @@ tx_only:
 
        /* Work is done so exit the polling mode and re-enable the interrupt */
        napi_complete_done(napi, work_done);
-       if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) {
-               i40e_update_enable_itr(vsi, q_vector);
-       } else { /* Legacy mode */
+
+       /* If we're prematurely stopping polling to fix the interrupt
+        * affinity we want to make sure polling starts back up so we
+        * issue a call to i40e_force_wb which triggers a SW interrupt.
+        */
+       if (!clean_complete)
+               i40e_force_wb(vsi, q_vector);
+       else if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))
                i40e_irq_dynamic_enable_icr0(vsi->back, false);
-       }
+       else
+               i40e_update_enable_itr(vsi, q_vector);
+
        return 0;
 }
 
index f861d3109d1a10ace23242f4d3779328a6a32539..974ba2baf6ea006d2f3dae4e7aa841e7bffb96d3 100644 (file)
@@ -165,6 +165,10 @@ struct i40e_virtchnl_vsi_resource {
 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF                0X00080000
 #define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM    0X00100000
 
+#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \
+                                   I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \
+                                   I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
+
 struct i40e_virtchnl_vf_resource {
        u16 num_vsis;
        u16 num_queue_pairs;
index 75f2a2cdd738592795e387473eefab6c81215dc5..e2d362238fd770238e9351ae4c7ea094095f7983 100644 (file)
@@ -705,7 +705,6 @@ bool i40evf_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
                 * because each write-back erases this info.
                 */
                rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
-               rx_desc->read.hdr_addr = 0;
 
                rx_desc++;
                bi++;
@@ -1209,7 +1208,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
        while (likely(total_rx_packets < budget)) {
                union i40e_rx_desc *rx_desc;
                struct sk_buff *skb;
-               u32 rx_status;
                u16 vlan_tag;
                u8 rx_ptype;
                u64 qword;
@@ -1223,21 +1221,13 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
 
                rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean);
 
-               qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-               rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-                          I40E_RXD_QW1_PTYPE_SHIFT;
-               rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
-                           I40E_RXD_QW1_STATUS_SHIFT;
-
-               if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
-                       break;
-
                /* status_error_len will always be zero for unused descriptors
                 * because it's cleared in cleanup, and overlaps with hdr_addr
                 * which is always zero because packet split isn't used, if the
                 * hardware wrote DD then it will be non-zero
                 */
-               if (!rx_desc->wb.qword1.status_error_len)
+               if (!i40e_test_staterr(rx_desc,
+                                      BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
                        break;
 
                /* This memory barrier is needed to keep us from reading
@@ -1271,6 +1261,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
                /* probably a little skewed due to removing CRC */
                total_rx_bytes += skb->len;
 
+               qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+               rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+                          I40E_RXD_QW1_PTYPE_SHIFT;
+
                /* populate checksum, VLAN, and protocol */
                i40evf_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
 
@@ -1461,12 +1455,24 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
 
        /* If work not completed, return budget and polling will return */
        if (!clean_complete) {
+               const cpumask_t *aff_mask = &q_vector->affinity_mask;
+               int cpu_id = smp_processor_id();
+
+               /* It is possible that the interrupt affinity has changed but,
+                * if the cpu is pegged at 100%, polling will never exit while
+                * traffic continues and the interrupt will be stuck on this
+                * cpu.  We check to make sure affinity is correct before we
+                * continue to poll, otherwise we must stop polling so the
+                * interrupt can move to the correct cpu.
+                */
+               if (likely(cpumask_test_cpu(cpu_id, aff_mask))) {
 tx_only:
-               if (arm_wb) {
-                       q_vector->tx.ring[0].tx_stats.tx_force_wb++;
-                       i40e_enable_wb_on_itr(vsi, q_vector);
+                       if (arm_wb) {
+                               q_vector->tx.ring[0].tx_stats.tx_force_wb++;
+                               i40e_enable_wb_on_itr(vsi, q_vector);
+                       }
+                       return budget;
                }
-               return budget;
        }
 
        if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
@@ -1474,7 +1480,16 @@ tx_only:
 
        /* Work is done so exit the polling mode and re-enable the interrupt */
        napi_complete_done(napi, work_done);
-       i40e_update_enable_itr(vsi, q_vector);
+
+       /* If we're prematurely stopping polling to fix the interrupt
+        * affinity we want to make sure polling starts back up so we
+        * issue a call to i40evf_force_wb which triggers a SW interrupt.
+        */
+       if (!clean_complete)
+               i40evf_force_wb(vsi, q_vector);
+       else
+               i40e_update_enable_itr(vsi, q_vector);
+
        return 0;
 }
 
index bd691ad86673d21bcd70600226126b36136a42c1..fc374f833aa9a930f2d119c306dd2547209884af 100644 (file)
@@ -162,6 +162,10 @@ struct i40e_virtchnl_vsi_resource {
 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF                0X00080000
 #define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM    0X00100000
 
+#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \
+                                   I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \
+                                   I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
+
 struct i40e_virtchnl_vf_resource {
        u16 num_vsis;
        u16 num_queue_pairs;
index c5fd724313c7f786bf1912dc200a5174e646eae1..fffe4cf2c20b302df75a830877719dc915254687 100644 (file)
@@ -107,7 +107,8 @@ struct i40e_q_vector {
        int v_idx;      /* vector index in list */
        char name[IFNAMSIZ + 9];
        bool arm_wb_state;
-       cpumask_var_t affinity_mask;
+       cpumask_t affinity_mask;
+       struct irq_affinity_notify affinity_notify;
 };
 
 /* Helper macros to switch between ints/sec and what the register uses.
index 14372810fc27aefc36ed1244641051eda34ec184..bcb1cafdf28a9ef149c1c72183b818395aeeab7e 100644 (file)
@@ -38,7 +38,7 @@ static const char i40evf_driver_string[] =
 
 #define DRV_VERSION_MAJOR 1
 #define DRV_VERSION_MINOR 6
-#define DRV_VERSION_BUILD 16
+#define DRV_VERSION_BUILD 21
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
             __stringify(DRV_VERSION_MINOR) "." \
             __stringify(DRV_VERSION_BUILD) \
@@ -495,6 +495,33 @@ static void i40evf_netpoll(struct net_device *netdev)
 }
 
 #endif
+/**
+ * i40evf_irq_affinity_notify - Callback for affinity changes
+ * @notify: context as to what irq was changed
+ * @mask: the new affinity mask
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * so that we may register to receive changes to the irq affinity masks.
+ **/
+static void i40evf_irq_affinity_notify(struct irq_affinity_notify *notify,
+                                      const cpumask_t *mask)
+{
+       struct i40e_q_vector *q_vector =
+               container_of(notify, struct i40e_q_vector, affinity_notify);
+
+       q_vector->affinity_mask = *mask;
+}
+
+/**
+ * i40evf_irq_affinity_release - Callback for affinity notifier release
+ * @ref: internal core kernel usage
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * to inform the current notification subscriber that they will no longer
+ * receive notifications.
+ **/
+static void i40evf_irq_affinity_release(struct kref *ref) {}
+
 /**
  * i40evf_request_traffic_irqs - Initialize MSI-X interrupts
  * @adapter: board private structure
@@ -507,6 +534,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
 {
        int vector, err, q_vectors;
        int rx_int_idx = 0, tx_int_idx = 0;
+       int irq_num;
 
        i40evf_irq_disable(adapter);
        /* Decrement for Other and TCP Timer vectors */
@@ -514,6 +542,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
 
        for (vector = 0; vector < q_vectors; vector++) {
                struct i40e_q_vector *q_vector = &adapter->q_vectors[vector];
+               irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
 
                if (q_vector->tx.ring && q_vector->rx.ring) {
                        snprintf(q_vector->name, sizeof(q_vector->name) - 1,
@@ -532,21 +561,23 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
                        /* skip this unused q_vector */
                        continue;
                }
-               err = request_irq(
-                       adapter->msix_entries[vector + NONQ_VECS].vector,
-                       i40evf_msix_clean_rings,
-                       0,
-                       q_vector->name,
-                       q_vector);
+               err = request_irq(irq_num,
+                                 i40evf_msix_clean_rings,
+                                 0,
+                                 q_vector->name,
+                                 q_vector);
                if (err) {
                        dev_info(&adapter->pdev->dev,
                                 "Request_irq failed, error: %d\n", err);
                        goto free_queue_irqs;
                }
+               /* register for affinity change notifications */
+               q_vector->affinity_notify.notify = i40evf_irq_affinity_notify;
+               q_vector->affinity_notify.release =
+                                                  i40evf_irq_affinity_release;
+               irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
                /* assign the mask for this irq */
-               irq_set_affinity_hint(
-                       adapter->msix_entries[vector + NONQ_VECS].vector,
-                       q_vector->affinity_mask);
+               irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
        }
 
        return 0;
@@ -554,11 +585,10 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
 free_queue_irqs:
        while (vector) {
                vector--;
-               irq_set_affinity_hint(
-                       adapter->msix_entries[vector + NONQ_VECS].vector,
-                       NULL);
-               free_irq(adapter->msix_entries[vector + NONQ_VECS].vector,
-                        &adapter->q_vectors[vector]);
+               irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+               irq_set_affinity_notifier(irq_num, NULL);
+               irq_set_affinity_hint(irq_num, NULL);
+               free_irq(irq_num, &adapter->q_vectors[vector]);
        }
        return err;
 }
@@ -599,16 +629,15 @@ static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)
  **/
 static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter)
 {
-       int i;
-       int q_vectors;
+       int vector, irq_num, q_vectors;
 
        q_vectors = adapter->num_msix_vectors - NONQ_VECS;
 
-       for (i = 0; i < q_vectors; i++) {
-               irq_set_affinity_hint(adapter->msix_entries[i+1].vector,
-                                     NULL);
-               free_irq(adapter->msix_entries[i+1].vector,
-                        &adapter->q_vectors[i]);
+       for (vector = 0; vector < q_vectors; vector++) {
+               irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+               irq_set_affinity_notifier(irq_num, NULL);
+               irq_set_affinity_hint(irq_num, NULL);
+               free_irq(irq_num, &adapter->q_vectors[vector]);
        }
 }
 
@@ -2133,10 +2162,6 @@ static struct net_device_stats *i40evf_get_stats(struct net_device *netdev)
 static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct i40evf_adapter *adapter = netdev_priv(netdev);
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-
-       if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER))
-               return -EINVAL;
 
        netdev->mtu = new_mtu;
        adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
@@ -2424,6 +2449,10 @@ static void i40evf_init_task(struct work_struct *work)
        i40evf_set_ethtool_ops(netdev);
        netdev->watchdog_timeo = 5 * HZ;
 
+       /* MTU range: 68 - 9710 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = I40E_MAX_RXBUFFER - (ETH_HLEN + ETH_FCS_LEN);
+
        if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
                dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n",
                         adapter->hw.mac.addr);
index 2688180a7acd76a89c9cf7de28af455da9f8f95d..8aee314332a87a9cfe696d8451aeb8b321b7411d 100644 (file)
 #define ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.3ac packet */
 
 /* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
-#define MAX_JUMBO_FRAME_SIZE   0x2600
+#define MAX_JUMBO_FRAME_SIZE           0x2600
+#define MAX_STD_JUMBO_FRAME_SIZE       9216
 
 /* PBA constants */
 #define E1000_PBA_34K 0x0022
index edc9a6ac5169328b3690672b47a699df8dc2d588..4feca69e583359cf15b9a6873a6098c3387a068f 100644 (file)
@@ -2468,6 +2468,10 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        netdev->priv_flags |= IFF_UNICAST_FLT;
 
+       /* MTU range: 68 - 9216 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
+
        adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
 
        /* before reading the NVM, reset the controller to put the device in a
@@ -5408,17 +5412,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
        struct pci_dev *pdev = adapter->pdev;
        int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
 
-       if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-               dev_err(&pdev->dev, "Invalid MTU setting\n");
-               return -EINVAL;
-       }
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9238
-       if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
-               dev_err(&pdev->dev, "MTU > 9216 not supported.\n");
-               return -EINVAL;
-       }
-
        /* adjust max frame to be at least the size of a standard frame */
        if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
                max_frame = ETH_FRAME_LEN + ETH_FCS_LEN;
index ee1ef08d7fc49df7ada655bfd8c39e83f4624695..f1789d192e2425e2fa37ca4d0550da3afde3541c 100644 (file)
@@ -85,7 +85,8 @@
 #define E1000_TXD_CMD_DEXT     0x20000000 /* Desc extension (0 = legacy) */
 #define E1000_TXD_STAT_DD      0x00000001 /* Desc Done */
 
-#define MAX_JUMBO_FRAME_SIZE   0x3F00
+#define MAX_JUMBO_FRAME_SIZE           0x3F00
+#define MAX_STD_JUMBO_FRAME_SIZE       9216
 
 /* 802.1q VLAN Packet Size */
 #define VLAN_TAG_SIZE          4    /* 802.3ac tag (not DMA'd) */
index 12bb877df86091f92716f1225e17a6b66bc1a4b4..810fcf7aa2c6a2df9cb415a6245085666a287fdc 100644 (file)
@@ -2356,16 +2356,6 @@ static int igbvf_change_mtu(struct net_device *netdev, int new_mtu)
        struct igbvf_adapter *adapter = netdev_priv(netdev);
        int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
-       if (new_mtu < 68 || new_mtu > INT_MAX - ETH_HLEN - ETH_FCS_LEN ||
-           max_frame > MAX_JUMBO_FRAME_SIZE)
-               return -EINVAL;
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
-       if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
-               dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n");
-               return -EINVAL;
-       }
-
        while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
                usleep_range(1000, 2000);
        /* igbvf_down has a dependency on max_frame_size */
@@ -2786,6 +2776,10 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                            NETIF_F_HW_VLAN_CTAG_RX |
                            NETIF_F_HW_VLAN_CTAG_TX;
 
+       /* MTU range: 68 - 9216 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
+
        /*reset the controller to put the device in a known good state */
        err = hw->mac.ops.reset_hw(hw);
        if (err) {
index 31f91459312f1757fcd795eb3cd512cd12911b59..5826b1ddedcfe1560de83fd5b24a6e36a4ced323 100644 (file)
@@ -487,6 +487,10 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                netdev->vlan_features |= NETIF_F_HIGHDMA;
        }
 
+       /* MTU range: 68 - 16114 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = IXGB_MAX_JUMBO_FRAME_SIZE - ETH_HLEN;
+
        /* make sure the EEPROM is good */
 
        if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
@@ -1619,18 +1623,6 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct ixgb_adapter *adapter = netdev_priv(netdev);
        int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
-       int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
-
-       /* MTU < 68 is an error for IPv4 traffic, just don't allow it */
-       if ((new_mtu < 68) ||
-           (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
-               netif_err(adapter, probe, adapter->netdev,
-                         "Invalid MTU setting %d\n", new_mtu);
-               return -EINVAL;
-       }
-
-       if (old_max_frame == max_frame)
-               return 0;
 
        if (netif_running(netdev))
                ixgb_down(adapter, true);
index bd93d823cc25eb6808fbe8a2262bbcf5e15af422..5e1f57c7ee1b095b8ace7c81a9412c420a119b56 100644 (file)
@@ -5012,24 +5012,23 @@ fwd_queue_err:
        return err;
 }
 
-static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter)
+static int ixgbe_upper_dev_walk(struct net_device *upper, void *data)
 {
-       struct net_device *upper;
-       struct list_head *iter;
-       int err;
-
-       netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-               if (netif_is_macvlan(upper)) {
-                       struct macvlan_dev *dfwd = netdev_priv(upper);
-                       struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
+       if (netif_is_macvlan(upper)) {
+               struct macvlan_dev *dfwd = netdev_priv(upper);
+               struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
 
-                       if (dfwd->fwd_priv) {
-                               err = ixgbe_fwd_ring_up(upper, vadapter);
-                               if (err)
-                                       continue;
-                       }
-               }
+               if (dfwd->fwd_priv)
+                       ixgbe_fwd_ring_up(upper, vadapter);
        }
+
+       return 0;
+}
+
+static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter)
+{
+       netdev_walk_all_upper_dev_rcu(adapter->netdev,
+                                     ixgbe_upper_dev_walk, NULL);
 }
 
 static void ixgbe_configure(struct ixgbe_adapter *adapter)
@@ -5448,12 +5447,25 @@ static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)
        spin_unlock(&adapter->fdir_perfect_lock);
 }
 
+static int ixgbe_disable_macvlan(struct net_device *upper, void *data)
+{
+       if (netif_is_macvlan(upper)) {
+               struct macvlan_dev *vlan = netdev_priv(upper);
+
+               if (vlan->fwd_priv) {
+                       netif_tx_stop_all_queues(upper);
+                       netif_carrier_off(upper);
+                       netif_tx_disable(upper);
+               }
+       }
+
+       return 0;
+}
+
 void ixgbe_down(struct ixgbe_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
        struct ixgbe_hw *hw = &adapter->hw;
-       struct net_device *upper;
-       struct list_head *iter;
        int i;
 
        /* signal that we are down to the interrupt handler */
@@ -5477,17 +5489,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
        netif_tx_disable(netdev);
 
        /* disable any upper devices */
-       netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-               if (netif_is_macvlan(upper)) {
-                       struct macvlan_dev *vlan = netdev_priv(upper);
-
-                       if (vlan->fwd_priv) {
-                               netif_tx_stop_all_queues(upper);
-                               netif_carrier_off(upper);
-                               netif_tx_disable(upper);
-                       }
-               }
-       }
+       netdev_walk_all_upper_dev_rcu(adapter->netdev,
+                                     ixgbe_disable_macvlan, NULL);
 
        ixgbe_irq_disable(adapter);
 
@@ -6049,11 +6052,6 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)
 static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-
-       /* MTU < 68 is an error and causes problems on some kernels */
-       if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
-               return -EINVAL;
 
        /*
         * For 82599EB we cannot allow legacy VFs to enable their receive
@@ -6062,7 +6060,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
         */
        if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
            (adapter->hw.mac.type == ixgbe_mac_82599EB) &&
-           (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)))
+           (new_mtu > ETH_DATA_LEN))
                e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n");
 
        e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
@@ -6728,6 +6726,18 @@ static void ixgbe_update_default_up(struct ixgbe_adapter *adapter)
 #endif
 }
 
+static int ixgbe_enable_macvlan(struct net_device *upper, void *data)
+{
+       if (netif_is_macvlan(upper)) {
+               struct macvlan_dev *vlan = netdev_priv(upper);
+
+               if (vlan->fwd_priv)
+                       netif_tx_wake_all_queues(upper);
+       }
+
+       return 0;
+}
+
 /**
  * ixgbe_watchdog_link_is_up - update netif_carrier status and
  *                             print link up message
@@ -6737,8 +6747,6 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
        struct ixgbe_hw *hw = &adapter->hw;
-       struct net_device *upper;
-       struct list_head *iter;
        u32 link_speed = adapter->link_speed;
        const char *speed_str;
        bool flow_rx, flow_tx;
@@ -6809,14 +6817,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
 
        /* enable any upper devices */
        rtnl_lock();
-       netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-               if (netif_is_macvlan(upper)) {
-                       struct macvlan_dev *vlan = netdev_priv(upper);
-
-                       if (vlan->fwd_priv)
-                               netif_tx_wake_all_queues(upper);
-               }
-       }
+       netdev_walk_all_upper_dev_rcu(adapter->netdev,
+                                     ixgbe_enable_macvlan, NULL);
        rtnl_unlock();
 
        /* update the default user priority for VFs */
@@ -8350,12 +8352,38 @@ static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter,
 }
 
 #ifdef CONFIG_NET_CLS_ACT
+struct upper_walk_data {
+       struct ixgbe_adapter *adapter;
+       u64 action;
+       int ifindex;
+       u8 queue;
+};
+
+static int get_macvlan_queue(struct net_device *upper, void *_data)
+{
+       if (netif_is_macvlan(upper)) {
+               struct macvlan_dev *dfwd = netdev_priv(upper);
+               struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
+               struct upper_walk_data *data = _data;
+               struct ixgbe_adapter *adapter = data->adapter;
+               int ifindex = data->ifindex;
+
+               if (vadapter && vadapter->netdev->ifindex == ifindex) {
+                       data->queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
+                       data->action = data->queue;
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
                                  u8 *queue, u64 *action)
 {
        unsigned int num_vfs = adapter->num_vfs, vf;
+       struct upper_walk_data data;
        struct net_device *upper;
-       struct list_head *iter;
 
        /* redirect to a SRIOV VF */
        for (vf = 0; vf < num_vfs; ++vf) {
@@ -8373,17 +8401,16 @@ static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
        }
 
        /* redirect to a offloaded macvlan netdev */
-       netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-               if (netif_is_macvlan(upper)) {
-                       struct macvlan_dev *dfwd = netdev_priv(upper);
-                       struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
-
-                       if (vadapter && vadapter->netdev->ifindex == ifindex) {
-                               *queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
-                               *action = *queue;
-                               return 0;
-                       }
-               }
+       data.adapter = adapter;
+       data.ifindex = ifindex;
+       data.action = 0;
+       data.queue = 0;
+       if (netdev_walk_all_upper_dev_rcu(adapter->netdev,
+                                         get_macvlan_queue, &data)) {
+               *action = data.action;
+               *queue = data.queue;
+
+               return 0;
        }
 
        return -EINVAL;
@@ -8410,7 +8437,7 @@ static int parse_tc_actions(struct ixgbe_adapter *adapter,
                }
 
                /* Redirect to a VF or a offloaded macvlan */
-               if (is_tcf_mirred_redirect(a)) {
+               if (is_tcf_mirred_egress_redirect(a)) {
                        int ifindex = tcf_mirred_ifindex(a);
 
                        err = handle_redirect_action(adapter, ifindex, queue,
@@ -9612,6 +9639,10 @@ skip_sriov:
        netdev->priv_flags |= IFF_UNICAST_FLT;
        netdev->priv_flags |= IFF_SUPP_NOFCS;
 
+       /* MTU range: 68 - 9710 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
+
 #ifdef CONFIG_IXGBE_DCB
        if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE)
                netdev->dcbnl_ops = &dcbnl_ops;
index 7eaac323404990073439d243e884801bee61db3c..d2775f032f74e7676abbd6b1abdaa4f4fce282ad 100644 (file)
@@ -3742,24 +3742,8 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
        struct ixgbevf_adapter *adapter = netdev_priv(netdev);
        struct ixgbe_hw *hw = &adapter->hw;
        int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-       int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
        int ret;
 
-       switch (adapter->hw.api_version) {
-       case ixgbe_mbox_api_11:
-       case ixgbe_mbox_api_12:
-               max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
-               break;
-       default:
-               if (adapter->hw.mac.type != ixgbe_mac_82599_vf)
-                       max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
-               break;
-       }
-
-       /* MTU < 68 is an error and causes problems on some kernels */
-       if ((new_mtu < 68) || (max_frame > max_possible_frame))
-               return -EINVAL;
-
        spin_lock_bh(&adapter->mbx_lock);
        /* notify the PF of our intent to use this size of frame */
        ret = hw->mac.ops.set_rlpml(hw, max_frame);
@@ -4104,6 +4088,23 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        netdev->priv_flags |= IFF_UNICAST_FLT;
 
+       /* MTU range: 68 - 1504 or 9710 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       switch (adapter->hw.api_version) {
+       case ixgbe_mbox_api_11:
+       case ixgbe_mbox_api_12:
+               netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE -
+                                 (ETH_HLEN + ETH_FCS_LEN);
+               break;
+       default:
+               if (adapter->hw.mac.type != ixgbe_mac_82599_vf)
+                       netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE -
+                                         (ETH_HLEN + ETH_FCS_LEN);
+               else
+                       netdev->max_mtu = ETH_DATA_LEN + ETH_FCS_LEN;
+               break;
+       }
+
        if (IXGBE_REMOVED(hw->hw_addr)) {
                err = -EIO;
                goto err_sw_init;
index 836ebd8ee768fc8083da04a45192eff81742a644..f9fcab54783c45b0ff49b3d3edc5077cf18401fa 100644 (file)
@@ -2357,14 +2357,6 @@ jme_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct jme_adapter *jme = netdev_priv(netdev);
 
-       if (new_mtu == jme->old_mtu)
-               return 0;
-
-       if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
-               ((new_mtu) < IPV6_MIN_MTU))
-               return -EINVAL;
-
-
        netdev->mtu = new_mtu;
        netdev_update_features(netdev);
 
@@ -3063,6 +3055,10 @@ jme_init_one(struct pci_dev *pdev,
        if (using_dac)
                netdev->features        |=      NETIF_F_HIGHDMA;
 
+       /* MTU range: 1280 - 9202*/
+       netdev->min_mtu = IPV6_MIN_MTU;
+       netdev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE - ETH_HLEN;
+
        SET_NETDEV_DEV(netdev, &pdev->dev);
        pci_set_drvdata(pdev, netdev);
 
index 1799fe1415df5070104edf4946a537e245c80176..cbeea915f02699696072d1da77c724588e5c3b0e 100644 (file)
@@ -1085,7 +1085,6 @@ static const struct net_device_ops korina_netdev_ops = {
        .ndo_set_rx_mode        = korina_multicast_list,
        .ndo_tx_timeout         = korina_tx_timeout,
        .ndo_do_ioctl           = korina_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 91e09d68b7e25ddd720aefdd7a79720e2e02ae4c..1a739d71f1c22ca33eb1d9b490761f5ddaaab070 100644 (file)
@@ -519,18 +519,16 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
 static int
 ltq_etop_change_mtu(struct net_device *dev, int new_mtu)
 {
-       int ret = eth_change_mtu(dev, new_mtu);
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       unsigned long flags;
 
-       if (!ret) {
-               struct ltq_etop_priv *priv = netdev_priv(dev);
-               unsigned long flags;
+       dev->mtu = new_mtu;
 
-               spin_lock_irqsave(&priv->lock, flags);
-               ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu,
-                       LTQ_ETOP_IGPLEN);
-               spin_unlock_irqrestore(&priv->lock, flags);
-       }
-       return ret;
+       spin_lock_irqsave(&priv->lock, flags);
+       ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu, LTQ_ETOP_IGPLEN);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
 }
 
 static int
index bf5cc55ba24cbe9aeb44352462dccb254117abed..8302c7e660ce27151b4823c71fab9a97a51456c1 100644 (file)
@@ -384,8 +384,6 @@ struct mv643xx_eth_private {
 
        struct net_device *dev;
 
-       struct phy_device *phy;
-
        struct timer_list mib_counters_timer;
        spinlock_t mib_counters_lock;
        struct mib_counters mib_counters;
@@ -1236,7 +1234,7 @@ static void mv643xx_eth_adjust_link(struct net_device *dev)
                     DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
                     DISABLE_AUTO_NEG_FOR_DUPLEX;
 
-       if (mp->phy->autoneg == AUTONEG_ENABLE) {
+       if (dev->phydev->autoneg == AUTONEG_ENABLE) {
                /* enable auto negotiation */
                pscr &= ~autoneg_disable;
                goto out_write;
@@ -1244,7 +1242,7 @@ static void mv643xx_eth_adjust_link(struct net_device *dev)
 
        pscr |= autoneg_disable;
 
-       if (mp->phy->speed == SPEED_1000) {
+       if (dev->phydev->speed == SPEED_1000) {
                /* force gigabit, half duplex not supported */
                pscr |= SET_GMII_SPEED_TO_1000;
                pscr |= SET_FULL_DUPLEX_MODE;
@@ -1253,12 +1251,12 @@ static void mv643xx_eth_adjust_link(struct net_device *dev)
 
        pscr &= ~SET_GMII_SPEED_TO_1000;
 
-       if (mp->phy->speed == SPEED_100)
+       if (dev->phydev->speed == SPEED_100)
                pscr |= SET_MII_SPEED_TO_100;
        else
                pscr &= ~SET_MII_SPEED_TO_100;
 
-       if (mp->phy->duplex == DUPLEX_FULL)
+       if (dev->phydev->duplex == DUPLEX_FULL)
                pscr |= SET_FULL_DUPLEX_MODE;
        else
                pscr &= ~SET_FULL_DUPLEX_MODE;
@@ -1497,55 +1495,69 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = {
 };
 
 static int
-mv643xx_eth_get_settings_phy(struct mv643xx_eth_private *mp,
-                            struct ethtool_cmd *cmd)
+mv643xx_eth_get_link_ksettings_phy(struct mv643xx_eth_private *mp,
+                                  struct ethtool_link_ksettings *cmd)
 {
+       struct net_device *dev = mp->dev;
        int err;
+       u32 supported, advertising;
 
-       err = phy_read_status(mp->phy);
+       err = phy_read_status(dev->phydev);
        if (err == 0)
-               err = phy_ethtool_gset(mp->phy, cmd);
+               err = phy_ethtool_ksettings_get(dev->phydev, cmd);
 
        /*
         * The MAC does not support 1000baseT_Half.
         */
-       cmd->supported &= ~SUPPORTED_1000baseT_Half;
-       cmd->advertising &= ~ADVERTISED_1000baseT_Half;
+       ethtool_convert_link_mode_to_legacy_u32(&supported,
+                                               cmd->link_modes.supported);
+       ethtool_convert_link_mode_to_legacy_u32(&advertising,
+                                               cmd->link_modes.advertising);
+       supported &= ~SUPPORTED_1000baseT_Half;
+       advertising &= ~ADVERTISED_1000baseT_Half;
+       ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+                                               supported);
+       ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+                                               advertising);
 
        return err;
 }
 
 static int
-mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp,
-                                struct ethtool_cmd *cmd)
+mv643xx_eth_get_link_ksettings_phyless(struct mv643xx_eth_private *mp,
+                                      struct ethtool_link_ksettings *cmd)
 {
        u32 port_status;
+       u32 supported, advertising;
 
        port_status = rdlp(mp, PORT_STATUS);
 
-       cmd->supported = SUPPORTED_MII;
-       cmd->advertising = ADVERTISED_MII;
+       supported = SUPPORTED_MII;
+       advertising = ADVERTISED_MII;
        switch (port_status & PORT_SPEED_MASK) {
        case PORT_SPEED_10:
-               ethtool_cmd_speed_set(cmd, SPEED_10);
+               cmd->base.speed = SPEED_10;
                break;
        case PORT_SPEED_100:
-               ethtool_cmd_speed_set(cmd, SPEED_100);
+               cmd->base.speed = SPEED_100;
                break;
        case PORT_SPEED_1000:
-               ethtool_cmd_speed_set(cmd, SPEED_1000);
+               cmd->base.speed = SPEED_1000;
                break;
        default:
-               cmd->speed = -1;
+               cmd->base.speed = -1;
                break;
        }
-       cmd->duplex = (port_status & FULL_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
-       cmd->port = PORT_MII;
-       cmd->phy_address = 0;
-       cmd->transceiver = XCVR_INTERNAL;
-       cmd->autoneg = AUTONEG_DISABLE;
-       cmd->maxtxpkt = 1;
-       cmd->maxrxpkt = 1;
+       cmd->base.duplex = (port_status & FULL_DUPLEX) ?
+               DUPLEX_FULL : DUPLEX_HALF;
+       cmd->base.port = PORT_MII;
+       cmd->base.phy_address = 0;
+       cmd->base.autoneg = AUTONEG_DISABLE;
+
+       ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+                                               supported);
+       ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+                                               advertising);
 
        return 0;
 }
@@ -1553,23 +1565,21 @@ mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp,
 static void
 mv643xx_eth_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-       struct mv643xx_eth_private *mp = netdev_priv(dev);
        wol->supported = 0;
        wol->wolopts = 0;
-       if (mp->phy)
-               phy_ethtool_get_wol(mp->phy, wol);
+       if (dev->phydev)
+               phy_ethtool_get_wol(dev->phydev, wol);
 }
 
 static int
 mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-       struct mv643xx_eth_private *mp = netdev_priv(dev);
        int err;
 
-       if (mp->phy == NULL)
+       if (!dev->phydev)
                return -EOPNOTSUPP;
 
-       err = phy_ethtool_set_wol(mp->phy, wol);
+       err = phy_ethtool_set_wol(dev->phydev, wol);
        /* Given that mv643xx_eth works without the marvell-specific PHY driver,
         * this debugging hint is useful to have.
         */
@@ -1579,31 +1589,38 @@ mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 }
 
 static int
-mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+mv643xx_eth_get_link_ksettings(struct net_device *dev,
+                              struct ethtool_link_ksettings *cmd)
 {
        struct mv643xx_eth_private *mp = netdev_priv(dev);
 
-       if (mp->phy != NULL)
-               return mv643xx_eth_get_settings_phy(mp, cmd);
+       if (dev->phydev)
+               return mv643xx_eth_get_link_ksettings_phy(mp, cmd);
        else
-               return mv643xx_eth_get_settings_phyless(mp, cmd);
+               return mv643xx_eth_get_link_ksettings_phyless(mp, cmd);
 }
 
 static int
-mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+mv643xx_eth_set_link_ksettings(struct net_device *dev,
+                              const struct ethtool_link_ksettings *cmd)
 {
-       struct mv643xx_eth_private *mp = netdev_priv(dev);
+       struct ethtool_link_ksettings c = *cmd;
+       u32 advertising;
        int ret;
 
-       if (mp->phy == NULL)
+       if (!dev->phydev)
                return -EINVAL;
 
        /*
         * The MAC does not support 1000baseT_Half.
         */
-       cmd->advertising &= ~ADVERTISED_1000baseT_Half;
+       ethtool_convert_link_mode_to_legacy_u32(&advertising,
+                                               c.link_modes.advertising);
+       advertising &= ~ADVERTISED_1000baseT_Half;
+       ethtool_convert_legacy_u32_to_link_mode(c.link_modes.advertising,
+                                               advertising);
 
-       ret = phy_ethtool_sset(mp->phy, cmd);
+       ret = phy_ethtool_ksettings_set(dev->phydev, &c);
        if (!ret)
                mv643xx_eth_adjust_link(dev);
        return ret;
@@ -1622,12 +1639,10 @@ static void mv643xx_eth_get_drvinfo(struct net_device *dev,
 
 static int mv643xx_eth_nway_reset(struct net_device *dev)
 {
-       struct mv643xx_eth_private *mp = netdev_priv(dev);
-
-       if (mp->phy == NULL)
+       if (!dev->phydev)
                return -EINVAL;
 
-       return genphy_restart_aneg(mp->phy);
+       return genphy_restart_aneg(dev->phydev);
 }
 
 static int
@@ -1752,8 +1767,6 @@ static int mv643xx_eth_get_sset_count(struct net_device *dev, int sset)
 }
 
 static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
-       .get_settings           = mv643xx_eth_get_settings,
-       .set_settings           = mv643xx_eth_set_settings,
        .get_drvinfo            = mv643xx_eth_get_drvinfo,
        .nway_reset             = mv643xx_eth_nway_reset,
        .get_link               = ethtool_op_get_link,
@@ -1767,6 +1780,8 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
        .get_ts_info            = ethtool_op_get_ts_info,
        .get_wol                = mv643xx_eth_get_wol,
        .set_wol                = mv643xx_eth_set_wol,
+       .get_link_ksettings     = mv643xx_eth_get_link_ksettings,
+       .set_link_ksettings     = mv643xx_eth_set_link_ksettings,
 };
 
 
@@ -2326,19 +2341,21 @@ static inline void oom_timer_wrapper(unsigned long data)
 
 static void port_start(struct mv643xx_eth_private *mp)
 {
+       struct net_device *dev = mp->dev;
        u32 pscr;
        int i;
 
        /*
         * Perform PHY reset, if there is a PHY.
         */
-       if (mp->phy != NULL) {
-               struct ethtool_cmd cmd;
+       if (dev->phydev) {
+               struct ethtool_link_ksettings cmd;
 
-               mv643xx_eth_get_settings(mp->dev, &cmd);
-               phy_init_hw(mp->phy);
-               mv643xx_eth_set_settings(mp->dev, &cmd);
-               phy_start(mp->phy);
+               mv643xx_eth_get_link_ksettings(dev, &cmd);
+               phy_init_hw(dev->phydev);
+               mv643xx_eth_set_link_ksettings(
+                       dev, (const struct ethtool_link_ksettings *)&cmd);
+               phy_start(dev->phydev);
        }
 
        /*
@@ -2350,7 +2367,7 @@ static void port_start(struct mv643xx_eth_private *mp)
        wrlp(mp, PORT_SERIAL_CONTROL, pscr);
 
        pscr |= DO_NOT_FORCE_LINK_FAIL;
-       if (mp->phy == NULL)
+       if (!dev->phydev)
                pscr |= FORCE_LINK_PASS;
        wrlp(mp, PORT_SERIAL_CONTROL, pscr);
 
@@ -2534,8 +2551,8 @@ static int mv643xx_eth_stop(struct net_device *dev)
        del_timer_sync(&mp->rx_oom);
 
        netif_carrier_off(dev);
-       if (mp->phy)
-               phy_stop(mp->phy);
+       if (dev->phydev)
+               phy_stop(dev->phydev);
        free_irq(dev->irq, dev);
 
        port_reset(mp);
@@ -2553,13 +2570,12 @@ static int mv643xx_eth_stop(struct net_device *dev)
 
 static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-       struct mv643xx_eth_private *mp = netdev_priv(dev);
        int ret;
 
-       if (mp->phy == NULL)
+       if (!dev->phydev)
                return -ENOTSUPP;
 
-       ret = phy_mii_ioctl(mp->phy, ifr, cmd);
+       ret = phy_mii_ioctl(dev->phydev, ifr, cmd);
        if (!ret)
                mv643xx_eth_adjust_link(dev);
        return ret;
@@ -2569,9 +2585,6 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct mv643xx_eth_private *mp = netdev_priv(dev);
 
-       if (new_mtu < 64 || new_mtu > 9500)
-               return -EINVAL;
-
        dev->mtu = new_mtu;
        mv643xx_eth_recalc_skb_size(mp);
        tx_set_rate(mp, 1000000000, 16777216);
@@ -3022,7 +3035,8 @@ static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
 
 static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)
 {
-       struct phy_device *phy = mp->phy;
+       struct net_device *dev = mp->dev;
+       struct phy_device *phy = dev->phydev;
 
        if (speed == 0) {
                phy->autoneg = AUTONEG_ENABLE;
@@ -3040,6 +3054,7 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)
 
 static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
 {
+       struct net_device *dev = mp->dev;
        u32 pscr;
 
        pscr = rdlp(mp, PORT_SERIAL_CONTROL);
@@ -3049,7 +3064,7 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
        }
 
        pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED;
-       if (mp->phy == NULL) {
+       if (!dev->phydev) {
                pscr |= DISABLE_AUTO_NEG_SPEED_GMII;
                if (speed == SPEED_1000)
                        pscr |= SET_GMII_SPEED_TO_1000;
@@ -3088,6 +3103,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        struct mv643xx_eth_platform_data *pd;
        struct mv643xx_eth_private *mp;
        struct net_device *dev;
+       struct phy_device *phydev = NULL;
        struct resource *res;
        int err;
 
@@ -3144,18 +3160,18 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 
        err = 0;
        if (pd->phy_node) {
-               mp->phy = of_phy_connect(mp->dev, pd->phy_node,
-                                        mv643xx_eth_adjust_link, 0,
-                                        get_phy_mode(mp));
-               if (!mp->phy)
+               phydev = of_phy_connect(mp->dev, pd->phy_node,
+                                       mv643xx_eth_adjust_link, 0,
+                                       get_phy_mode(mp));
+               if (!phydev)
                        err = -ENODEV;
                else
-                       phy_addr_set(mp, mp->phy->mdio.addr);
+                       phy_addr_set(mp, phydev->mdio.addr);
        } else if (pd->phy_addr != MV643XX_ETH_PHY_NONE) {
-               mp->phy = phy_scan(mp, pd->phy_addr);
+               phydev = phy_scan(mp, pd->phy_addr);
 
-               if (IS_ERR(mp->phy))
-                       err = PTR_ERR(mp->phy);
+               if (IS_ERR(phydev))
+                       err = PTR_ERR(phydev);
                else
                        phy_init(mp, pd->speed, pd->duplex);
        }
@@ -3204,6 +3220,15 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        dev->priv_flags |= IFF_UNICAST_FLT;
        dev->gso_max_segs = MV643XX_MAX_TSO_SEGS;
 
+<<<<<<< HEAD
+       /* MTU range: 64 - 9500 */
+       dev->min_mtu = 64;
+       dev->max_mtu = 9500;
+
+       SET_NETDEV_DEV(dev, &pdev->dev);
+
+=======
+>>>>>>> 2a26d99b251b8625d27aed14e97fc10707a3a81f
        if (mp->shared->win_protect)
                wrl(mp, WINDOW_PROTECT(mp->port_num), mp->shared->win_protect);
 
@@ -3237,10 +3262,11 @@ out:
 static int mv643xx_eth_remove(struct platform_device *pdev)
 {
        struct mv643xx_eth_private *mp = platform_get_drvdata(pdev);
+       struct net_device *dev = mp->dev;
 
        unregister_netdev(mp->dev);
-       if (mp->phy != NULL)
-               phy_disconnect(mp->phy);
+       if (dev->phydev)
+               phy_disconnect(dev->phydev);
        cancel_work_sync(&mp->tx_timeout_task);
 
        if (!IS_ERR(mp->clk))
index 5cb07c2017bfa897248d589fda460ca68e770114..b85819ea8eea5b429badbb1ab89f3411809289d8 100644 (file)
@@ -3024,29 +3024,6 @@ static void mvneta_stop_dev(struct mvneta_port *pp)
        mvneta_rx_reset(pp);
 }
 
-/* Return positive if MTU is valid */
-static int mvneta_check_mtu_valid(struct net_device *dev, int mtu)
-{
-       if (mtu < 68) {
-               netdev_err(dev, "cannot change mtu to less than 68\n");
-               return -EINVAL;
-       }
-
-       /* 9676 == 9700 - 20 and rounding to 8 */
-       if (mtu > 9676) {
-               netdev_info(dev, "Illegal MTU value %d, round to 9676\n", mtu);
-               mtu = 9676;
-       }
-
-       if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) {
-               netdev_info(dev, "Illegal MTU value %d, rounding to %d\n",
-                       mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8));
-               mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8);
-       }
-
-       return mtu;
-}
-
 static void mvneta_percpu_enable(void *arg)
 {
        struct mvneta_port *pp = arg;
@@ -3067,9 +3044,11 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu)
        struct mvneta_port *pp = netdev_priv(dev);
        int ret;
 
-       mtu = mvneta_check_mtu_valid(dev, mtu);
-       if (mtu < 0)
-               return -EINVAL;
+       if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) {
+               netdev_info(dev, "Illegal MTU value %d, rounding to %d\n",
+                           mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8));
+               mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8);
+       }
 
        dev->mtu = mtu;
 
@@ -4154,6 +4133,11 @@ static int mvneta_probe(struct platform_device *pdev)
        dev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE;
        dev->gso_max_segs = MVNETA_MAX_TSO_SEGS;
 
+       /* MTU range: 68 - 9676 */
+       dev->min_mtu = ETH_MIN_MTU;
+       /* 9676 == 9700 - 20 and rounding to 8 */
+       dev->max_mtu = 9676;
+
        err = register_netdev(dev);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to register\n");
index 60227a3452a40d00014a2f7d5584f3b518785455..c8bf155cad94c9155c379bde35562ca0977e1515 100644 (file)
@@ -5453,29 +5453,6 @@ static void mvpp2_stop_dev(struct mvpp2_port *port)
        phy_stop(ndev->phydev);
 }
 
-/* Return positive if MTU is valid */
-static inline int mvpp2_check_mtu_valid(struct net_device *dev, int mtu)
-{
-       if (mtu < 68) {
-               netdev_err(dev, "cannot change mtu to less than 68\n");
-               return -EINVAL;
-       }
-
-       /* 9676 == 9700 - 20 and rounding to 8 */
-       if (mtu > 9676) {
-               netdev_info(dev, "illegal MTU value %d, round to 9676\n", mtu);
-               mtu = 9676;
-       }
-
-       if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
-               netdev_info(dev, "illegal MTU value %d, round to %d\n", mtu,
-                           ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8));
-               mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
-       }
-
-       return mtu;
-}
-
 static int mvpp2_check_ringparam_valid(struct net_device *dev,
                                       struct ethtool_ringparam *ring)
 {
@@ -5717,10 +5694,10 @@ static int mvpp2_change_mtu(struct net_device *dev, int mtu)
        struct mvpp2_port *port = netdev_priv(dev);
        int err;
 
-       mtu = mvpp2_check_mtu_valid(dev, mtu);
-       if (mtu < 0) {
-               err = mtu;
-               goto error;
+       if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
+               netdev_info(dev, "illegal MTU value %d, round to %d\n", mtu,
+                           ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8));
+               mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
        }
 
        if (!netif_running(dev)) {
@@ -6212,6 +6189,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,
        dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO;
        dev->vlan_features |= features;
 
+       /* MTU range: 68 - 9676 */
+       dev->min_mtu = ETH_MIN_MTU;
+       /* 9676 == 9700 - 20 and rounding to 8 */
+       dev->max_mtu = 9676;
+
        err = register_netdev(dev);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to register netdev\n");
index 5d5000c8edf1db72e179249cf4abf20011e3301f..b78a838f306c86b21c8c8a29a4c6dbb12fe5aa6c 100644 (file)
@@ -1209,9 +1209,6 @@ static int pxa168_eth_change_mtu(struct net_device *dev, int mtu)
        int retval;
        struct pxa168_eth_private *pep = netdev_priv(dev);
 
-       if ((mtu > 9500) || (mtu < 68))
-               return -EINVAL;
-
        dev->mtu = mtu;
        retval = set_port_config_ext(pep);
 
@@ -1459,6 +1456,10 @@ static int pxa168_eth_probe(struct platform_device *pdev)
        dev->base_addr = 0;
        dev->ethtool_ops = &pxa168_ethtool_ops;
 
+       /* MTU range: 68 - 9500 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = 9500;
+
        INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task);
 
        if (pdev->dev.of_node)
index 7173836fe361962d5c88796ac34c07c9d5ecd166..9146a514fb33c7993ec1018347a44fc606a283e8 100644 (file)
@@ -1048,7 +1048,7 @@ static const char *skge_pause(enum pause_status status)
 static void skge_link_up(struct skge_port *skge)
 {
        skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
-                   LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
+                   LED_BLK_OFF|LED_SYNC_OFF|LED_REG_ON);
 
        netif_carrier_on(skge->netdev);
        netif_wake_queue(skge->netdev);
@@ -1062,7 +1062,7 @@ static void skge_link_up(struct skge_port *skge)
 
 static void skge_link_down(struct skge_port *skge)
 {
-       skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+       skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_REG_OFF);
        netif_carrier_off(skge->netdev);
        netif_stop_queue(skge->netdev);
 
@@ -2668,7 +2668,7 @@ static int skge_down(struct net_device *dev)
        if (hw->ports == 1)
                free_irq(hw->pdev->irq, hw);
 
-       skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+       skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_REG_OFF);
        if (is_genesis(hw))
                genesis_stop(skge);
        else
@@ -2900,9 +2900,6 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu)
 {
        int err;
 
-       if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
-               return -EINVAL;
-
        if (!netif_running(dev)) {
                dev->mtu = new_mtu;
                return 0;
@@ -3857,6 +3854,10 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
        dev->watchdog_timeo = TX_WATCHDOG;
        dev->irq = hw->pdev->irq;
 
+       /* MTU range: 60 - 9000 */
+       dev->min_mtu = ETH_ZLEN;
+       dev->max_mtu = ETH_JUMBO_MTU;
+
        if (highmem)
                dev->features |= NETIF_F_HIGHDMA;
 
index a2eb3411584481e74562b22335954f40c949c72c..3ea151ff9c432ef9b693e26056c40ce083bca5ea 100644 (file)
@@ -662,8 +662,8 @@ enum {
        LED_BLK_OFF     = 1<<4, /* Link LED Blinking Off */
        LED_SYNC_ON     = 1<<3, /* Use Sync Wire to switch LED */
        LED_SYNC_OFF    = 1<<2, /* Disable Sync Wire Input */
-       LED_ON  = 1<<1, /* switch LED on */
-       LED_OFF = 1<<0, /* switch LED off */
+       LED_REG_ON      = 1<<1, /* switch LED on */
+       LED_REG_OFF     = 1<<0, /* switch LED off */
 };
 
 /* Receive GMAC FIFO (YUKON) */
index f05ea56dcff2cdecee79e21ac38c1c9623378912..aa60f4dcddd84969e84130da51545482afdd9d7d 100644 (file)
@@ -2398,16 +2398,6 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
        u16 ctl, mode;
        u32 imask;
 
-       /* MTU size outside the spec */
-       if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
-               return -EINVAL;
-
-       /* MTU > 1500 on yukon FE and FE+ not allowed */
-       if (new_mtu > ETH_DATA_LEN &&
-           (hw->chip_id == CHIP_ID_YUKON_FE ||
-            hw->chip_id == CHIP_ID_YUKON_FE_P))
-               return -EINVAL;
-
        if (!netif_running(dev)) {
                dev->mtu = new_mtu;
                netdev_update_features(dev);
@@ -4808,6 +4798,14 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
 
        dev->features |= dev->hw_features;
 
+       /* MTU range: 60 - 1500 or 9000 */
+       dev->min_mtu = ETH_ZLEN;
+       if (hw->chip_id == CHIP_ID_YUKON_FE ||
+           hw->chip_id == CHIP_ID_YUKON_FE_P)
+               dev->max_mtu = ETH_DATA_LEN;
+       else
+               dev->max_mtu = ETH_JUMBO_MTU;
+
        /* try to get mac address in the following order:
         * 1) from device tree data
         * 2) from internal registers set by bootloader
index 4a62ffd7729d0327f35b16d4a5b4e3dc89adbb01..d71627417ea7de8d0102fa5e0de7053fb15f094a 100644 (file)
@@ -843,7 +843,7 @@ static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
 drop:
        spin_unlock(&eth->page_lock);
        stats->tx_dropped++;
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        return NETDEV_TX_OK;
 }
 
@@ -2243,7 +2243,6 @@ static const struct net_device_ops mtk_netdev_ops = {
        .ndo_set_mac_address    = mtk_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = mtk_do_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_tx_timeout         = mtk_tx_timeout,
        .ndo_get_stats64        = mtk_get_stats64,
        .ndo_fix_features       = mtk_fix_features,
index 12c99a2655f265d96ee3646d419a742f1bc4b609..58b749dd612572d4bf87532935399a9bcbe84700 100644 (file)
@@ -2214,10 +2214,6 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
        en_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n",
                 dev->mtu, new_mtu);
 
-       if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) {
-               en_err(priv, "Bad MTU size:%d.\n", new_mtu);
-               return -EPERM;
-       }
        if (priv->xdp_ring_num && MLX4_EN_EFF_MTU(new_mtu) > FRAG_SZ0) {
                en_err(priv, "MTU size:%d requires frags but XDP running\n",
                       new_mtu);
@@ -3297,6 +3293,10 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
                dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
        }
 
+       /* MTU range: 46 - hw-specific max */
+       dev->min_mtu = MLX4_EN_MIN_MTU;
+       dev->max_mtu = priv->max_mtu;
+
        mdev->pndev[port] = dev;
        mdev->upper[port] = NULL;
 
index f4c687ce4c5989e26f1cb192a3eccbc0855bf054..d3f13b5db5b32396b76fed0056cd64ac3e08b85d 100644 (file)
@@ -2849,31 +2849,13 @@ static int mlx5e_set_features(struct net_device *netdev,
        return err ? -EINVAL : 0;
 }
 
-#define MXL5_HW_MIN_MTU 64
-#define MXL5E_MIN_MTU (MXL5_HW_MIN_MTU + ETH_FCS_LEN)
-
 static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-       struct mlx5_core_dev *mdev = priv->mdev;
        bool was_opened;
-       u16 max_mtu;
-       u16 min_mtu;
        int err = 0;
        bool reset;
 
-       mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
-
-       max_mtu = MLX5E_HW2SW_MTU(max_mtu);
-       min_mtu = MLX5E_HW2SW_MTU(MXL5E_MIN_MTU);
-
-       if (new_mtu > max_mtu || new_mtu < min_mtu) {
-               netdev_err(netdev,
-                          "%s: Bad MTU (%d), valid range is: [%d..%d]\n",
-                          __func__, new_mtu, min_mtu, max_mtu);
-               return -EINVAL;
-       }
-
        mutex_lock(&priv->state_lock);
 
        reset = !priv->params.lro_en &&
@@ -3848,6 +3830,7 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
 {
        const struct mlx5e_profile *profile;
        struct mlx5e_priv *priv;
+       u16 max_mtu;
        int err;
 
        priv = netdev_priv(netdev);
@@ -3878,6 +3861,11 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
 
        mlx5e_init_l2_addr(priv);
 
+       /* MTU range: 68 - hw-specific max */
+       netdev->min_mtu = ETH_MIN_MTU;
+       mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
+       netdev->max_mtu = MLX5E_HW2SW_MTU(max_mtu);
+
        mlx5e_set_dev_port_mtu(netdev);
 
        if (profile->enable)
index ce8c54d18906bedc57f0bdd8353e1f2156d47ce7..135a95bcc3929d81b236cebd2c8f574275f99040 100644 (file)
@@ -404,7 +404,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                        continue;
                }
 
-               if (is_tcf_mirred_redirect(a)) {
+               if (is_tcf_mirred_egress_redirect(a)) {
                        int ifindex = tcf_mirred_ifindex(a);
                        struct net_device *out_dev;
                        struct mlx5e_priv *out_priv;
index 5989f7cb546235850cf3c3740b21d1a26d0417da..d0bcf59c1bd6e4d3ab795624c319036d07e342ec 100644 (file)
@@ -31,7 +31,7 @@ config MLXSW_PCI
 
 config MLXSW_SWITCHX2
        tristate "Mellanox Technologies SwitchX-2 support"
-       depends on MLXSW_CORE && NET_SWITCHDEV
+       depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV
        default m
        ---help---
          This driver supports Mellanox Technologies SwitchX-2 Ethernet
@@ -42,7 +42,7 @@ config MLXSW_SWITCHX2
 
 config MLXSW_SPECTRUM
        tristate "Mellanox Technologies Spectrum support"
-       depends on MLXSW_CORE && NET_SWITCHDEV && VLAN_8021Q
+       depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV && VLAN_8021Q
        default m
        ---help---
          This driver supports Mellanox Technologies Spectrum Ethernet
index 28271bedd95711b190934d6939348557600f1fa2..56e19b0d2f8f272d9833159264b2f139c5cee13b 100644 (file)
@@ -513,6 +513,11 @@ static inline int mlxsw_cmd_unmap_fa(struct mlxsw_core *mlxsw_core)
  * are no more sources in the table, will return resource id 0xFFF to indicate
  * it.
  */
+
+#define MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID 0xffff
+#define MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES 100
+#define MLXSW_CMD_QUERY_RESOURCES_PER_QUERY 32
+
 static inline int mlxsw_cmd_query_resources(struct mlxsw_core *mlxsw_core,
                                            char *out_mbox, int index)
 {
index aa33d58b9f81ca9812a59cf8cc48a3a44322975a..02183f6a8b930b73f494ce62b085f79d33ebba3b 100644 (file)
@@ -67,6 +67,7 @@
 #include "trap.h"
 #include "emad.h"
 #include "reg.h"
+#include "resources.h"
 
 static LIST_HEAD(mlxsw_core_driver_list);
 static DEFINE_SPINLOCK(mlxsw_core_driver_list_lock);
@@ -111,7 +112,7 @@ struct mlxsw_core {
        struct {
                u8 *mapping; /* lag_id+port_index to local_port mapping */
        } lag;
-       struct mlxsw_resources resources;
+       struct mlxsw_res res;
        struct mlxsw_hwmon *hwmon;
        unsigned long driver_priv[0];
        /* driver_priv has to be always the last item */
@@ -822,17 +823,6 @@ static struct mlxsw_driver *mlxsw_core_driver_get(const char *kind)
 
        spin_lock(&mlxsw_core_driver_list_lock);
        mlxsw_driver = __driver_find(kind);
-       if (!mlxsw_driver) {
-               spin_unlock(&mlxsw_core_driver_list_lock);
-               request_module(MLXSW_MODULE_ALIAS_PREFIX "%s", kind);
-               spin_lock(&mlxsw_core_driver_list_lock);
-               mlxsw_driver = __driver_find(kind);
-       }
-       if (mlxsw_driver) {
-               if (!try_module_get(mlxsw_driver->owner))
-                       mlxsw_driver = NULL;
-       }
-
        spin_unlock(&mlxsw_core_driver_list_lock);
        return mlxsw_driver;
 }
@@ -844,9 +834,6 @@ static void mlxsw_core_driver_put(const char *kind)
        spin_lock(&mlxsw_core_driver_list_lock);
        mlxsw_driver = __driver_find(kind);
        spin_unlock(&mlxsw_core_driver_list_lock);
-       if (!mlxsw_driver)
-               return;
-       module_put(mlxsw_driver->owner);
 }
 
 static int mlxsw_core_debugfs_init(struct mlxsw_core *mlxsw_core)
@@ -1101,14 +1088,15 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
        }
 
        err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile,
-                             &mlxsw_core->resources);
+                             &mlxsw_core->res);
        if (err)
                goto err_bus_init;
 
-       if (mlxsw_core->resources.max_lag_valid &&
-           mlxsw_core->resources.max_ports_in_lag_valid) {
-               alloc_size = sizeof(u8) * mlxsw_core->resources.max_lag *
-                       mlxsw_core->resources.max_ports_in_lag;
+       if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) &&
+           MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) {
+               alloc_size = sizeof(u8) *
+                       MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG) *
+                       MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS);
                mlxsw_core->lag.mapping = kzalloc(alloc_size, GFP_KERNEL);
                if (!mlxsw_core->lag.mapping) {
                        err = -ENOMEM;
@@ -1615,7 +1603,7 @@ EXPORT_SYMBOL(mlxsw_core_skb_receive);
 static int mlxsw_core_lag_mapping_index(struct mlxsw_core *mlxsw_core,
                                        u16 lag_id, u8 port_index)
 {
-       return mlxsw_core->resources.max_ports_in_lag * lag_id +
+       return MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS) * lag_id +
               port_index;
 }
 
@@ -1644,7 +1632,7 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
 {
        int i;
 
-       for (i = 0; i < mlxsw_core->resources.max_ports_in_lag; i++) {
+       for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); i++) {
                int index = mlxsw_core_lag_mapping_index(mlxsw_core,
                                                         lag_id, i);
 
@@ -1654,11 +1642,19 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
 }
 EXPORT_SYMBOL(mlxsw_core_lag_mapping_clear);
 
-struct mlxsw_resources *mlxsw_core_resources_get(struct mlxsw_core *mlxsw_core)
+bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core,
+                         enum mlxsw_res_id res_id)
+{
+       return mlxsw_res_valid(&mlxsw_core->res, res_id);
+}
+EXPORT_SYMBOL(mlxsw_core_res_valid);
+
+u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
+                      enum mlxsw_res_id res_id)
 {
-       return &mlxsw_core->resources;
+       return mlxsw_res_get(&mlxsw_core->res, res_id);
 }
-EXPORT_SYMBOL(mlxsw_core_resources_get);
+EXPORT_SYMBOL(mlxsw_core_res_get);
 
 int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core,
                         struct mlxsw_core_port *mlxsw_core_port, u8 local_port,
index c4f550b6f783998eded5bb14d154dad41a073496..0cf721cee7fb074f4f8c68549411675e05539890 100644 (file)
 
 #include "trap.h"
 #include "reg.h"
-
 #include "cmd.h"
-
-#define MLXSW_MODULE_ALIAS_PREFIX "mlxsw-driver-"
-#define MODULE_MLXSW_DRIVER_ALIAS(kind)        \
-       MODULE_ALIAS(MLXSW_MODULE_ALIAS_PREFIX kind)
-
-#define MLXSW_DEVICE_KIND_SWITCHX2 "switchx2"
-#define MLXSW_DEVICE_KIND_SPECTRUM "spectrum"
+#include "resources.h"
 
 struct mlxsw_core;
 struct mlxsw_driver;
@@ -221,7 +214,6 @@ struct mlxsw_config_profile {
 struct mlxsw_driver {
        struct list_head list;
        const char *kind;
-       struct module *owner;
        size_t priv_size;
        int (*init)(struct mlxsw_core *mlxsw_core,
                    const struct mlxsw_bus_info *mlxsw_bus_info);
@@ -266,45 +258,23 @@ struct mlxsw_driver {
        const struct mlxsw_config_profile *profile;
 };
 
-struct mlxsw_resources {
-       u32     max_span_valid:1,
-               max_lag_valid:1,
-               max_ports_in_lag_valid:1,
-               kvd_size_valid:1,
-               kvd_single_min_size_valid:1,
-               kvd_double_min_size_valid:1,
-               max_virtual_routers_valid:1,
-               max_system_ports_valid:1,
-               max_vlan_groups_valid:1,
-               max_regions_valid:1,
-               max_rif_valid:1;
-       u8      max_span;
-       u8      max_lag;
-       u8      max_ports_in_lag;
-       u32     kvd_size;
-       u32     kvd_single_min_size;
-       u32     kvd_double_min_size;
-       u16     max_virtual_routers;
-       u16     max_system_ports;
-       u16     max_vlan_groups;
-       u16     max_regions;
-       u16     max_rif;
+bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core,
+                         enum mlxsw_res_id res_id);
 
-       /* Internal resources.
-        * Determined by the SW, not queried from the HW.
-        */
-       u32     kvd_single_size;
-       u32     kvd_double_size;
-       u32     kvd_linear_size;
-};
+#define MLXSW_CORE_RES_VALID(res, short_res_id)                        \
+       mlxsw_core_res_valid(res, MLXSW_RES_ID_##short_res_id)
+
+u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
+                      enum mlxsw_res_id res_id);
 
-struct mlxsw_resources *mlxsw_core_resources_get(struct mlxsw_core *mlxsw_core);
+#define MLXSW_CORE_RES_GET(res, short_res_id)                  \
+       mlxsw_core_res_get(res, MLXSW_RES_ID_##short_res_id)
 
 struct mlxsw_bus {
        const char *kind;
        int (*init)(void *bus_priv, struct mlxsw_core *mlxsw_core,
                    const struct mlxsw_config_profile *profile,
-                   struct mlxsw_resources *resources);
+                   struct mlxsw_res *res);
        void (*fini)(void *bus_priv);
        bool (*skb_transmit_busy)(void *bus_priv,
                                  const struct mlxsw_tx_info *tx_info);
index a94dbda6590b36ee8a59a90c36f1ede510a2ae14..3c95e3ddd9c25c18ed0daff92518194652e2d2af 100644 (file)
@@ -55,7 +55,7 @@ struct mlxsw_item {
 };
 
 static inline unsigned int
-__mlxsw_item_offset(struct mlxsw_item *item, unsigned short index,
+__mlxsw_item_offset(const struct mlxsw_item *item, unsigned short index,
                    size_t typesize)
 {
        BUG_ON(index && !item->step);
@@ -72,7 +72,8 @@ __mlxsw_item_offset(struct mlxsw_item *item, unsigned short index,
                typesize);
 }
 
-static inline u16 __mlxsw_item_get16(char *buf, struct mlxsw_item *item,
+static inline u16 __mlxsw_item_get16(const char *buf,
+                                    const struct mlxsw_item *item,
                                     unsigned short index)
 {
        unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u16));
@@ -87,7 +88,7 @@ static inline u16 __mlxsw_item_get16(char *buf, struct mlxsw_item *item,
        return tmp;
 }
 
-static inline void __mlxsw_item_set16(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_set16(char *buf, const struct mlxsw_item *item,
                                      unsigned short index, u16 val)
 {
        unsigned int offset = __mlxsw_item_offset(item, index,
@@ -105,7 +106,8 @@ static inline void __mlxsw_item_set16(char *buf, struct mlxsw_item *item,
        b[offset] = cpu_to_be16(tmp);
 }
 
-static inline u32 __mlxsw_item_get32(char *buf, struct mlxsw_item *item,
+static inline u32 __mlxsw_item_get32(const char *buf,
+                                    const struct mlxsw_item *item,
                                     unsigned short index)
 {
        unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u32));
@@ -120,7 +122,7 @@ static inline u32 __mlxsw_item_get32(char *buf, struct mlxsw_item *item,
        return tmp;
 }
 
-static inline void __mlxsw_item_set32(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_set32(char *buf, const struct mlxsw_item *item,
                                      unsigned short index, u32 val)
 {
        unsigned int offset = __mlxsw_item_offset(item, index,
@@ -138,7 +140,8 @@ static inline void __mlxsw_item_set32(char *buf, struct mlxsw_item *item,
        b[offset] = cpu_to_be32(tmp);
 }
 
-static inline u64 __mlxsw_item_get64(char *buf, struct mlxsw_item *item,
+static inline u64 __mlxsw_item_get64(const char *buf,
+                                    const struct mlxsw_item *item,
                                     unsigned short index)
 {
        unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
@@ -153,7 +156,7 @@ static inline u64 __mlxsw_item_get64(char *buf, struct mlxsw_item *item,
        return tmp;
 }
 
-static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_set64(char *buf, const struct mlxsw_item *item,
                                      unsigned short index, u64 val)
 {
        unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
@@ -170,8 +173,8 @@ static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item,
        b[offset] = cpu_to_be64(tmp);
 }
 
-static inline void __mlxsw_item_memcpy_from(char *buf, char *dst,
-                                           struct mlxsw_item *item,
+static inline void __mlxsw_item_memcpy_from(const char *buf, char *dst,
+                                           const struct mlxsw_item *item,
                                            unsigned short index)
 {
        unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
@@ -180,7 +183,7 @@ static inline void __mlxsw_item_memcpy_from(char *buf, char *dst,
 }
 
 static inline void __mlxsw_item_memcpy_to(char *buf, const char *src,
-                                         struct mlxsw_item *item,
+                                         const struct mlxsw_item *item,
                                          unsigned short index)
 {
        unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
@@ -189,7 +192,8 @@ static inline void __mlxsw_item_memcpy_to(char *buf, const char *src,
 }
 
 static inline u16
-__mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
+__mlxsw_item_bit_array_offset(const struct mlxsw_item *item,
+                             u16 index, u8 *shift)
 {
        u16 max_index, be_index;
        u16 offset;             /* byte offset inside the array */
@@ -212,7 +216,8 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
        return item->offset + offset;
 }
 
-static inline u8 __mlxsw_item_bit_array_get(char *buf, struct mlxsw_item *item,
+static inline u8 __mlxsw_item_bit_array_get(const char *buf,
+                                           const struct mlxsw_item *item,
                                            u16 index)
 {
        u8 shift, tmp;
@@ -224,7 +229,8 @@ static inline u8 __mlxsw_item_bit_array_get(char *buf, struct mlxsw_item *item,
        return tmp;
 }
 
-static inline void __mlxsw_item_bit_array_set(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_bit_array_set(char *buf,
+                                             const struct mlxsw_item *item,
                                              u16 index, u8 val)
 {
        u8 shift, tmp;
@@ -254,7 +260,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                     \
        .size = {.bits = _sizebits,},                                           \
        .name = #_type "_" #_cname "_" #_iname,                                 \
 };                                                                             \
-static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf)         \
+static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)   \
 {                                                                              \
        return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
 }                                                                              \
@@ -275,7 +281,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                     \
        .name = #_type "_" #_cname "_" #_iname,                                 \
 };                                                                             \
 static inline u16                                                              \
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index)     \
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
 {                                                                              \
        return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname),     \
                                  index);                                       \
@@ -295,7 +301,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                     \
        .size = {.bits = _sizebits,},                                           \
        .name = #_type "_" #_cname "_" #_iname,                                 \
 };                                                                             \
-static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf)         \
+static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)   \
 {                                                                              \
        return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
 }                                                                              \
@@ -316,7 +322,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                     \
        .name = #_type "_" #_cname "_" #_iname,                                 \
 };                                                                             \
 static inline u32                                                              \
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index)     \
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
 {                                                                              \
        return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname),     \
                                  index);                                       \
@@ -336,7 +342,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                     \
        .size = {.bits = _sizebits,},                                           \
        .name = #_type "_" #_cname "_" #_iname,                                 \
 };                                                                             \
-static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf)         \
+static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)   \
 {                                                                              \
        return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname), 0); \
 }                                                                              \
@@ -357,7 +363,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                     \
        .name = #_type "_" #_cname "_" #_iname,                                 \
 };                                                                             \
 static inline u64                                                              \
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index)     \
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
 {                                                                              \
        return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname),     \
                                  index);                                       \
@@ -377,7 +383,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                     \
        .name = #_type "_" #_cname "_" #_iname,                                 \
 };                                                                             \
 static inline void                                                             \
-mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, char *dst)                \
+mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf, char *dst)  \
 {                                                                              \
        __mlxsw_item_memcpy_from(buf, dst,                                      \
                                 &__ITEM_NAME(_type, _cname, _iname), 0);       \
@@ -399,7 +405,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                     \
        .name = #_type "_" #_cname "_" #_iname,                                 \
 };                                                                             \
 static inline void                                                             \
-mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf,                   \
+mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf,             \
                                                  unsigned short index,         \
                                                  char *dst)                    \
 {                                                                              \
@@ -424,7 +430,7 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {                     \
        .name = #_type "_" #_cname "_" #_iname,                                 \
 };                                                                             \
 static inline u8                                                               \
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, u16 index)                        \
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, u16 index)          \
 {                                                                              \
        return __mlxsw_item_bit_array_get(buf,                                  \
                                          &__ITEM_NAME(_type, _cname, _iname),  \
index 912f71f84209d3e22a386cf36498bbfccb541047..d5cf1ea1c89a472fb96a6521616591609012fe25 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/string.h>
 
+#include "pci_hw.h"
 #include "pci.h"
 #include "core.h"
 #include "cmd.h"
 #include "port.h"
+#include "resources.h"
 
 static const char mlxsw_pci_driver_name[] = "mlxsw_pci";
 
-static const struct pci_device_id mlxsw_pci_id_table[] = {
-       {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0},
-       {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
-       {0, }
-};
-
 static struct dentry *mlxsw_pci_dbg_root;
 
-static const char *mlxsw_pci_device_kind_get(const struct pci_device_id *id)
-{
-       switch (id->device) {
-       case PCI_DEVICE_ID_MELLANOX_SWITCHX2:
-               return MLXSW_DEVICE_KIND_SWITCHX2;
-       case PCI_DEVICE_ID_MELLANOX_SPECTRUM:
-               return MLXSW_DEVICE_KIND_SPECTRUM;
-       default:
-               BUG();
-       }
-}
-
 #define mlxsw_pci_write32(mlxsw_pci, reg, val) \
        iowrite32be(val, (mlxsw_pci)->hw_addr + (MLXSW_PCI_ ## reg))
 #define mlxsw_pci_read32(mlxsw_pci, reg) \
@@ -238,8 +222,9 @@ static bool mlxsw_pci_elem_hw_owned(struct mlxsw_pci_queue *q, bool owner_bit)
        return owner_bit != !!(q->consumer_counter & q->count);
 }
 
-static char *mlxsw_pci_queue_sw_elem_get(struct mlxsw_pci_queue *q,
-                                        u32 (*get_elem_owner_func)(char *))
+static char *
+mlxsw_pci_queue_sw_elem_get(struct mlxsw_pci_queue *q,
+                           u32 (*get_elem_owner_func)(const char *))
 {
        struct mlxsw_pci_queue_elem_info *elem_info;
        char *elem;
@@ -1154,76 +1139,8 @@ mlxsw_pci_config_profile_swid_config(struct mlxsw_pci *mlxsw_pci,
        mlxsw_cmd_mbox_config_profile_swid_config_mask_set(mbox, index, mask);
 }
 
-#define MLXSW_RESOURCES_TABLE_END_ID 0xffff
-#define MLXSW_MAX_SPAN_ID 0x2420
-#define MLXSW_MAX_LAG_ID 0x2520
-#define MLXSW_MAX_PORTS_IN_LAG_ID 0x2521
-#define MLXSW_KVD_SIZE_ID 0x1001
-#define MLXSW_KVD_SINGLE_MIN_SIZE_ID 0x1002
-#define MLXSW_KVD_DOUBLE_MIN_SIZE_ID 0x1003
-#define MLXSW_MAX_VIRTUAL_ROUTERS_ID 0x2C01
-#define MLXSW_MAX_SYSTEM_PORT_ID 0x2502
-#define MLXSW_MAX_VLAN_GROUPS_ID 0x2906
-#define MLXSW_MAX_REGIONS_ID 0x2901
-#define MLXSW_MAX_RIF_ID 0x2C02
-#define MLXSW_RESOURCES_QUERY_MAX_QUERIES 100
-#define MLXSW_RESOURCES_PER_QUERY 32
-
-static void mlxsw_pci_resources_query_parse(int id, u64 val,
-                                           struct mlxsw_resources *resources)
-{
-       switch (id) {
-       case MLXSW_MAX_SPAN_ID:
-               resources->max_span = val;
-               resources->max_span_valid = 1;
-               break;
-       case MLXSW_MAX_LAG_ID:
-               resources->max_lag = val;
-               resources->max_lag_valid = 1;
-               break;
-       case MLXSW_MAX_PORTS_IN_LAG_ID:
-               resources->max_ports_in_lag = val;
-               resources->max_ports_in_lag_valid = 1;
-               break;
-       case MLXSW_KVD_SIZE_ID:
-               resources->kvd_size = val;
-               resources->kvd_size_valid = 1;
-               break;
-       case MLXSW_KVD_SINGLE_MIN_SIZE_ID:
-               resources->kvd_single_min_size = val;
-               resources->kvd_single_min_size_valid = 1;
-               break;
-       case MLXSW_KVD_DOUBLE_MIN_SIZE_ID:
-               resources->kvd_double_min_size = val;
-               resources->kvd_double_min_size_valid = 1;
-               break;
-       case MLXSW_MAX_VIRTUAL_ROUTERS_ID:
-               resources->max_virtual_routers = val;
-               resources->max_virtual_routers_valid = 1;
-               break;
-       case MLXSW_MAX_SYSTEM_PORT_ID:
-               resources->max_system_ports = val;
-               resources->max_system_ports_valid = 1;
-               break;
-       case MLXSW_MAX_VLAN_GROUPS_ID:
-               resources->max_vlan_groups = val;
-               resources->max_vlan_groups_valid = 1;
-               break;
-       case MLXSW_MAX_REGIONS_ID:
-               resources->max_regions = val;
-               resources->max_regions_valid = 1;
-               break;
-       case MLXSW_MAX_RIF_ID:
-               resources->max_rif = val;
-               resources->max_rif_valid = 1;
-               break;
-       default:
-               break;
-       }
-}
-
 static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox,
-                                    struct mlxsw_resources *resources,
+                                    struct mlxsw_res *res,
                                     u8 query_enabled)
 {
        int index, i;
@@ -1237,19 +1154,20 @@ static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox,
 
        mlxsw_cmd_mbox_zero(mbox);
 
-       for (index = 0; index < MLXSW_RESOURCES_QUERY_MAX_QUERIES; index++) {
+       for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES;
+            index++) {
                err = mlxsw_cmd_query_resources(mlxsw_pci->core, mbox, index);
                if (err)
                        return err;
 
-               for (i = 0; i < MLXSW_RESOURCES_PER_QUERY; i++) {
+               for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) {
                        id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i);
                        data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i);
 
-                       if (id == MLXSW_RESOURCES_TABLE_END_ID)
+                       if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID)
                                return 0;
 
-                       mlxsw_pci_resources_query_parse(id, data, resources);
+                       mlxsw_res_parse(res, id, data);
                }
        }
 
@@ -1259,13 +1177,14 @@ static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox,
        return -EIO;
 }
 
-static int mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *profile,
-                                          struct mlxsw_resources *resources)
+static int
+mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *profile,
+                               struct mlxsw_res *res)
 {
-       u32 singles_size, doubles_size, linear_size;
+       u32 single_size, double_size, linear_size;
 
-       if (!resources->kvd_single_min_size_valid ||
-           !resources->kvd_double_min_size_valid ||
+       if (!MLXSW_RES_VALID(res, KVD_SINGLE_MIN_SIZE) ||
+           !MLXSW_RES_VALID(res, KVD_DOUBLE_MIN_SIZE) ||
            !profile->used_kvd_split_data)
                return -EIO;
 
@@ -1277,31 +1196,31 @@ static int mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *pr
         * Both sizes must be a multiplications of the
         * granularity from the profile.
         */
-       doubles_size = (resources->kvd_size - linear_size);
-       doubles_size *= profile->kvd_hash_double_parts;
-       doubles_size /= (profile->kvd_hash_double_parts +
-                        profile->kvd_hash_single_parts);
-       doubles_size /= profile->kvd_hash_granularity;
-       doubles_size *= profile->kvd_hash_granularity;
-       singles_size = resources->kvd_size - doubles_size -
-                      linear_size;
+       double_size = MLXSW_RES_GET(res, KVD_SIZE) - linear_size;
+       double_size *= profile->kvd_hash_double_parts;
+       double_size /= profile->kvd_hash_double_parts +
+                      profile->kvd_hash_single_parts;
+       double_size /= profile->kvd_hash_granularity;
+       double_size *= profile->kvd_hash_granularity;
+       single_size = MLXSW_RES_GET(res, KVD_SIZE) - double_size -
+                     linear_size;
 
        /* Check results are legal. */
-       if (singles_size < resources->kvd_single_min_size ||
-           doubles_size < resources->kvd_double_min_size ||
-           resources->kvd_size < linear_size)
+       if (single_size < MLXSW_RES_GET(res, KVD_SINGLE_MIN_SIZE) ||
+           double_size < MLXSW_RES_GET(res, KVD_DOUBLE_MIN_SIZE) ||
+           MLXSW_RES_GET(res, KVD_SIZE) < linear_size)
                return -EIO;
 
-       resources->kvd_single_size = singles_size;
-       resources->kvd_double_size = doubles_size;
-       resources->kvd_linear_size = linear_size;
+       MLXSW_RES_SET(res, KVD_SINGLE_SIZE, single_size);
+       MLXSW_RES_SET(res, KVD_DOUBLE_SIZE, double_size);
+       MLXSW_RES_SET(res, KVD_LINEAR_SIZE, linear_size);
 
        return 0;
 }
 
 static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
                                    const struct mlxsw_config_profile *profile,
-                                   struct mlxsw_resources *resources)
+                                   struct mlxsw_res *res)
 {
        int i;
        int err;
@@ -1390,22 +1309,22 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
                mlxsw_cmd_mbox_config_profile_adaptive_routing_group_cap_set(
                        mbox, profile->adaptive_routing_group_cap);
        }
-       if (resources->kvd_size_valid) {
-               err = mlxsw_pci_profile_get_kvd_sizes(profile, resources);
+       if (MLXSW_RES_VALID(res, KVD_SIZE)) {
+               err = mlxsw_pci_profile_get_kvd_sizes(profile, res);
                if (err)
                        return err;
 
                mlxsw_cmd_mbox_config_profile_set_kvd_linear_size_set(mbox, 1);
                mlxsw_cmd_mbox_config_profile_kvd_linear_size_set(mbox,
-                                               resources->kvd_linear_size);
+                                       MLXSW_RES_GET(res, KVD_LINEAR_SIZE));
                mlxsw_cmd_mbox_config_profile_set_kvd_hash_single_size_set(mbox,
                                                                           1);
                mlxsw_cmd_mbox_config_profile_kvd_hash_single_size_set(mbox,
-                                               resources->kvd_single_size);
+                                       MLXSW_RES_GET(res, KVD_SINGLE_SIZE));
                mlxsw_cmd_mbox_config_profile_set_kvd_hash_double_size_set(
                                                                mbox, 1);
                mlxsw_cmd_mbox_config_profile_kvd_hash_double_size_set(mbox,
-                                               resources->kvd_double_size);
+                                       MLXSW_RES_GET(res, KVD_DOUBLE_SIZE));
        }
 
        for (i = 0; i < MLXSW_CONFIG_PROFILE_SWID_COUNT; i++)
@@ -1543,7 +1462,7 @@ static void mlxsw_pci_mbox_free(struct mlxsw_pci *mlxsw_pci,
 
 static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
                          const struct mlxsw_config_profile *profile,
-                         struct mlxsw_resources *resources)
+                         struct mlxsw_res *res)
 {
        struct mlxsw_pci *mlxsw_pci = bus_priv;
        struct pci_dev *pdev = mlxsw_pci->pdev;
@@ -1602,12 +1521,12 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
        if (err)
                goto err_boardinfo;
 
-       err = mlxsw_pci_resources_query(mlxsw_pci, mbox, resources,
+       err = mlxsw_pci_resources_query(mlxsw_pci, mbox, res,
                                        profile->resource_query_enable);
        if (err)
                goto err_query_resources;
 
-       err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, resources);
+       err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, res);
        if (err)
                goto err_config_profile;
 
@@ -1617,7 +1536,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
 
        err = request_irq(mlxsw_pci->msix_entry.vector,
                          mlxsw_pci_eq_irq_handler, 0,
-                         mlxsw_pci_driver_name, mlxsw_pci);
+                         mlxsw_pci->bus_info.device_kind, mlxsw_pci);
        if (err) {
                dev_err(&pdev->dev, "IRQ request failed\n");
                goto err_request_eq_irq;
@@ -1863,6 +1782,7 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
 
 static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+       const char *driver_name = pdev->driver->name;
        struct mlxsw_pci *mlxsw_pci;
        int err;
 
@@ -1876,7 +1796,7 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto err_pci_enable_device;
        }
 
-       err = pci_request_regions(pdev, mlxsw_pci_driver_name);
+       err = pci_request_regions(pdev, driver_name);
        if (err) {
                dev_err(&pdev->dev, "pci_request_regions failed\n");
                goto err_pci_request_regions;
@@ -1927,7 +1847,7 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto err_msix_init;
        }
 
-       mlxsw_pci->bus_info.device_kind = mlxsw_pci_device_kind_get(id);
+       mlxsw_pci->bus_info.device_kind = driver_name;
        mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev);
        mlxsw_pci->bus_info.dev = &pdev->dev;
 
@@ -1979,33 +1899,30 @@ static void mlxsw_pci_remove(struct pci_dev *pdev)
        kfree(mlxsw_pci);
 }
 
-static struct pci_driver mlxsw_pci_driver = {
-       .name           = mlxsw_pci_driver_name,
-       .id_table       = mlxsw_pci_id_table,
-       .probe          = mlxsw_pci_probe,
-       .remove         = mlxsw_pci_remove,
-};
+int mlxsw_pci_driver_register(struct pci_driver *pci_driver)
+{
+       pci_driver->probe = mlxsw_pci_probe;
+       pci_driver->remove = mlxsw_pci_remove;
+       return pci_register_driver(pci_driver);
+}
+EXPORT_SYMBOL(mlxsw_pci_driver_register);
 
-static int __init mlxsw_pci_module_init(void)
+void mlxsw_pci_driver_unregister(struct pci_driver *pci_driver)
 {
-       int err;
+       pci_unregister_driver(pci_driver);
+}
+EXPORT_SYMBOL(mlxsw_pci_driver_unregister);
 
+static int __init mlxsw_pci_module_init(void)
+{
        mlxsw_pci_dbg_root = debugfs_create_dir(mlxsw_pci_driver_name, NULL);
        if (!mlxsw_pci_dbg_root)
                return -ENOMEM;
-       err = pci_register_driver(&mlxsw_pci_driver);
-       if (err)
-               goto err_register_driver;
        return 0;
-
-err_register_driver:
-       debugfs_remove_recursive(mlxsw_pci_dbg_root);
-       return err;
 }
 
 static void __exit mlxsw_pci_module_exit(void)
 {
-       pci_unregister_driver(&mlxsw_pci_driver);
        debugfs_remove_recursive(mlxsw_pci_dbg_root);
 }
 
@@ -2015,4 +1932,3 @@ module_exit(mlxsw_pci_module_exit);
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox switch PCI interface driver");
-MODULE_DEVICE_TABLE(pci, mlxsw_pci_id_table);
index d942a3e6fa4151cbc10f4207b25c95ea8aa734c6..35a0011be64d93493e3255d3340118df0d653d2d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/net/ethernet/mellanox/mlxsw/pci.h
- * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
 #ifndef _MLXSW_PCI_H
 #define _MLXSW_PCI_H
 
-#include <linux/bitops.h>
+#include <linux/pci.h>
 
-#include "item.h"
+#define PCI_DEVICE_ID_MELLANOX_SWITCHX2                0xc738
+#define PCI_DEVICE_ID_MELLANOX_SPECTRUM                0xcb84
 
-#define PCI_DEVICE_ID_MELLANOX_SWITCHX2        0xc738
-#define PCI_DEVICE_ID_MELLANOX_SPECTRUM        0xcb84
-#define MLXSW_PCI_BAR0_SIZE            (1024 * 1024) /* 1MB */
-#define MLXSW_PCI_PAGE_SIZE            4096
+#if IS_ENABLED(CONFIG_MLXSW_PCI)
 
-#define MLXSW_PCI_CIR_BASE                     0x71000
-#define MLXSW_PCI_CIR_IN_PARAM_HI              MLXSW_PCI_CIR_BASE
-#define MLXSW_PCI_CIR_IN_PARAM_LO              (MLXSW_PCI_CIR_BASE + 0x04)
-#define MLXSW_PCI_CIR_IN_MODIFIER              (MLXSW_PCI_CIR_BASE + 0x08)
-#define MLXSW_PCI_CIR_OUT_PARAM_HI             (MLXSW_PCI_CIR_BASE + 0x0C)
-#define MLXSW_PCI_CIR_OUT_PARAM_LO             (MLXSW_PCI_CIR_BASE + 0x10)
-#define MLXSW_PCI_CIR_TOKEN                    (MLXSW_PCI_CIR_BASE + 0x14)
-#define MLXSW_PCI_CIR_CTRL                     (MLXSW_PCI_CIR_BASE + 0x18)
-#define MLXSW_PCI_CIR_CTRL_GO_BIT              BIT(23)
-#define MLXSW_PCI_CIR_CTRL_EVREQ_BIT           BIT(22)
-#define MLXSW_PCI_CIR_CTRL_OPCODE_MOD_SHIFT    12
-#define MLXSW_PCI_CIR_CTRL_STATUS_SHIFT                24
-#define MLXSW_PCI_CIR_TIMEOUT_MSECS            1000
+int mlxsw_pci_driver_register(struct pci_driver *pci_driver);
+void mlxsw_pci_driver_unregister(struct pci_driver *pci_driver);
 
-#define MLXSW_PCI_SW_RESET                     0xF0010
-#define MLXSW_PCI_SW_RESET_RST_BIT             BIT(0)
-#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       5000
-#define MLXSW_PCI_FW_READY                     0xA1844
-#define MLXSW_PCI_FW_READY_MASK                        0xFF
-#define MLXSW_PCI_FW_READY_MAGIC               0x5E
+#else
 
-#define MLXSW_PCI_DOORBELL_SDQ_OFFSET          0x000
-#define MLXSW_PCI_DOORBELL_RDQ_OFFSET          0x200
-#define MLXSW_PCI_DOORBELL_CQ_OFFSET           0x400
-#define MLXSW_PCI_DOORBELL_EQ_OFFSET           0x600
-#define MLXSW_PCI_DOORBELL_ARM_CQ_OFFSET       0x800
-#define MLXSW_PCI_DOORBELL_ARM_EQ_OFFSET       0xA00
+static inline int
+mlxsw_pci_driver_register(struct pci_driver *pci_driver)
+{
+       return 0;
+}
 
-#define MLXSW_PCI_DOORBELL(offset, type_offset, num)   \
-       ((offset) + (type_offset) + (num) * 4)
+static inline void
+mlxsw_pci_driver_unregister(struct pci_driver *pci_driver)
+{
+}
 
-#define MLXSW_PCI_CQS_MAX      96
-#define MLXSW_PCI_EQS_COUNT    2
-#define MLXSW_PCI_EQ_ASYNC_NUM 0
-#define MLXSW_PCI_EQ_COMP_NUM  1
-
-#define MLXSW_PCI_AQ_PAGES     8
-#define MLXSW_PCI_AQ_SIZE      (MLXSW_PCI_PAGE_SIZE * MLXSW_PCI_AQ_PAGES)
-#define MLXSW_PCI_WQE_SIZE     32 /* 32 bytes per element */
-#define MLXSW_PCI_CQE_SIZE     16 /* 16 bytes per element */
-#define MLXSW_PCI_EQE_SIZE     16 /* 16 bytes per element */
-#define MLXSW_PCI_WQE_COUNT    (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
-#define MLXSW_PCI_CQE_COUNT    (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE_SIZE)
-#define MLXSW_PCI_EQE_COUNT    (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_EQE_SIZE)
-#define MLXSW_PCI_EQE_UPDATE_COUNT     0x80
-
-#define MLXSW_PCI_WQE_SG_ENTRIES       3
-#define MLXSW_PCI_WQE_TYPE_ETHERNET    0xA
-
-/* pci_wqe_c
- * If set it indicates that a completion should be reported upon
- * execution of this descriptor.
- */
-MLXSW_ITEM32(pci, wqe, c, 0x00, 31, 1);
-
-/* pci_wqe_lp
- * Local Processing, set if packet should be processed by the local
- * switch hardware:
- * For Ethernet EMAD (Direct Route and non Direct Route) -
- * must be set if packet destination is local device
- * For InfiniBand CTL - must be set if packet destination is local device
- * Otherwise it must be clear
- * Local Process packets must not exceed the size of 2K (including payload
- * and headers).
- */
-MLXSW_ITEM32(pci, wqe, lp, 0x00, 30, 1);
-
-/* pci_wqe_type
- * Packet type.
- */
-MLXSW_ITEM32(pci, wqe, type, 0x00, 23, 4);
-
-/* pci_wqe_byte_count
- * Size of i-th scatter/gather entry, 0 if entry is unused.
- */
-MLXSW_ITEM16_INDEXED(pci, wqe, byte_count, 0x02, 0, 14, 0x02, 0x00, false);
-
-/* pci_wqe_address
- * Physical address of i-th scatter/gather entry.
- * Gather Entries must be 2Byte aligned.
- */
-MLXSW_ITEM64_INDEXED(pci, wqe, address, 0x08, 0, 64, 0x8, 0x0, false);
-
-/* pci_cqe_lag
- * Packet arrives from a port which is a LAG
- */
-MLXSW_ITEM32(pci, cqe, lag, 0x00, 23, 1);
-
-/* pci_cqe_system_port/lag_id
- * When lag=0: System port on which the packet was received
- * When lag=1:
- * bits [15:4] LAG ID on which the packet was received
- * bits [3:0] sub_port on which the packet was received
- */
-MLXSW_ITEM32(pci, cqe, system_port, 0x00, 0, 16);
-MLXSW_ITEM32(pci, cqe, lag_id, 0x00, 4, 12);
-MLXSW_ITEM32(pci, cqe, lag_port_index, 0x00, 0, 4);
-
-/* pci_cqe_wqe_counter
- * WQE count of the WQEs completed on the associated dqn
- */
-MLXSW_ITEM32(pci, cqe, wqe_counter, 0x04, 16, 16);
-
-/* pci_cqe_byte_count
- * Byte count of received packets including additional two
- * Reserved Bytes that are append to the end of the frame.
- * Reserved for Send CQE.
- */
-MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14);
-
-/* pci_cqe_trap_id
- * Trap ID that captured the packet.
- */
-MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 8);
-
-/* pci_cqe_crc
- * Length include CRC. Indicates the length field includes
- * the packet's CRC.
- */
-MLXSW_ITEM32(pci, cqe, crc, 0x0C, 8, 1);
-
-/* pci_cqe_e
- * CQE with Error.
- */
-MLXSW_ITEM32(pci, cqe, e, 0x0C, 7, 1);
-
-/* pci_cqe_sr
- * 1 - Send Queue
- * 0 - Receive Queue
- */
-MLXSW_ITEM32(pci, cqe, sr, 0x0C, 6, 1);
-
-/* pci_cqe_dqn
- * Descriptor Queue (DQ) Number.
- */
-MLXSW_ITEM32(pci, cqe, dqn, 0x0C, 1, 5);
-
-/* pci_cqe_owner
- * Ownership bit.
- */
-MLXSW_ITEM32(pci, cqe, owner, 0x0C, 0, 1);
-
-/* pci_eqe_event_type
- * Event type.
- */
-MLXSW_ITEM32(pci, eqe, event_type, 0x0C, 24, 8);
-#define MLXSW_PCI_EQE_EVENT_TYPE_COMP  0x00
-#define MLXSW_PCI_EQE_EVENT_TYPE_CMD   0x0A
-
-/* pci_eqe_event_sub_type
- * Event type.
- */
-MLXSW_ITEM32(pci, eqe, event_sub_type, 0x0C, 16, 8);
-
-/* pci_eqe_cqn
- * Completion Queue that triggeret this EQE.
- */
-MLXSW_ITEM32(pci, eqe, cqn, 0x0C, 8, 7);
-
-/* pci_eqe_owner
- * Ownership bit.
- */
-MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1);
-
-/* pci_eqe_cmd_token
- * Command completion event - token
- */
-MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16);
-
-/* pci_eqe_cmd_status
- * Command completion event - status
- */
-MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8);
-
-/* pci_eqe_cmd_out_param_h
- * Command completion event - output parameter - higher part
- */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32);
-
-/* pci_eqe_cmd_out_param_l
- * Command completion event - output parameter - lower part
- */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32);
+#endif
 
 #endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
new file mode 100644 (file)
index 0000000..708736f
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
+ * Copyright (c) 2015-2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2015-2016 Jiri Pirko <jiri@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MLXSW_PCI_HW_H
+#define _MLXSW_PCI_HW_H
+
+#include <linux/bitops.h>
+
+#include "item.h"
+
+#define MLXSW_PCI_BAR0_SIZE            (1024 * 1024) /* 1MB */
+#define MLXSW_PCI_PAGE_SIZE            4096
+
+#define MLXSW_PCI_CIR_BASE                     0x71000
+#define MLXSW_PCI_CIR_IN_PARAM_HI              MLXSW_PCI_CIR_BASE
+#define MLXSW_PCI_CIR_IN_PARAM_LO              (MLXSW_PCI_CIR_BASE + 0x04)
+#define MLXSW_PCI_CIR_IN_MODIFIER              (MLXSW_PCI_CIR_BASE + 0x08)
+#define MLXSW_PCI_CIR_OUT_PARAM_HI             (MLXSW_PCI_CIR_BASE + 0x0C)
+#define MLXSW_PCI_CIR_OUT_PARAM_LO             (MLXSW_PCI_CIR_BASE + 0x10)
+#define MLXSW_PCI_CIR_TOKEN                    (MLXSW_PCI_CIR_BASE + 0x14)
+#define MLXSW_PCI_CIR_CTRL                     (MLXSW_PCI_CIR_BASE + 0x18)
+#define MLXSW_PCI_CIR_CTRL_GO_BIT              BIT(23)
+#define MLXSW_PCI_CIR_CTRL_EVREQ_BIT           BIT(22)
+#define MLXSW_PCI_CIR_CTRL_OPCODE_MOD_SHIFT    12
+#define MLXSW_PCI_CIR_CTRL_STATUS_SHIFT                24
+#define MLXSW_PCI_CIR_TIMEOUT_MSECS            1000
+
+#define MLXSW_PCI_SW_RESET                     0xF0010
+#define MLXSW_PCI_SW_RESET_RST_BIT             BIT(0)
+#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       5000
+#define MLXSW_PCI_FW_READY                     0xA1844
+#define MLXSW_PCI_FW_READY_MASK                        0xFF
+#define MLXSW_PCI_FW_READY_MAGIC               0x5E
+
+#define MLXSW_PCI_DOORBELL_SDQ_OFFSET          0x000
+#define MLXSW_PCI_DOORBELL_RDQ_OFFSET          0x200
+#define MLXSW_PCI_DOORBELL_CQ_OFFSET           0x400
+#define MLXSW_PCI_DOORBELL_EQ_OFFSET           0x600
+#define MLXSW_PCI_DOORBELL_ARM_CQ_OFFSET       0x800
+#define MLXSW_PCI_DOORBELL_ARM_EQ_OFFSET       0xA00
+
+#define MLXSW_PCI_DOORBELL(offset, type_offset, num)   \
+       ((offset) + (type_offset) + (num) * 4)
+
+#define MLXSW_PCI_CQS_MAX      96
+#define MLXSW_PCI_EQS_COUNT    2
+#define MLXSW_PCI_EQ_ASYNC_NUM 0
+#define MLXSW_PCI_EQ_COMP_NUM  1
+
+#define MLXSW_PCI_AQ_PAGES     8
+#define MLXSW_PCI_AQ_SIZE      (MLXSW_PCI_PAGE_SIZE * MLXSW_PCI_AQ_PAGES)
+#define MLXSW_PCI_WQE_SIZE     32 /* 32 bytes per element */
+#define MLXSW_PCI_CQE_SIZE     16 /* 16 bytes per element */
+#define MLXSW_PCI_EQE_SIZE     16 /* 16 bytes per element */
+#define MLXSW_PCI_WQE_COUNT    (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
+#define MLXSW_PCI_CQE_COUNT    (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE_SIZE)
+#define MLXSW_PCI_EQE_COUNT    (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_EQE_SIZE)
+#define MLXSW_PCI_EQE_UPDATE_COUNT     0x80
+
+#define MLXSW_PCI_WQE_SG_ENTRIES       3
+#define MLXSW_PCI_WQE_TYPE_ETHERNET    0xA
+
+/* pci_wqe_c
+ * If set it indicates that a completion should be reported upon
+ * execution of this descriptor.
+ */
+MLXSW_ITEM32(pci, wqe, c, 0x00, 31, 1);
+
+/* pci_wqe_lp
+ * Local Processing, set if packet should be processed by the local
+ * switch hardware:
+ * For Ethernet EMAD (Direct Route and non Direct Route) -
+ * must be set if packet destination is local device
+ * For InfiniBand CTL - must be set if packet destination is local device
+ * Otherwise it must be clear
+ * Local Process packets must not exceed the size of 2K (including payload
+ * and headers).
+ */
+MLXSW_ITEM32(pci, wqe, lp, 0x00, 30, 1);
+
+/* pci_wqe_type
+ * Packet type.
+ */
+MLXSW_ITEM32(pci, wqe, type, 0x00, 23, 4);
+
+/* pci_wqe_byte_count
+ * Size of i-th scatter/gather entry, 0 if entry is unused.
+ */
+MLXSW_ITEM16_INDEXED(pci, wqe, byte_count, 0x02, 0, 14, 0x02, 0x00, false);
+
+/* pci_wqe_address
+ * Physical address of i-th scatter/gather entry.
+ * Gather Entries must be 2Byte aligned.
+ */
+MLXSW_ITEM64_INDEXED(pci, wqe, address, 0x08, 0, 64, 0x8, 0x0, false);
+
+/* pci_cqe_lag
+ * Packet arrives from a port which is a LAG
+ */
+MLXSW_ITEM32(pci, cqe, lag, 0x00, 23, 1);
+
+/* pci_cqe_system_port/lag_id
+ * When lag=0: System port on which the packet was received
+ * When lag=1:
+ * bits [15:4] LAG ID on which the packet was received
+ * bits [3:0] sub_port on which the packet was received
+ */
+MLXSW_ITEM32(pci, cqe, system_port, 0x00, 0, 16);
+MLXSW_ITEM32(pci, cqe, lag_id, 0x00, 4, 12);
+MLXSW_ITEM32(pci, cqe, lag_port_index, 0x00, 0, 4);
+
+/* pci_cqe_wqe_counter
+ * WQE count of the WQEs completed on the associated dqn
+ */
+MLXSW_ITEM32(pci, cqe, wqe_counter, 0x04, 16, 16);
+
+/* pci_cqe_byte_count
+ * Byte count of received packets including additional two
+ * Reserved Bytes that are append to the end of the frame.
+ * Reserved for Send CQE.
+ */
+MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14);
+
+/* pci_cqe_trap_id
+ * Trap ID that captured the packet.
+ */
+MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 8);
+
+/* pci_cqe_crc
+ * Length include CRC. Indicates the length field includes
+ * the packet's CRC.
+ */
+MLXSW_ITEM32(pci, cqe, crc, 0x0C, 8, 1);
+
+/* pci_cqe_e
+ * CQE with Error.
+ */
+MLXSW_ITEM32(pci, cqe, e, 0x0C, 7, 1);
+
+/* pci_cqe_sr
+ * 1 - Send Queue
+ * 0 - Receive Queue
+ */
+MLXSW_ITEM32(pci, cqe, sr, 0x0C, 6, 1);
+
+/* pci_cqe_dqn
+ * Descriptor Queue (DQ) Number.
+ */
+MLXSW_ITEM32(pci, cqe, dqn, 0x0C, 1, 5);
+
+/* pci_cqe_owner
+ * Ownership bit.
+ */
+MLXSW_ITEM32(pci, cqe, owner, 0x0C, 0, 1);
+
+/* pci_eqe_event_type
+ * Event type.
+ */
+MLXSW_ITEM32(pci, eqe, event_type, 0x0C, 24, 8);
+#define MLXSW_PCI_EQE_EVENT_TYPE_COMP  0x00
+#define MLXSW_PCI_EQE_EVENT_TYPE_CMD   0x0A
+
+/* pci_eqe_event_sub_type
+ * Event type.
+ */
+MLXSW_ITEM32(pci, eqe, event_sub_type, 0x0C, 16, 8);
+
+/* pci_eqe_cqn
+ * Completion Queue that triggeret this EQE.
+ */
+MLXSW_ITEM32(pci, eqe, cqn, 0x0C, 8, 7);
+
+/* pci_eqe_owner
+ * Ownership bit.
+ */
+MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1);
+
+/* pci_eqe_cmd_token
+ * Command completion event - token
+ */
+MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16);
+
+/* pci_eqe_cmd_status
+ * Command completion event - status
+ */
+MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8);
+
+/* pci_eqe_cmd_out_param_h
+ * Command completion event - output parameter - higher part
+ */
+MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32);
+
+/* pci_eqe_cmd_out_param_l
+ * Command completion event - output parameter - lower part
+ */
+MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32);
+
+#endif
index 6460c7256f2ba0260245f69200bc176167b4c6ee..debcf264839844018f43bcff970956cfe3e9b993 100644 (file)
 struct mlxsw_reg_info {
        u16 id;
        u16 len; /* In u8 */
+       const char *name;
 };
 
+#define MLXSW_REG_DEFINE(_name, _id, _len)                             \
+static const struct mlxsw_reg_info mlxsw_reg_##_name = {               \
+       .id = _id,                                                      \
+       .len = _len,                                                    \
+       .name = #_name,                                                 \
+}
+
 #define MLXSW_REG(type) (&mlxsw_reg_##type)
 #define MLXSW_REG_LEN(type) MLXSW_REG(type)->len
 #define MLXSW_REG_ZERO(type, payload) memset(payload, 0, MLXSW_REG(type)->len)
@@ -61,10 +69,7 @@ struct mlxsw_reg_info {
 #define MLXSW_REG_SGCR_ID 0x2000
 #define MLXSW_REG_SGCR_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_sgcr = {
-       .id = MLXSW_REG_SGCR_ID,
-       .len = MLXSW_REG_SGCR_LEN,
-};
+MLXSW_REG_DEFINE(sgcr, MLXSW_REG_SGCR_ID, MLXSW_REG_SGCR_LEN);
 
 /* reg_sgcr_llb
  * Link Local Broadcast (Default=0)
@@ -87,10 +92,7 @@ static inline void mlxsw_reg_sgcr_pack(char *payload, bool llb)
 #define MLXSW_REG_SPAD_ID 0x2002
 #define MLXSW_REG_SPAD_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_spad = {
-       .id = MLXSW_REG_SPAD_ID,
-       .len = MLXSW_REG_SPAD_LEN,
-};
+MLXSW_REG_DEFINE(spad, MLXSW_REG_SPAD_ID, MLXSW_REG_SPAD_LEN);
 
 /* reg_spad_base_mac
  * Base MAC address for the switch partitions.
@@ -109,10 +111,7 @@ MLXSW_ITEM_BUF(reg, spad, base_mac, 0x02, 6);
 #define MLXSW_REG_SMID_ID 0x2007
 #define MLXSW_REG_SMID_LEN 0x240
 
-static const struct mlxsw_reg_info mlxsw_reg_smid = {
-       .id = MLXSW_REG_SMID_ID,
-       .len = MLXSW_REG_SMID_LEN,
-};
+MLXSW_REG_DEFINE(smid, MLXSW_REG_SMID_ID, MLXSW_REG_SMID_LEN);
 
 /* reg_smid_swid
  * Switch partition ID.
@@ -156,10 +155,7 @@ static inline void mlxsw_reg_smid_pack(char *payload, u16 mid,
 #define MLXSW_REG_SSPR_ID 0x2008
 #define MLXSW_REG_SSPR_LEN 0x8
 
-static const struct mlxsw_reg_info mlxsw_reg_sspr = {
-       .id = MLXSW_REG_SSPR_ID,
-       .len = MLXSW_REG_SSPR_LEN,
-};
+MLXSW_REG_DEFINE(sspr, MLXSW_REG_SSPR_ID, MLXSW_REG_SSPR_LEN);
 
 /* reg_sspr_m
  * Master - if set, then the record describes the master system port.
@@ -215,10 +211,7 @@ static inline void mlxsw_reg_sspr_pack(char *payload, u8 local_port)
 #define MLXSW_REG_SFDAT_ID 0x2009
 #define MLXSW_REG_SFDAT_LEN 0x8
 
-static const struct mlxsw_reg_info mlxsw_reg_sfdat = {
-       .id = MLXSW_REG_SFDAT_ID,
-       .len = MLXSW_REG_SFDAT_LEN,
-};
+MLXSW_REG_DEFINE(sfdat, MLXSW_REG_SFDAT_ID, MLXSW_REG_SFDAT_LEN);
 
 /* reg_sfdat_swid
  * Switch partition ID.
@@ -256,10 +249,7 @@ static inline void mlxsw_reg_sfdat_pack(char *payload, u32 age_time)
 #define MLXSW_REG_SFD_LEN (MLXSW_REG_SFD_BASE_LEN +    \
                           MLXSW_REG_SFD_REC_LEN * MLXSW_REG_SFD_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_sfd = {
-       .id = MLXSW_REG_SFD_ID,
-       .len = MLXSW_REG_SFD_LEN,
-};
+MLXSW_REG_DEFINE(sfd, MLXSW_REG_SFD_ID, MLXSW_REG_SFD_LEN);
 
 /* reg_sfd_swid
  * Switch partition ID for queries. Reserved on Write.
@@ -580,10 +570,7 @@ mlxsw_reg_sfd_mc_pack(char *payload, int rec_index,
 #define MLXSW_REG_SFN_LEN (MLXSW_REG_SFN_BASE_LEN +    \
                           MLXSW_REG_SFN_REC_LEN * MLXSW_REG_SFN_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_sfn = {
-       .id = MLXSW_REG_SFN_ID,
-       .len = MLXSW_REG_SFN_LEN,
-};
+MLXSW_REG_DEFINE(sfn, MLXSW_REG_SFN_ID, MLXSW_REG_SFN_LEN);
 
 /* reg_sfn_swid
  * Switch partition ID.
@@ -701,10 +688,7 @@ static inline void mlxsw_reg_sfn_mac_lag_unpack(char *payload, int rec_index,
 #define MLXSW_REG_SPMS_ID 0x200D
 #define MLXSW_REG_SPMS_LEN 0x404
 
-static const struct mlxsw_reg_info mlxsw_reg_spms = {
-       .id = MLXSW_REG_SPMS_ID,
-       .len = MLXSW_REG_SPMS_LEN,
-};
+MLXSW_REG_DEFINE(spms, MLXSW_REG_SPMS_ID, MLXSW_REG_SPMS_LEN);
 
 /* reg_spms_local_port
  * Local port number.
@@ -748,10 +732,7 @@ static inline void mlxsw_reg_spms_vid_pack(char *payload, u16 vid,
 #define MLXSW_REG_SPVID_ID 0x200E
 #define MLXSW_REG_SPVID_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_spvid = {
-       .id = MLXSW_REG_SPVID_ID,
-       .len = MLXSW_REG_SPVID_LEN,
-};
+MLXSW_REG_DEFINE(spvid, MLXSW_REG_SPVID_ID, MLXSW_REG_SPVID_LEN);
 
 /* reg_spvid_local_port
  * Local port number.
@@ -792,10 +773,7 @@ static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid)
 #define MLXSW_REG_SPVM_LEN (MLXSW_REG_SPVM_BASE_LEN +  \
                    MLXSW_REG_SPVM_REC_LEN * MLXSW_REG_SPVM_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_spvm = {
-       .id = MLXSW_REG_SPVM_ID,
-       .len = MLXSW_REG_SPVM_LEN,
-};
+MLXSW_REG_DEFINE(spvm, MLXSW_REG_SPVM_ID, MLXSW_REG_SPVM_LEN);
 
 /* reg_spvm_pt
  * Priority tagged. If this bit is set, packets forwarded to the port with
@@ -891,10 +869,7 @@ static inline void mlxsw_reg_spvm_pack(char *payload, u8 local_port,
 #define MLXSW_REG_SPAFT_ID 0x2010
 #define MLXSW_REG_SPAFT_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_spaft = {
-       .id = MLXSW_REG_SPAFT_ID,
-       .len = MLXSW_REG_SPAFT_LEN,
-};
+MLXSW_REG_DEFINE(spaft, MLXSW_REG_SPAFT_ID, MLXSW_REG_SPAFT_LEN);
 
 /* reg_spaft_local_port
  * Local port number.
@@ -947,10 +922,7 @@ static inline void mlxsw_reg_spaft_pack(char *payload, u8 local_port,
 #define MLXSW_REG_SFGC_ID 0x2011
 #define MLXSW_REG_SFGC_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_sfgc = {
-       .id = MLXSW_REG_SFGC_ID,
-       .len = MLXSW_REG_SFGC_LEN,
-};
+MLXSW_REG_DEFINE(sfgc, MLXSW_REG_SFGC_ID, MLXSW_REG_SFGC_LEN);
 
 enum mlxsw_reg_sfgc_type {
        MLXSW_REG_SFGC_TYPE_BROADCAST,
@@ -1045,10 +1017,7 @@ mlxsw_reg_sfgc_pack(char *payload, enum mlxsw_reg_sfgc_type type,
 #define MLXSW_REG_SFTR_ID 0x2012
 #define MLXSW_REG_SFTR_LEN 0x420
 
-static const struct mlxsw_reg_info mlxsw_reg_sftr = {
-       .id = MLXSW_REG_SFTR_ID,
-       .len = MLXSW_REG_SFTR_LEN,
-};
+MLXSW_REG_DEFINE(sftr, MLXSW_REG_SFTR_ID, MLXSW_REG_SFTR_LEN);
 
 /* reg_sftr_swid
  * Switch partition ID with which to associate the port.
@@ -1118,10 +1087,7 @@ static inline void mlxsw_reg_sftr_pack(char *payload,
 #define MLXSW_REG_SFDF_ID 0x2013
 #define MLXSW_REG_SFDF_LEN 0x14
 
-static const struct mlxsw_reg_info mlxsw_reg_sfdf = {
-       .id = MLXSW_REG_SFDF_ID,
-       .len = MLXSW_REG_SFDF_LEN,
-};
+MLXSW_REG_DEFINE(sfdf, MLXSW_REG_SFDF_ID, MLXSW_REG_SFDF_LEN);
 
 /* reg_sfdf_swid
  * Switch partition ID.
@@ -1205,10 +1171,7 @@ MLXSW_ITEM32(reg, sfdf, lag_fid_lag_id, 0x08, 0, 10);
 #define MLXSW_REG_SLDR_ID 0x2014
 #define MLXSW_REG_SLDR_LEN 0x0C /* counting in only one port in list */
 
-static const struct mlxsw_reg_info mlxsw_reg_sldr = {
-       .id = MLXSW_REG_SLDR_ID,
-       .len = MLXSW_REG_SLDR_LEN,
-};
+MLXSW_REG_DEFINE(sldr, MLXSW_REG_SLDR_ID, MLXSW_REG_SLDR_LEN);
 
 enum mlxsw_reg_sldr_op {
        /* Indicates a creation of a new LAG-ID, lag_id must be valid */
@@ -1288,10 +1251,7 @@ static inline void mlxsw_reg_sldr_lag_remove_port_pack(char *payload, u8 lag_id,
 #define MLXSW_REG_SLCR_ID 0x2015
 #define MLXSW_REG_SLCR_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_slcr = {
-       .id = MLXSW_REG_SLCR_ID,
-       .len = MLXSW_REG_SLCR_LEN,
-};
+MLXSW_REG_DEFINE(slcr, MLXSW_REG_SLCR_ID, MLXSW_REG_SLCR_LEN);
 
 enum mlxsw_reg_slcr_pp {
        /* Global Configuration (for all ports) */
@@ -1404,10 +1364,7 @@ static inline void mlxsw_reg_slcr_pack(char *payload, u16 lag_hash)
 #define MLXSW_REG_SLCOR_ID 0x2016
 #define MLXSW_REG_SLCOR_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_slcor = {
-       .id = MLXSW_REG_SLCOR_ID,
-       .len = MLXSW_REG_SLCOR_LEN,
-};
+MLXSW_REG_DEFINE(slcor, MLXSW_REG_SLCOR_ID, MLXSW_REG_SLCOR_LEN);
 
 enum mlxsw_reg_slcor_col {
        /* Port is added with collector disabled */
@@ -1490,10 +1447,7 @@ static inline void mlxsw_reg_slcor_col_disable_pack(char *payload,
 #define MLXSW_REG_SPMLR_ID 0x2018
 #define MLXSW_REG_SPMLR_LEN 0x8
 
-static const struct mlxsw_reg_info mlxsw_reg_spmlr = {
-       .id = MLXSW_REG_SPMLR_ID,
-       .len = MLXSW_REG_SPMLR_LEN,
-};
+MLXSW_REG_DEFINE(spmlr, MLXSW_REG_SPMLR_ID, MLXSW_REG_SPMLR_LEN);
 
 /* reg_spmlr_local_port
  * Local port number.
@@ -1544,10 +1498,7 @@ static inline void mlxsw_reg_spmlr_pack(char *payload, u8 local_port,
 #define MLXSW_REG_SVFA_ID 0x201C
 #define MLXSW_REG_SVFA_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_svfa = {
-       .id = MLXSW_REG_SVFA_ID,
-       .len = MLXSW_REG_SVFA_LEN,
-};
+MLXSW_REG_DEFINE(svfa, MLXSW_REG_SVFA_ID, MLXSW_REG_SVFA_LEN);
 
 /* reg_svfa_swid
  * Switch partition ID.
@@ -1636,10 +1587,7 @@ static inline void mlxsw_reg_svfa_pack(char *payload, u8 local_port,
 #define MLXSW_REG_SVPE_ID 0x201E
 #define MLXSW_REG_SVPE_LEN 0x4
 
-static const struct mlxsw_reg_info mlxsw_reg_svpe = {
-       .id = MLXSW_REG_SVPE_ID,
-       .len = MLXSW_REG_SVPE_LEN,
-};
+MLXSW_REG_DEFINE(svpe, MLXSW_REG_SVPE_ID, MLXSW_REG_SVPE_LEN);
 
 /* reg_svpe_local_port
  * Local port number
@@ -1672,10 +1620,7 @@ static inline void mlxsw_reg_svpe_pack(char *payload, u8 local_port,
 #define MLXSW_REG_SFMR_ID 0x201F
 #define MLXSW_REG_SFMR_LEN 0x18
 
-static const struct mlxsw_reg_info mlxsw_reg_sfmr = {
-       .id = MLXSW_REG_SFMR_ID,
-       .len = MLXSW_REG_SFMR_LEN,
-};
+MLXSW_REG_DEFINE(sfmr, MLXSW_REG_SFMR_ID, MLXSW_REG_SFMR_LEN);
 
 enum mlxsw_reg_sfmr_op {
        MLXSW_REG_SFMR_OP_CREATE_FID,
@@ -1762,10 +1707,7 @@ static inline void mlxsw_reg_sfmr_pack(char *payload,
                              MLXSW_REG_SPVMLR_REC_LEN * \
                              MLXSW_REG_SPVMLR_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_spvmlr = {
-       .id = MLXSW_REG_SPVMLR_ID,
-       .len = MLXSW_REG_SPVMLR_LEN,
-};
+MLXSW_REG_DEFINE(spvmlr, MLXSW_REG_SPVMLR_ID, MLXSW_REG_SPVMLR_LEN);
 
 /* reg_spvmlr_local_port
  * Local ingress port.
@@ -1823,10 +1765,7 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port,
 #define MLXSW_REG_QTCT_ID 0x400A
 #define MLXSW_REG_QTCT_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_qtct = {
-       .id = MLXSW_REG_QTCT_ID,
-       .len = MLXSW_REG_QTCT_LEN,
-};
+MLXSW_REG_DEFINE(qtct, MLXSW_REG_QTCT_ID, MLXSW_REG_QTCT_LEN);
 
 /* reg_qtct_local_port
  * Local port number.
@@ -1875,10 +1814,7 @@ static inline void mlxsw_reg_qtct_pack(char *payload, u8 local_port,
 #define MLXSW_REG_QEEC_ID 0x400D
 #define MLXSW_REG_QEEC_LEN 0x1C
 
-static const struct mlxsw_reg_info mlxsw_reg_qeec = {
-       .id = MLXSW_REG_QEEC_ID,
-       .len = MLXSW_REG_QEEC_LEN,
-};
+MLXSW_REG_DEFINE(qeec, MLXSW_REG_QEEC_ID, MLXSW_REG_QEEC_LEN);
 
 /* reg_qeec_local_port
  * Local port number.
@@ -2000,10 +1936,7 @@ static inline void mlxsw_reg_qeec_pack(char *payload, u8 local_port,
 #define MLXSW_REG_PMLP_ID 0x5002
 #define MLXSW_REG_PMLP_LEN 0x40
 
-static const struct mlxsw_reg_info mlxsw_reg_pmlp = {
-       .id = MLXSW_REG_PMLP_ID,
-       .len = MLXSW_REG_PMLP_LEN,
-};
+MLXSW_REG_DEFINE(pmlp, MLXSW_REG_PMLP_ID, MLXSW_REG_PMLP_LEN);
 
 /* reg_pmlp_rxtx
  * 0 - Tx value is used for both Tx and Rx.
@@ -2059,10 +1992,7 @@ static inline void mlxsw_reg_pmlp_pack(char *payload, u8 local_port)
 #define MLXSW_REG_PMTU_ID 0x5003
 #define MLXSW_REG_PMTU_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_pmtu = {
-       .id = MLXSW_REG_PMTU_ID,
-       .len = MLXSW_REG_PMTU_LEN,
-};
+MLXSW_REG_DEFINE(pmtu, MLXSW_REG_PMTU_ID, MLXSW_REG_PMTU_LEN);
 
 /* reg_pmtu_local_port
  * Local port number.
@@ -2116,10 +2046,7 @@ static inline void mlxsw_reg_pmtu_pack(char *payload, u8 local_port,
 #define MLXSW_REG_PTYS_ID 0x5004
 #define MLXSW_REG_PTYS_LEN 0x40
 
-static const struct mlxsw_reg_info mlxsw_reg_ptys = {
-       .id = MLXSW_REG_PTYS_ID,
-       .len = MLXSW_REG_PTYS_LEN,
-};
+MLXSW_REG_DEFINE(ptys, MLXSW_REG_PTYS_ID, MLXSW_REG_PTYS_LEN);
 
 /* reg_ptys_local_port
  * Local port number.
@@ -2232,10 +2159,7 @@ static inline void mlxsw_reg_ptys_unpack(char *payload, u32 *p_eth_proto_cap,
 #define MLXSW_REG_PPAD_ID 0x5005
 #define MLXSW_REG_PPAD_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_ppad = {
-       .id = MLXSW_REG_PPAD_ID,
-       .len = MLXSW_REG_PPAD_LEN,
-};
+MLXSW_REG_DEFINE(ppad, MLXSW_REG_PPAD_ID, MLXSW_REG_PPAD_LEN);
 
 /* reg_ppad_single_base_mac
  * 0: base_mac, local port should be 0 and mac[7:0] is
@@ -2273,10 +2197,7 @@ static inline void mlxsw_reg_ppad_pack(char *payload, bool single_base_mac,
 #define MLXSW_REG_PAOS_ID 0x5006
 #define MLXSW_REG_PAOS_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_paos = {
-       .id = MLXSW_REG_PAOS_ID,
-       .len = MLXSW_REG_PAOS_LEN,
-};
+MLXSW_REG_DEFINE(paos, MLXSW_REG_PAOS_ID, MLXSW_REG_PAOS_LEN);
 
 /* reg_paos_swid
  * Switch partition ID with which to associate the port.
@@ -2356,10 +2277,7 @@ static inline void mlxsw_reg_paos_pack(char *payload, u8 local_port,
 #define MLXSW_REG_PFCC_ID 0x5007
 #define MLXSW_REG_PFCC_LEN 0x20
 
-static const struct mlxsw_reg_info mlxsw_reg_pfcc = {
-       .id = MLXSW_REG_PFCC_ID,
-       .len = MLXSW_REG_PFCC_LEN,
-};
+MLXSW_REG_DEFINE(pfcc, MLXSW_REG_PFCC_ID, MLXSW_REG_PFCC_LEN);
 
 /* reg_pfcc_local_port
  * Local port number.
@@ -2495,10 +2413,7 @@ static inline void mlxsw_reg_pfcc_pack(char *payload, u8 local_port)
 #define MLXSW_REG_PPCNT_ID 0x5008
 #define MLXSW_REG_PPCNT_LEN 0x100
 
-static const struct mlxsw_reg_info mlxsw_reg_ppcnt = {
-       .id = MLXSW_REG_PPCNT_ID,
-       .len = MLXSW_REG_PPCNT_LEN,
-};
+MLXSW_REG_DEFINE(ppcnt, MLXSW_REG_PPCNT_ID, MLXSW_REG_PPCNT_LEN);
 
 /* reg_ppcnt_swid
  * For HCA: must be always 0.
@@ -2768,10 +2683,7 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port,
 #define MLXSW_REG_PPTB_ID 0x500B
 #define MLXSW_REG_PPTB_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_pptb = {
-       .id = MLXSW_REG_PPTB_ID,
-       .len = MLXSW_REG_PPTB_LEN,
-};
+MLXSW_REG_DEFINE(pptb, MLXSW_REG_PPTB_ID, MLXSW_REG_PPTB_LEN);
 
 enum {
        MLXSW_REG_PPTB_MM_UM,
@@ -2865,10 +2777,7 @@ static inline void mlxsw_reg_pptb_prio_to_buff_pack(char *payload, u8 prio,
 #define MLXSW_REG_PBMC_ID 0x500C
 #define MLXSW_REG_PBMC_LEN 0x6C
 
-static const struct mlxsw_reg_info mlxsw_reg_pbmc = {
-       .id = MLXSW_REG_PBMC_ID,
-       .len = MLXSW_REG_PBMC_LEN,
-};
+MLXSW_REG_DEFINE(pbmc, MLXSW_REG_PBMC_ID, MLXSW_REG_PBMC_LEN);
 
 /* reg_pbmc_local_port
  * Local port number.
@@ -2978,10 +2887,7 @@ static inline void mlxsw_reg_pbmc_lossless_buffer_pack(char *payload,
 #define MLXSW_REG_PSPA_ID 0x500D
 #define MLXSW_REG_PSPA_LEN 0x8
 
-static const struct mlxsw_reg_info mlxsw_reg_pspa = {
-       .id = MLXSW_REG_PSPA_ID,
-       .len = MLXSW_REG_PSPA_LEN,
-};
+MLXSW_REG_DEFINE(pspa, MLXSW_REG_PSPA_ID, MLXSW_REG_PSPA_LEN);
 
 /* reg_pspa_swid
  * Switch partition ID.
@@ -3017,10 +2923,7 @@ static inline void mlxsw_reg_pspa_pack(char *payload, u8 swid, u8 local_port)
 #define MLXSW_REG_HTGT_ID 0x7002
 #define MLXSW_REG_HTGT_LEN 0x100
 
-static const struct mlxsw_reg_info mlxsw_reg_htgt = {
-       .id = MLXSW_REG_HTGT_ID,
-       .len = MLXSW_REG_HTGT_LEN,
-};
+MLXSW_REG_DEFINE(htgt, MLXSW_REG_HTGT_ID, MLXSW_REG_HTGT_LEN);
 
 /* reg_htgt_swid
  * Switch partition ID.
@@ -3154,10 +3057,7 @@ static inline void mlxsw_reg_htgt_pack(char *payload,
 #define MLXSW_REG_HPKT_ID 0x7003
 #define MLXSW_REG_HPKT_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_hpkt = {
-       .id = MLXSW_REG_HPKT_ID,
-       .len = MLXSW_REG_HPKT_LEN,
-};
+MLXSW_REG_DEFINE(hpkt, MLXSW_REG_HPKT_ID, MLXSW_REG_HPKT_LEN);
 
 enum {
        MLXSW_REG_HPKT_ACK_NOT_REQUIRED,
@@ -3256,10 +3156,7 @@ static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id)
 #define MLXSW_REG_RGCR_ID 0x8001
 #define MLXSW_REG_RGCR_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_rgcr = {
-       .id = MLXSW_REG_RGCR_ID,
-       .len = MLXSW_REG_RGCR_LEN,
-};
+MLXSW_REG_DEFINE(rgcr, MLXSW_REG_RGCR_ID, MLXSW_REG_RGCR_LEN);
 
 /* reg_rgcr_ipv4_en
  * IPv4 router enable.
@@ -3330,10 +3227,7 @@ static inline void mlxsw_reg_rgcr_pack(char *payload, bool ipv4_en)
 #define MLXSW_REG_RITR_ID 0x8002
 #define MLXSW_REG_RITR_LEN 0x40
 
-static const struct mlxsw_reg_info mlxsw_reg_ritr = {
-       .id = MLXSW_REG_RITR_ID,
-       .len = MLXSW_REG_RITR_LEN,
-};
+MLXSW_REG_DEFINE(ritr, MLXSW_REG_RITR_ID, MLXSW_REG_RITR_LEN);
 
 /* reg_ritr_enable
  * Enables routing on the router interface.
@@ -3533,10 +3427,7 @@ static inline void mlxsw_reg_ritr_pack(char *payload, bool enable,
 #define MLXSW_REG_RATR_ID 0x8008
 #define MLXSW_REG_RATR_LEN 0x2C
 
-static const struct mlxsw_reg_info mlxsw_reg_ratr = {
-       .id = MLXSW_REG_RATR_ID,
-       .len = MLXSW_REG_RATR_LEN,
-};
+MLXSW_REG_DEFINE(ratr, MLXSW_REG_RATR_ID, MLXSW_REG_RATR_LEN);
 
 enum mlxsw_reg_ratr_op {
        /* Read */
@@ -3663,10 +3554,7 @@ static inline void mlxsw_reg_ratr_eth_entry_pack(char *payload,
 #define MLXSW_REG_RALTA_ID 0x8010
 #define MLXSW_REG_RALTA_LEN 0x04
 
-static const struct mlxsw_reg_info mlxsw_reg_ralta = {
-       .id = MLXSW_REG_RALTA_ID,
-       .len = MLXSW_REG_RALTA_LEN,
-};
+MLXSW_REG_DEFINE(ralta, MLXSW_REG_RALTA_ID, MLXSW_REG_RALTA_LEN);
 
 /* reg_ralta_op
  * opcode (valid for Write, must be 0 on Read)
@@ -3718,10 +3606,7 @@ static inline void mlxsw_reg_ralta_pack(char *payload, bool alloc,
 #define MLXSW_REG_RALST_ID 0x8011
 #define MLXSW_REG_RALST_LEN 0x104
 
-static const struct mlxsw_reg_info mlxsw_reg_ralst = {
-       .id = MLXSW_REG_RALST_ID,
-       .len = MLXSW_REG_RALST_LEN,
-};
+MLXSW_REG_DEFINE(ralst, MLXSW_REG_RALST_ID, MLXSW_REG_RALST_LEN);
 
 /* reg_ralst_root_bin
  * The bin number of the root bin.
@@ -3788,10 +3673,7 @@ static inline void mlxsw_reg_ralst_bin_pack(char *payload, u8 bin_number,
 #define MLXSW_REG_RALTB_ID 0x8012
 #define MLXSW_REG_RALTB_LEN 0x04
 
-static const struct mlxsw_reg_info mlxsw_reg_raltb = {
-       .id = MLXSW_REG_RALTB_ID,
-       .len = MLXSW_REG_RALTB_LEN,
-};
+MLXSW_REG_DEFINE(raltb, MLXSW_REG_RALTB_ID, MLXSW_REG_RALTB_LEN);
 
 /* reg_raltb_virtual_router
  * Virtual Router ID
@@ -3832,10 +3714,7 @@ static inline void mlxsw_reg_raltb_pack(char *payload, u16 virtual_router,
 #define MLXSW_REG_RALUE_ID 0x8013
 #define MLXSW_REG_RALUE_LEN 0x38
 
-static const struct mlxsw_reg_info mlxsw_reg_ralue = {
-       .id = MLXSW_REG_RALUE_ID,
-       .len = MLXSW_REG_RALUE_LEN,
-};
+MLXSW_REG_DEFINE(ralue, MLXSW_REG_RALUE_ID, MLXSW_REG_RALUE_LEN);
 
 /* reg_ralue_protocol
  * Protocol.
@@ -4095,10 +3974,7 @@ mlxsw_reg_ralue_act_ip2me_pack(char *payload)
 #define MLXSW_REG_RAUHT_ID 0x8014
 #define MLXSW_REG_RAUHT_LEN 0x74
 
-static const struct mlxsw_reg_info mlxsw_reg_rauht = {
-       .id = MLXSW_REG_RAUHT_ID,
-       .len = MLXSW_REG_RAUHT_LEN,
-};
+MLXSW_REG_DEFINE(rauht, MLXSW_REG_RAUHT_ID, MLXSW_REG_RAUHT_LEN);
 
 enum mlxsw_reg_rauht_type {
        MLXSW_REG_RAUHT_TYPE_IPV4,
@@ -4234,10 +4110,7 @@ static inline void mlxsw_reg_rauht_pack4(char *payload,
 #define MLXSW_REG_RALEU_ID 0x8015
 #define MLXSW_REG_RALEU_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_raleu = {
-       .id = MLXSW_REG_RALEU_ID,
-       .len = MLXSW_REG_RALEU_LEN,
-};
+MLXSW_REG_DEFINE(raleu, MLXSW_REG_RALEU_ID, MLXSW_REG_RALEU_LEN);
 
 /* reg_raleu_protocol
  * Protocol.
@@ -4309,10 +4182,7 @@ static inline void mlxsw_reg_raleu_pack(char *payload,
                MLXSW_REG_RAUHTD_REC_MAX_NUM * MLXSW_REG_RAUHTD_REC_LEN)
 #define MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC 4
 
-static const struct mlxsw_reg_info mlxsw_reg_rauhtd = {
-       .id = MLXSW_REG_RAUHTD_ID,
-       .len = MLXSW_REG_RAUHTD_LEN,
-};
+MLXSW_REG_DEFINE(rauhtd, MLXSW_REG_RAUHTD_ID, MLXSW_REG_RAUHTD_LEN);
 
 #define MLXSW_REG_RAUHTD_FILTER_A BIT(0)
 #define MLXSW_REG_RAUHTD_FILTER_RIF BIT(3)
@@ -4444,10 +4314,7 @@ static inline void mlxsw_reg_rauhtd_ent_ipv4_unpack(char *payload,
 #define MLXSW_REG_MFCR_ID 0x9001
 #define MLXSW_REG_MFCR_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mfcr = {
-       .id = MLXSW_REG_MFCR_ID,
-       .len = MLXSW_REG_MFCR_LEN,
-};
+MLXSW_REG_DEFINE(mfcr, MLXSW_REG_MFCR_ID, MLXSW_REG_MFCR_LEN);
 
 enum mlxsw_reg_mfcr_pwm_frequency {
        MLXSW_REG_MFCR_PWM_FEQ_11HZ = 0x00,
@@ -4507,10 +4374,7 @@ mlxsw_reg_mfcr_unpack(char *payload,
 #define MLXSW_REG_MFSC_ID 0x9002
 #define MLXSW_REG_MFSC_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mfsc = {
-       .id = MLXSW_REG_MFSC_ID,
-       .len = MLXSW_REG_MFSC_LEN,
-};
+MLXSW_REG_DEFINE(mfsc, MLXSW_REG_MFSC_ID, MLXSW_REG_MFSC_LEN);
 
 /* reg_mfsc_pwm
  * Fan pwm to control / monitor.
@@ -4541,10 +4405,7 @@ static inline void mlxsw_reg_mfsc_pack(char *payload, u8 pwm,
 #define MLXSW_REG_MFSM_ID 0x9003
 #define MLXSW_REG_MFSM_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mfsm = {
-       .id = MLXSW_REG_MFSM_ID,
-       .len = MLXSW_REG_MFSM_LEN,
-};
+MLXSW_REG_DEFINE(mfsm, MLXSW_REG_MFSM_ID, MLXSW_REG_MFSM_LEN);
 
 /* reg_mfsm_tacho
  * Fan tachometer index.
@@ -4572,10 +4433,7 @@ static inline void mlxsw_reg_mfsm_pack(char *payload, u8 tacho)
 #define MLXSW_REG_MTCAP_ID 0x9009
 #define MLXSW_REG_MTCAP_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mtcap = {
-       .id = MLXSW_REG_MTCAP_ID,
-       .len = MLXSW_REG_MTCAP_LEN,
-};
+MLXSW_REG_DEFINE(mtcap, MLXSW_REG_MTCAP_ID, MLXSW_REG_MTCAP_LEN);
 
 /* reg_mtcap_sensor_count
  * Number of sensors supported by the device.
@@ -4593,10 +4451,7 @@ MLXSW_ITEM32(reg, mtcap, sensor_count, 0x00, 0, 7);
 #define MLXSW_REG_MTMP_ID 0x900A
 #define MLXSW_REG_MTMP_LEN 0x20
 
-static const struct mlxsw_reg_info mlxsw_reg_mtmp = {
-       .id = MLXSW_REG_MTMP_ID,
-       .len = MLXSW_REG_MTMP_LEN,
-};
+MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN);
 
 /* reg_mtmp_sensor_index
  * Sensors index to access.
@@ -4679,10 +4534,7 @@ static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp,
 #define MLXSW_REG_MPAT_ID 0x901A
 #define MLXSW_REG_MPAT_LEN 0x78
 
-static const struct mlxsw_reg_info mlxsw_reg_mpat = {
-       .id = MLXSW_REG_MPAT_ID,
-       .len = MLXSW_REG_MPAT_LEN,
-};
+MLXSW_REG_DEFINE(mpat, MLXSW_REG_MPAT_ID, MLXSW_REG_MPAT_LEN);
 
 /* reg_mpat_pa_id
  * Port Analyzer ID.
@@ -4742,10 +4594,7 @@ static inline void mlxsw_reg_mpat_pack(char *payload, u8 pa_id,
 #define MLXSW_REG_MPAR_ID 0x901B
 #define MLXSW_REG_MPAR_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mpar = {
-       .id = MLXSW_REG_MPAR_ID,
-       .len = MLXSW_REG_MPAR_LEN,
-};
+MLXSW_REG_DEFINE(mpar, MLXSW_REG_MPAR_ID, MLXSW_REG_MPAR_LEN);
 
 /* reg_mpar_local_port
  * The local port to mirror the packets from.
@@ -4795,10 +4644,7 @@ static inline void mlxsw_reg_mpar_pack(char *payload, u8 local_port,
 #define MLXSW_REG_MLCR_ID 0x902B
 #define MLXSW_REG_MLCR_LEN 0x0C
 
-static const struct mlxsw_reg_info mlxsw_reg_mlcr = {
-       .id = MLXSW_REG_MLCR_ID,
-       .len = MLXSW_REG_MLCR_LEN,
-};
+MLXSW_REG_DEFINE(mlcr, MLXSW_REG_MLCR_ID, MLXSW_REG_MLCR_LEN);
 
 /* reg_mlcr_local_port
  * Local port number.
@@ -4839,10 +4685,7 @@ static inline void mlxsw_reg_mlcr_pack(char *payload, u8 local_port,
 #define MLXSW_REG_SBPR_ID 0xB001
 #define MLXSW_REG_SBPR_LEN 0x14
 
-static const struct mlxsw_reg_info mlxsw_reg_sbpr = {
-       .id = MLXSW_REG_SBPR_ID,
-       .len = MLXSW_REG_SBPR_LEN,
-};
+MLXSW_REG_DEFINE(sbpr, MLXSW_REG_SBPR_ID, MLXSW_REG_SBPR_LEN);
 
 /* shared direstion enum for SBPR, SBCM, SBPM */
 enum mlxsw_reg_sbxx_dir {
@@ -4899,10 +4742,7 @@ static inline void mlxsw_reg_sbpr_pack(char *payload, u8 pool,
 #define MLXSW_REG_SBCM_ID 0xB002
 #define MLXSW_REG_SBCM_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_sbcm = {
-       .id = MLXSW_REG_SBCM_ID,
-       .len = MLXSW_REG_SBCM_LEN,
-};
+MLXSW_REG_DEFINE(sbcm, MLXSW_REG_SBCM_ID, MLXSW_REG_SBCM_LEN);
 
 /* reg_sbcm_local_port
  * Local port number.
@@ -4979,10 +4819,7 @@ static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff,
 #define MLXSW_REG_SBPM_ID 0xB003
 #define MLXSW_REG_SBPM_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_sbpm = {
-       .id = MLXSW_REG_SBPM_ID,
-       .len = MLXSW_REG_SBPM_LEN,
-};
+MLXSW_REG_DEFINE(sbpm, MLXSW_REG_SBPM_ID, MLXSW_REG_SBPM_LEN);
 
 /* reg_sbpm_local_port
  * Local port number.
@@ -5073,10 +4910,7 @@ static inline void mlxsw_reg_sbpm_unpack(char *payload, u32 *p_buff_occupancy,
 #define MLXSW_REG_SBMM_ID 0xB004
 #define MLXSW_REG_SBMM_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_sbmm = {
-       .id = MLXSW_REG_SBMM_ID,
-       .len = MLXSW_REG_SBMM_LEN,
-};
+MLXSW_REG_DEFINE(sbmm, MLXSW_REG_SBMM_ID, MLXSW_REG_SBMM_LEN);
 
 /* reg_sbmm_prio
  * Switch Priority.
@@ -5135,10 +4969,7 @@ static inline void mlxsw_reg_sbmm_pack(char *payload, u8 prio, u32 min_buff,
                            MLXSW_REG_SBSR_REC_LEN *    \
                            MLXSW_REG_SBSR_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_sbsr = {
-       .id = MLXSW_REG_SBSR_ID,
-       .len = MLXSW_REG_SBSR_LEN,
-};
+MLXSW_REG_DEFINE(sbsr, MLXSW_REG_SBSR_ID, MLXSW_REG_SBSR_LEN);
 
 /* reg_sbsr_clr
  * Clear Max Buffer Occupancy. When this bit is set, the max_buff_occupancy
@@ -5228,10 +5059,7 @@ static inline void mlxsw_reg_sbsr_rec_unpack(char *payload, int rec_index,
 #define MLXSW_REG_SBIB_ID 0xB006
 #define MLXSW_REG_SBIB_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_sbib = {
-       .id = MLXSW_REG_SBIB_ID,
-       .len = MLXSW_REG_SBIB_LEN,
-};
+MLXSW_REG_DEFINE(sbib, MLXSW_REG_SBIB_ID, MLXSW_REG_SBIB_LEN);
 
 /* reg_sbib_local_port
  * Local port number
@@ -5256,132 +5084,80 @@ static inline void mlxsw_reg_sbib_pack(char *payload, u8 local_port,
        mlxsw_reg_sbib_buff_size_set(payload, buff_size);
 }
 
+static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
+       MLXSW_REG(sgcr),
+       MLXSW_REG(spad),
+       MLXSW_REG(smid),
+       MLXSW_REG(sspr),
+       MLXSW_REG(sfdat),
+       MLXSW_REG(sfd),
+       MLXSW_REG(sfn),
+       MLXSW_REG(spms),
+       MLXSW_REG(spvid),
+       MLXSW_REG(spvm),
+       MLXSW_REG(spaft),
+       MLXSW_REG(sfgc),
+       MLXSW_REG(sftr),
+       MLXSW_REG(sfdf),
+       MLXSW_REG(sldr),
+       MLXSW_REG(slcr),
+       MLXSW_REG(slcor),
+       MLXSW_REG(spmlr),
+       MLXSW_REG(svfa),
+       MLXSW_REG(svpe),
+       MLXSW_REG(sfmr),
+       MLXSW_REG(spvmlr),
+       MLXSW_REG(qtct),
+       MLXSW_REG(qeec),
+       MLXSW_REG(pmlp),
+       MLXSW_REG(pmtu),
+       MLXSW_REG(ptys),
+       MLXSW_REG(ppad),
+       MLXSW_REG(paos),
+       MLXSW_REG(pfcc),
+       MLXSW_REG(ppcnt),
+       MLXSW_REG(pptb),
+       MLXSW_REG(pbmc),
+       MLXSW_REG(pspa),
+       MLXSW_REG(htgt),
+       MLXSW_REG(hpkt),
+       MLXSW_REG(rgcr),
+       MLXSW_REG(ritr),
+       MLXSW_REG(ratr),
+       MLXSW_REG(ralta),
+       MLXSW_REG(ralst),
+       MLXSW_REG(raltb),
+       MLXSW_REG(ralue),
+       MLXSW_REG(rauht),
+       MLXSW_REG(raleu),
+       MLXSW_REG(rauhtd),
+       MLXSW_REG(mfcr),
+       MLXSW_REG(mfsc),
+       MLXSW_REG(mfsm),
+       MLXSW_REG(mtcap),
+       MLXSW_REG(mtmp),
+       MLXSW_REG(mpat),
+       MLXSW_REG(mpar),
+       MLXSW_REG(mlcr),
+       MLXSW_REG(sbpr),
+       MLXSW_REG(sbcm),
+       MLXSW_REG(sbpm),
+       MLXSW_REG(sbmm),
+       MLXSW_REG(sbsr),
+       MLXSW_REG(sbib),
+};
+
 static inline const char *mlxsw_reg_id_str(u16 reg_id)
 {
-       switch (reg_id) {
-       case MLXSW_REG_SGCR_ID:
-               return "SGCR";
-       case MLXSW_REG_SPAD_ID:
-               return "SPAD";
-       case MLXSW_REG_SMID_ID:
-               return "SMID";
-       case MLXSW_REG_SSPR_ID:
-               return "SSPR";
-       case MLXSW_REG_SFDAT_ID:
-               return "SFDAT";
-       case MLXSW_REG_SFD_ID:
-               return "SFD";
-       case MLXSW_REG_SFN_ID:
-               return "SFN";
-       case MLXSW_REG_SPMS_ID:
-               return "SPMS";
-       case MLXSW_REG_SPVID_ID:
-               return "SPVID";
-       case MLXSW_REG_SPVM_ID:
-               return "SPVM";
-       case MLXSW_REG_SPAFT_ID:
-               return "SPAFT";
-       case MLXSW_REG_SFGC_ID:
-               return "SFGC";
-       case MLXSW_REG_SFTR_ID:
-               return "SFTR";
-       case MLXSW_REG_SFDF_ID:
-               return "SFDF";
-       case MLXSW_REG_SLDR_ID:
-               return "SLDR";
-       case MLXSW_REG_SLCR_ID:
-               return "SLCR";
-       case MLXSW_REG_SLCOR_ID:
-               return "SLCOR";
-       case MLXSW_REG_SPMLR_ID:
-               return "SPMLR";
-       case MLXSW_REG_SVFA_ID:
-               return "SVFA";
-       case MLXSW_REG_SVPE_ID:
-               return "SVPE";
-       case MLXSW_REG_SFMR_ID:
-               return "SFMR";
-       case MLXSW_REG_SPVMLR_ID:
-               return "SPVMLR";
-       case MLXSW_REG_QTCT_ID:
-               return "QTCT";
-       case MLXSW_REG_QEEC_ID:
-               return "QEEC";
-       case MLXSW_REG_PMLP_ID:
-               return "PMLP";
-       case MLXSW_REG_PMTU_ID:
-               return "PMTU";
-       case MLXSW_REG_PTYS_ID:
-               return "PTYS";
-       case MLXSW_REG_PPAD_ID:
-               return "PPAD";
-       case MLXSW_REG_PAOS_ID:
-               return "PAOS";
-       case MLXSW_REG_PFCC_ID:
-               return "PFCC";
-       case MLXSW_REG_PPCNT_ID:
-               return "PPCNT";
-       case MLXSW_REG_PPTB_ID:
-               return "PPTB";
-       case MLXSW_REG_PBMC_ID:
-               return "PBMC";
-       case MLXSW_REG_PSPA_ID:
-               return "PSPA";
-       case MLXSW_REG_HTGT_ID:
-               return "HTGT";
-       case MLXSW_REG_HPKT_ID:
-               return "HPKT";
-       case MLXSW_REG_RGCR_ID:
-               return "RGCR";
-       case MLXSW_REG_RITR_ID:
-               return "RITR";
-       case MLXSW_REG_RATR_ID:
-               return "RATR";
-       case MLXSW_REG_RALTA_ID:
-               return "RALTA";
-       case MLXSW_REG_RALST_ID:
-               return "RALST";
-       case MLXSW_REG_RALTB_ID:
-               return "RALTB";
-       case MLXSW_REG_RALUE_ID:
-               return "RALUE";
-       case MLXSW_REG_RAUHT_ID:
-               return "RAUHT";
-       case MLXSW_REG_RALEU_ID:
-               return "RALEU";
-       case MLXSW_REG_RAUHTD_ID:
-               return "RAUHTD";
-       case MLXSW_REG_MFCR_ID:
-               return "MFCR";
-       case MLXSW_REG_MFSC_ID:
-               return "MFSC";
-       case MLXSW_REG_MFSM_ID:
-               return "MFSM";
-       case MLXSW_REG_MTCAP_ID:
-               return "MTCAP";
-       case MLXSW_REG_MPAT_ID:
-               return "MPAT";
-       case MLXSW_REG_MPAR_ID:
-               return "MPAR";
-       case MLXSW_REG_MTMP_ID:
-               return "MTMP";
-       case MLXSW_REG_MLCR_ID:
-               return "MLCR";
-       case MLXSW_REG_SBPR_ID:
-               return "SBPR";
-       case MLXSW_REG_SBCM_ID:
-               return "SBCM";
-       case MLXSW_REG_SBPM_ID:
-               return "SBPM";
-       case MLXSW_REG_SBMM_ID:
-               return "SBMM";
-       case MLXSW_REG_SBSR_ID:
-               return "SBSR";
-       case MLXSW_REG_SBIB_ID:
-               return "SBIB";
-       default:
-               return "*UNKNOWN*";
+       const struct mlxsw_reg_info *reg_info;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mlxsw_reg_infos); i++) {
+               reg_info = mlxsw_reg_infos[i];
+               if (reg_info->id == reg_id)
+                       return reg_info->name;
        }
+       return "*UNKNOWN*";
 }
 
 /* PUDE - Port Up / Down Event
diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h
new file mode 100644 (file)
index 0000000..a031e45
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/resources.h
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MLXSW_RESOURCES_H
+#define _MLXSW_RESOURCES_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+enum mlxsw_res_id {
+       MLXSW_RES_ID_KVD_SIZE,
+       MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE,
+       MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE,
+       MLXSW_RES_ID_MAX_SPAN,
+       MLXSW_RES_ID_MAX_SYSTEM_PORT,
+       MLXSW_RES_ID_MAX_LAG,
+       MLXSW_RES_ID_MAX_LAG_MEMBERS,
+       MLXSW_RES_ID_MAX_VRS,
+       MLXSW_RES_ID_MAX_RIFS,
+
+       /* Internal resources.
+        * Determined by the SW, not queried from the HW.
+        */
+       MLXSW_RES_ID_KVD_SINGLE_SIZE,
+       MLXSW_RES_ID_KVD_DOUBLE_SIZE,
+       MLXSW_RES_ID_KVD_LINEAR_SIZE,
+
+       __MLXSW_RES_ID_MAX,
+};
+
+static u16 mlxsw_res_ids[] = {
+       [MLXSW_RES_ID_KVD_SIZE] = 0x1001,
+       [MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE] = 0x1002,
+       [MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE] = 0x1003,
+       [MLXSW_RES_ID_MAX_SPAN] = 0x2420,
+       [MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502,
+       [MLXSW_RES_ID_MAX_LAG] = 0x2520,
+       [MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521,
+       [MLXSW_RES_ID_MAX_VRS] = 0x2C01,
+       [MLXSW_RES_ID_MAX_RIFS] = 0x2C02,
+};
+
+struct mlxsw_res {
+       bool valid[__MLXSW_RES_ID_MAX];
+       u64 values[__MLXSW_RES_ID_MAX];
+};
+
+static inline bool mlxsw_res_valid(struct mlxsw_res *res,
+                                  enum mlxsw_res_id res_id)
+{
+       return res->valid[res_id];
+}
+
+#define MLXSW_RES_VALID(res, short_res_id)                     \
+       mlxsw_res_valid(res, MLXSW_RES_ID_##short_res_id)
+
+static inline u64 mlxsw_res_get(struct mlxsw_res *res,
+                               enum mlxsw_res_id res_id)
+{
+       if (WARN_ON(!res->valid[res_id]))
+               return 0;
+       return res->values[res_id];
+}
+
+#define MLXSW_RES_GET(res, short_res_id)                       \
+       mlxsw_res_get(res, MLXSW_RES_ID_##short_res_id)
+
+static inline void mlxsw_res_set(struct mlxsw_res *res,
+                                enum mlxsw_res_id res_id, u64 value)
+{
+       res->valid[res_id] = true;
+       res->values[res_id] = value;
+}
+
+#define MLXSW_RES_SET(res, short_res_id, value)                        \
+       mlxsw_res_set(res, MLXSW_RES_ID_##short_res_id, value)
+
+static inline void mlxsw_res_parse(struct mlxsw_res *res, u16 id, u64 value)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mlxsw_res_ids); i++) {
+               if (mlxsw_res_ids[i] == id) {
+                       mlxsw_res_set(res, i, value);
+                       return;
+               }
+       }
+}
+
+#endif
index 1ec0a4ce3c46edddc4fc0d63e67706d6459e10f3..d652f7f030cbc56cd857bc72438a8de973f714e8 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -59,6 +60,7 @@
 #include <net/netevent.h>
 
 #include "spectrum.h"
+#include "pci.h"
 #include "core.h"
 #include "reg.h"
 #include "port.h"
@@ -168,14 +170,13 @@ static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp)
 
 static int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
 {
-       struct mlxsw_resources *resources;
        int i;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       if (!resources->max_span_valid)
+       if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN))
                return -EIO;
 
-       mlxsw_sp->span.entries_count = resources->max_span;
+       mlxsw_sp->span.entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+                                                         MAX_SPAN);
        mlxsw_sp->span.entries = kcalloc(mlxsw_sp->span.entries_count,
                                         sizeof(struct mlxsw_sp_span_entry),
                                         GFP_KERNEL);
@@ -1237,8 +1238,10 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
 
        tcf_exts_to_list(cls->exts, &actions);
        list_for_each_entry(a, &actions, list) {
-               if (!is_tcf_mirred_mirror(a) || protocol != htons(ETH_P_ALL))
+               if (!is_tcf_mirred_egress_mirror(a) ||
+                   protocol != htons(ETH_P_ALL)) {
                        return -ENOTSUPP;
+               }
 
                err = mlxsw_sp_port_add_cls_matchall_mirror(mlxsw_sp_port, cls,
                                                            a, ingress);
@@ -1411,7 +1414,7 @@ err_port_pause_configure:
 
 struct mlxsw_sp_port_hw_stats {
        char str[ETH_GSTRING_LEN];
-       u64 (*getter)(char *payload);
+       u64 (*getter)(const char *payload);
 };
 
 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = {
@@ -1532,7 +1535,7 @@ static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_prio_stats[] = {
 
 #define MLXSW_SP_PORT_HW_PRIO_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_prio_stats)
 
-static u64 mlxsw_reg_ppcnt_tc_transmit_queue_bytes_get(char *ppcnt_pl)
+static u64 mlxsw_reg_ppcnt_tc_transmit_queue_bytes_get(const char *ppcnt_pl)
 {
        u64 transmit_queue = mlxsw_reg_ppcnt_tc_transmit_queue_get(ppcnt_pl);
 
@@ -2219,6 +2222,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
        dev = alloc_etherdev(sizeof(struct mlxsw_sp_port));
        if (!dev)
                return -ENOMEM;
+       SET_NETDEV_DEV(dev, mlxsw_sp->bus_info->dev);
        mlxsw_sp_port = netdev_priv(dev);
        mlxsw_sp_port->dev = dev;
        mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
@@ -2282,6 +2286,9 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                         NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_TC;
        dev->hw_features |= NETIF_F_HW_TC;
 
+       dev->min_mtu = 0;
+       dev->max_mtu = ETH_MAX_MTU;
+
        /* Each packet needs to have a Tx header (metadata) on top all other
         * headers.
         */
@@ -2887,7 +2894,6 @@ static int mlxsw_sp_flood_init(struct mlxsw_sp *mlxsw_sp)
 
 static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
 {
-       struct mlxsw_resources *resources;
        char slcr_pl[MLXSW_REG_SLCR_LEN];
        int err;
 
@@ -2904,11 +2910,11 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
        if (err)
                return err;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       if (!(resources->max_lag_valid && resources->max_ports_in_lag_valid))
+       if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG) ||
+           !MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS))
                return -EIO;
 
-       mlxsw_sp->lags = kcalloc(resources->max_lag,
+       mlxsw_sp->lags = kcalloc(MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG),
                                 sizeof(struct mlxsw_sp_upper),
                                 GFP_KERNEL);
        if (!mlxsw_sp->lags)
@@ -3063,8 +3069,7 @@ static struct mlxsw_config_profile mlxsw_sp_config_profile = {
 };
 
 static struct mlxsw_driver mlxsw_sp_driver = {
-       .kind                           = MLXSW_DEVICE_KIND_SPECTRUM,
-       .owner                          = THIS_MODULE,
+       .kind                           = mlxsw_sp_driver_name,
        .priv_size                      = sizeof(struct mlxsw_sp),
        .init                           = mlxsw_sp_init,
        .fini                           = mlxsw_sp_fini,
@@ -3090,19 +3095,30 @@ static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
        return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
 }
 
+static int mlxsw_lower_dev_walk(struct net_device *lower_dev, void *data)
+{
+       struct mlxsw_sp_port **port = data;
+       int ret = 0;
+
+       if (mlxsw_sp_port_dev_check(lower_dev)) {
+               *port = netdev_priv(lower_dev);
+               ret = 1;
+       }
+
+       return ret;
+}
+
 static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev)
 {
-       struct net_device *lower_dev;
-       struct list_head *iter;
+       struct mlxsw_sp_port *port;
 
        if (mlxsw_sp_port_dev_check(dev))
                return netdev_priv(dev);
 
-       netdev_for_each_all_lower_dev(dev, lower_dev, iter) {
-               if (mlxsw_sp_port_dev_check(lower_dev))
-                       return netdev_priv(lower_dev);
-       }
-       return NULL;
+       port = NULL;
+       netdev_walk_all_lower_dev(dev, mlxsw_lower_dev_walk, &port);
+
+       return port;
 }
 
 static struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
@@ -3115,17 +3131,15 @@ static struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
 
 static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
 {
-       struct net_device *lower_dev;
-       struct list_head *iter;
+       struct mlxsw_sp_port *port;
 
        if (mlxsw_sp_port_dev_check(dev))
                return netdev_priv(dev);
 
-       netdev_for_each_all_lower_dev_rcu(dev, lower_dev, iter) {
-               if (mlxsw_sp_port_dev_check(lower_dev))
-                       return netdev_priv(lower_dev);
-       }
-       return NULL;
+       port = NULL;
+       netdev_walk_all_lower_dev_rcu(dev, mlxsw_lower_dev_walk, &port);
+
+       return port;
 }
 
 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev)
@@ -3169,11 +3183,9 @@ static bool mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *r,
 
 static int mlxsw_sp_avail_rif_get(struct mlxsw_sp *mlxsw_sp)
 {
-       struct mlxsw_resources *resources;
        int i;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       for (i = 0; i < resources->max_rif; i++)
+       for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
                if (!mlxsw_sp->rifs[i])
                        return i;
 
@@ -3696,14 +3708,15 @@ static bool mlxsw_sp_port_fdb_should_flush(struct mlxsw_sp_port *mlxsw_sp_port,
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        u8 local_port = mlxsw_sp_port->local_port;
        u16 lag_id = mlxsw_sp_port->lag_id;
-       struct mlxsw_resources *resources;
+       u64 max_lag_members;
        int i, count = 0;
 
        if (!mlxsw_sp_port->lagged)
                return true;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       for (i = 0; i < resources->max_ports_in_lag; i++) {
+       max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+                                            MAX_LAG_MEMBERS);
+       for (i = 0; i < max_lag_members; i++) {
                struct mlxsw_sp_port *lag_port;
 
                lag_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i);
@@ -3909,13 +3922,13 @@ static int mlxsw_sp_lag_index_get(struct mlxsw_sp *mlxsw_sp,
                                  struct net_device *lag_dev,
                                  u16 *p_lag_id)
 {
-       struct mlxsw_resources *resources;
        struct mlxsw_sp_upper *lag;
        int free_lag_id = -1;
+       u64 max_lag;
        int i;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       for (i = 0; i < resources->max_lag; i++) {
+       max_lag = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG);
+       for (i = 0; i < max_lag; i++) {
                lag = mlxsw_sp_lag_get(mlxsw_sp, i);
                if (lag->ref_count) {
                        if (lag->dev == lag_dev) {
@@ -3949,11 +3962,12 @@ mlxsw_sp_master_lag_check(struct mlxsw_sp *mlxsw_sp,
 static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp,
                                       u16 lag_id, u8 *p_port_index)
 {
-       struct mlxsw_resources *resources;
+       u64 max_lag_members;
        int i;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       for (i = 0; i < resources->max_ports_in_lag; i++) {
+       max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+                                            MAX_LAG_MEMBERS);
+       for (i = 0; i < max_lag_members; i++) {
                if (!mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i)) {
                        *p_port_index = i;
                        return 0;
@@ -4650,6 +4664,16 @@ static struct notifier_block mlxsw_sp_router_netevent_nb __read_mostly = {
        .notifier_call = mlxsw_sp_router_netevent_event,
 };
 
+static const struct pci_device_id mlxsw_sp_pci_id_table[] = {
+       {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
+       {0, },
+};
+
+static struct pci_driver mlxsw_sp_pci_driver = {
+       .name = mlxsw_sp_driver_name,
+       .id_table = mlxsw_sp_pci_id_table,
+};
+
 static int __init mlxsw_sp_module_init(void)
 {
        int err;
@@ -4661,8 +4685,15 @@ static int __init mlxsw_sp_module_init(void)
        err = mlxsw_core_driver_register(&mlxsw_sp_driver);
        if (err)
                goto err_core_driver_register;
+
+       err = mlxsw_pci_driver_register(&mlxsw_sp_pci_driver);
+       if (err)
+               goto err_pci_driver_register;
+
        return 0;
 
+err_pci_driver_register:
+       mlxsw_core_driver_unregister(&mlxsw_sp_driver);
 err_core_driver_register:
        unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
        unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
@@ -4672,6 +4703,7 @@ err_core_driver_register:
 
 static void __exit mlxsw_sp_module_exit(void)
 {
+       mlxsw_pci_driver_unregister(&mlxsw_sp_pci_driver);
        mlxsw_core_driver_unregister(&mlxsw_sp_driver);
        unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
        unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
@@ -4684,4 +4716,4 @@ module_exit(mlxsw_sp_module_exit);
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox Spectrum driver");
-MODULE_MLXSW_DRIVER_ALIAS(MLXSW_DEVICE_KIND_SPECTRUM);
+MODULE_DEVICE_TABLE(pci, mlxsw_sp_pci_id_table);
index 9b22863a924b53d44b59ea5f07b61a500fc889cf..cc5462556a83260a6ff6d062f90a8f19f59a575e 100644 (file)
@@ -479,12 +479,9 @@ static inline struct mlxsw_sp_rif *
 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
                         const struct net_device *dev)
 {
-       struct mlxsw_resources *resources;
        int i;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-
-       for (i = 0; i < resources->max_rif; i++)
+       for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
                if (mlxsw_sp->rifs[i] && mlxsw_sp->rifs[i]->dev == dev)
                        return mlxsw_sp->rifs[i];
 
index 4573da2c55602b8b412fdf6a90296b306d5291de..348c77339d88626b437a98e6a86f7ec3ed6b4aed 100644 (file)
@@ -382,12 +382,10 @@ static void mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
 
 static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
 {
-       struct mlxsw_resources *resources;
        struct mlxsw_sp_vr *vr;
        int i;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       for (i = 0; i < resources->max_virtual_routers; i++) {
+       for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
                vr = &mlxsw_sp->router.vrs[i];
                if (!vr->used)
                        return vr;
@@ -429,14 +427,12 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp,
                                            u32 tb_id,
                                            enum mlxsw_sp_l3proto proto)
 {
-       struct mlxsw_resources *resources;
        struct mlxsw_sp_vr *vr;
        int i;
 
        tb_id = mlxsw_sp_fix_tb_id(tb_id);
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       for (i = 0; i < resources->max_virtual_routers; i++) {
+       for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
                vr = &mlxsw_sp->router.vrs[i];
                if (vr->used && vr->proto == proto && vr->tb_id == tb_id)
                        return vr;
@@ -572,21 +568,20 @@ static void mlxsw_sp_vr_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr)
 
 static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp)
 {
-       struct mlxsw_resources *resources;
        struct mlxsw_sp_vr *vr;
+       u64 max_vrs;
        int i;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       if (!resources->max_virtual_routers_valid)
+       if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS))
                return -EIO;
 
-       mlxsw_sp->router.vrs = kcalloc(resources->max_virtual_routers,
-                                      sizeof(struct mlxsw_sp_vr),
+       max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
+       mlxsw_sp->router.vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr),
                                       GFP_KERNEL);
        if (!mlxsw_sp->router.vrs)
                return -ENOMEM;
 
-       for (i = 0; i < resources->max_virtual_routers; i++) {
+       for (i = 0; i < max_vrs; i++) {
                vr = &mlxsw_sp->router.vrs[i];
                vr->id = i;
        }
@@ -1876,15 +1871,13 @@ static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
 
 static void mlxsw_sp_router_fib4_abort(struct mlxsw_sp *mlxsw_sp)
 {
-       struct mlxsw_resources *resources;
        struct mlxsw_sp_fib_entry *fib_entry;
        struct mlxsw_sp_fib_entry *tmp;
        struct mlxsw_sp_vr *vr;
        int i;
        int err;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       for (i = 0; i < resources->max_virtual_routers; i++) {
+       for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
                vr = &mlxsw_sp->router.vrs[i];
                if (!vr->used)
                        continue;
@@ -1909,21 +1902,21 @@ static void mlxsw_sp_router_fib4_abort(struct mlxsw_sp *mlxsw_sp)
 
 static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
 {
-       struct mlxsw_resources *resources;
        char rgcr_pl[MLXSW_REG_RGCR_LEN];
+       u64 max_rifs;
        int err;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       if (!resources->max_rif_valid)
+       if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
                return -EIO;
 
-       mlxsw_sp->rifs = kcalloc(resources->max_rif,
-                                sizeof(struct mlxsw_sp_rif *), GFP_KERNEL);
+       max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
+       mlxsw_sp->rifs = kcalloc(max_rifs, sizeof(struct mlxsw_sp_rif *),
+                                GFP_KERNEL);
        if (!mlxsw_sp->rifs)
                return -ENOMEM;
 
        mlxsw_reg_rgcr_pack(rgcr_pl, true);
-       mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, resources->max_rif);
+       mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
        if (err)
                goto err_rgcr_fail;
@@ -1937,15 +1930,13 @@ err_rgcr_fail:
 
 static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
 {
-       struct mlxsw_resources *resources;
        char rgcr_pl[MLXSW_REG_RGCR_LEN];
        int i;
 
        mlxsw_reg_rgcr_pack(rgcr_pl, false);
        mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       for (i = 0; i < resources->max_rif; i++)
+       for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
                WARN_ON_ONCE(mlxsw_sp->rifs[i]);
 
        kfree(mlxsw_sp->rifs);
@@ -1990,7 +1981,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
        if (err)
                goto err_vrs_init;
 
-       err =  mlxsw_sp_neigh_init(mlxsw_sp);
+       err = mlxsw_sp_neigh_init(mlxsw_sp);
        if (err)
                goto err_neigh_init;
 
index 5e00c79e8133b016684972d0d269c904ec2e2c54..b19552a7277882f92466c3f02fb1b875f59f7a1e 100644 (file)
@@ -1196,11 +1196,12 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
                                                   u16 lag_id)
 {
        struct mlxsw_sp_port *mlxsw_sp_port;
-       struct mlxsw_resources *resources;
+       u64 max_lag_members;
        int i;
 
-       resources = mlxsw_core_resources_get(mlxsw_sp->core);
-       for (i = 0; i < resources->max_ports_in_lag; i++) {
+       max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+                                            MAX_LAG_MEMBERS);
+       for (i = 0; i < max_lag_members; i++) {
                mlxsw_sp_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i);
                if (mlxsw_sp_port)
                        return mlxsw_sp_port;
index 92bda8703f8752756c472aac916a19c8e5f38a65..8c8f5d8a211352c939b74682887c71777954ecd1 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/slab.h>
@@ -46,6 +47,7 @@
 #include <net/switchdev.h>
 #include <generated/utsrelease.h>
 
+#include "pci.h"
 #include "core.h"
 #include "reg.h"
 #include "port.h"
@@ -410,7 +412,7 @@ static void mlxsw_sx_port_get_drvinfo(struct net_device *dev,
 
 struct mlxsw_sx_port_hw_stats {
        char str[ETH_GSTRING_LEN];
-       u64 (*getter)(char *payload);
+       u64 (*getter)(const char *payload);
 };
 
 static const struct mlxsw_sx_port_hw_stats mlxsw_sx_port_hw_stats[] = {
@@ -966,6 +968,7 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
        dev = alloc_etherdev(sizeof(struct mlxsw_sx_port));
        if (!dev)
                return -ENOMEM;
+       SET_NETDEV_DEV(dev, mlxsw_sx->bus_info->dev);
        mlxsw_sx_port = netdev_priv(dev);
        mlxsw_sx_port->dev = dev;
        mlxsw_sx_port->mlxsw_sx = mlxsw_sx;
@@ -994,6 +997,9 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
        dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG |
                         NETIF_F_VLAN_CHALLENGED;
 
+       dev->min_mtu = 0;
+       dev->max_mtu = ETH_MAX_MTU;
+
        /* Each packet needs to have a Tx header (metadata) on top all other
         * headers.
         */
@@ -1542,8 +1548,7 @@ static struct mlxsw_config_profile mlxsw_sx_config_profile = {
 };
 
 static struct mlxsw_driver mlxsw_sx_driver = {
-       .kind                   = MLXSW_DEVICE_KIND_SWITCHX2,
-       .owner                  = THIS_MODULE,
+       .kind                   = mlxsw_sx_driver_name,
        .priv_size              = sizeof(struct mlxsw_sx),
        .init                   = mlxsw_sx_init,
        .fini                   = mlxsw_sx_fini,
@@ -1552,13 +1557,38 @@ static struct mlxsw_driver mlxsw_sx_driver = {
        .profile                = &mlxsw_sx_config_profile,
 };
 
+static const struct pci_device_id mlxsw_sx_pci_id_table[] = {
+       {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0},
+       {0, },
+};
+
+static struct pci_driver mlxsw_sx_pci_driver = {
+       .name = mlxsw_sx_driver_name,
+       .id_table = mlxsw_sx_pci_id_table,
+};
+
 static int __init mlxsw_sx_module_init(void)
 {
-       return mlxsw_core_driver_register(&mlxsw_sx_driver);
+       int err;
+
+       err = mlxsw_core_driver_register(&mlxsw_sx_driver);
+       if (err)
+               return err;
+
+       err = mlxsw_pci_driver_register(&mlxsw_sx_pci_driver);
+       if (err)
+               goto err_pci_driver_register;
+
+       return 0;
+
+err_pci_driver_register:
+       mlxsw_core_driver_unregister(&mlxsw_sx_driver);
+       return err;
 }
 
 static void __exit mlxsw_sx_module_exit(void)
 {
+       mlxsw_pci_driver_unregister(&mlxsw_sx_pci_driver);
        mlxsw_core_driver_unregister(&mlxsw_sx_driver);
 }
 
@@ -1568,4 +1598,4 @@ module_exit(mlxsw_sx_module_exit);
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox SwitchX-2 driver");
-MODULE_MLXSW_DRIVER_ALIAS(MLXSW_DEVICE_KIND_SWITCHX2);
+MODULE_DEVICE_TABLE(pci, mlxsw_sx_pci_id_table);
index 1edc973df4c41d893608c08dae1ebbb7e7c07ac3..e7e1aff40bd9f2fe676b03ab524de5eaa2a815de 100644 (file)
@@ -1063,7 +1063,6 @@ static const struct net_device_ops ks8851_netdev_ops = {
        .ndo_start_xmit         = ks8851_start_xmit,
        .ndo_set_mac_address    = ks8851_set_mac_address,
        .ndo_set_rx_mode        = ks8851_set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 2fc5cd56c0a846d30e86ba7b6efa0bbfaedf264f..db628078a4e6f549b0d6a7a5baa97edcab9ba2b0 100644 (file)
@@ -1285,7 +1285,6 @@ static const struct net_device_ops ks_netdev_ops = {
        .ndo_start_xmit         = ks_start_xmit,
        .ndo_set_mac_address    = ks_set_mac_address,
        .ndo_set_rx_mode        = ks_set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 280e761d3a975acb042568a69b6603c1616fe36c..97f6ef1fa7d06a4b273be0e9ffc91c335dadc06a 100644 (file)
@@ -5807,24 +5807,19 @@ static int netdev_change_mtu(struct net_device *dev, int new_mtu)
        if (hw->dev_count > 1)
                if (dev != hw_priv->dev)
                        return 0;
-       if (new_mtu < 60)
-               return -EINVAL;
 
-       if (dev->mtu != new_mtu) {
-               hw_mtu = new_mtu + ETHERNET_HEADER_SIZE + 4;
-               if (hw_mtu > MAX_RX_BUF_SIZE)
-                       return -EINVAL;
-               if (hw_mtu > REGULAR_RX_BUF_SIZE) {
-                       hw->features |= RX_HUGE_FRAME;
-                       hw_mtu = MAX_RX_BUF_SIZE;
-               } else {
-                       hw->features &= ~RX_HUGE_FRAME;
-                       hw_mtu = REGULAR_RX_BUF_SIZE;
-               }
-               hw_mtu = (hw_mtu + 3) & ~3;
-               hw_priv->mtu = hw_mtu;
-               dev->mtu = new_mtu;
+       hw_mtu = new_mtu + ETHERNET_HEADER_SIZE + 4;
+       if (hw_mtu > REGULAR_RX_BUF_SIZE) {
+               hw->features |= RX_HUGE_FRAME;
+               hw_mtu = MAX_RX_BUF_SIZE;
+       } else {
+               hw->features &= ~RX_HUGE_FRAME;
+               hw_mtu = REGULAR_RX_BUF_SIZE;
        }
+       hw_mtu = (hw_mtu + 3) & ~3;
+       hw_priv->mtu = hw_mtu;
+       dev->mtu = new_mtu;
+
        return 0;
 }
 
@@ -7099,6 +7094,12 @@ static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id)
 
                dev->netdev_ops = &netdev_ops;
                dev->ethtool_ops = &netdev_ethtool_ops;
+
+               /* MTU range: 60 - 1894 */
+               dev->min_mtu = ETH_ZLEN;
+               dev->max_mtu = MAX_RX_BUF_SIZE -
+                              (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
                if (register_netdev(dev))
                        goto pcidev_init_reg_err;
                port_set_power_saving(port, true);
index 0a26b11ca8f61eff9f7c5b880b770a99948f07bf..045b9106c0ff50ba46acde30c22f46dab36e4fd8 100644 (file)
@@ -1544,7 +1544,6 @@ static const struct net_device_ops enc28j60_netdev_ops = {
        .ndo_set_rx_mode        = enc28j60_set_multicast_list,
        .ndo_set_mac_address    = enc28j60_set_mac_address,
        .ndo_tx_timeout         = enc28j60_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 4367dd6879a22791a1bef1726ba8d770b03cebca..9774b50cff6e6b3e9a71b06198bbddbe5aa503e5 100644 (file)
@@ -444,7 +444,6 @@ static struct net_device_ops moxart_netdev_ops = {
        .ndo_set_rx_mode        = moxart_mac_set_rx_mode,
        .ndo_set_mac_address    = moxart_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int moxart_mac_probe(struct platform_device *pdev)
index 6d1a956e3f779d57e83a8fd40a5136919231df2c..e506ca876d0d319aaf70abdd72792bb2a0224964 100644 (file)
@@ -289,7 +289,7 @@ static char *myri10ge_fw_names[MYRI10GE_MAX_BOARDS] =
     {[0 ... (MYRI10GE_MAX_BOARDS - 1)] = NULL };
 module_param_array_named(myri10ge_fw_names, myri10ge_fw_names, charp, NULL,
                         0444);
-MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image names per board");
+MODULE_PARM_DESC(myri10ge_fw_names, "Firmware image names per board");
 
 static int myri10ge_ecrc_enable = 1;
 module_param(myri10ge_ecrc_enable, int, S_IRUGO);
@@ -3232,10 +3232,6 @@ static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
        struct myri10ge_priv *mgp = netdev_priv(dev);
        int error = 0;
 
-       if ((new_mtu < 68) || (ETH_HLEN + new_mtu > MYRI10GE_MAX_ETHER_MTU)) {
-               netdev_err(dev, "new mtu (%d) is not valid\n", new_mtu);
-               return -EINVAL;
-       }
        netdev_info(dev, "changing mtu from %d to %d\n", dev->mtu, new_mtu);
        if (mgp->running) {
                /* if we change the mtu on an active device, we must
@@ -4086,13 +4082,19 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        myri10ge_setup_dca(mgp);
 #endif
        pci_set_drvdata(pdev, mgp);
-       if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU)
-               myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
-       if ((myri10ge_initial_mtu + ETH_HLEN) < 68)
-               myri10ge_initial_mtu = 68;
 
-       netdev->netdev_ops = &myri10ge_netdev_ops;
+       /* MTU range: 68 - 9000 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
+
+       if (myri10ge_initial_mtu > netdev->max_mtu)
+               myri10ge_initial_mtu = netdev->max_mtu;
+       if (myri10ge_initial_mtu < netdev->min_mtu)
+               myri10ge_initial_mtu = netdev->min_mtu;
+
        netdev->mtu = myri10ge_initial_mtu;
+
+       netdev->netdev_ops = &myri10ge_netdev_ops;
        netdev->hw_features = mgp->features | NETIF_F_RXCSUM;
 
        /* fake NETIF_F_HW_VLAN_CTAG_RX for good GRO performance */
index acf3f11e38cc1294555c6b7e2193865e7f455f54..a6caeb567c0d45735decbde7d7ebe8c8f8ebdedc 100644 (file)
@@ -110,7 +110,6 @@ static const struct net_device_ops sonic_netdev_ops = {
        .ndo_get_stats          = sonic_get_stats,
        .ndo_set_rx_mode        = sonic_multicast_list,
        .ndo_tx_timeout         = sonic_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 };
index d98f5b8a1c66ec39f1e0a5db6bd1d834ee09a65b..3ca6ae7caf55625d5e51d884f7c7acc7fb77726c 100644 (file)
@@ -190,7 +190,6 @@ static const struct net_device_ops macsonic_netdev_ops = {
        .ndo_tx_timeout         = sonic_tx_timeout,
        .ndo_get_stats          = sonic_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
index ed89029ff75bef44bd224d725ad8b76afc20d467..22b0821c1da02ddf0630f8a5e33d5a01af58b1a1 100644 (file)
@@ -929,6 +929,10 @@ static int natsemi_probe1(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        dev->ethtool_ops = &ethtool_ops;
 
+       /* MTU range: 64 - 2024 */
+       dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN;
+       dev->max_mtu = NATSEMI_RX_LIMIT - NATSEMI_HEADERS;
+
        if (mtu)
                dev->mtu = mtu;
 
@@ -2526,9 +2530,6 @@ static void __set_rx_mode(struct net_device *dev)
 
 static int natsemi_change_mtu(struct net_device *dev, int new_mtu)
 {
-       if (new_mtu < 64 || new_mtu > NATSEMI_RX_LIMIT-NATSEMI_HEADERS)
-               return -EINVAL;
-
        dev->mtu = new_mtu;
 
        /* synchronized against open : rtnl_lock() held by caller */
index 569ade6cf85c56e564269e4639d007fbbd2deb6f..93c4bdc0cdca5a9ebb61a4a9fb8f945039f7b604 100644 (file)
@@ -919,7 +919,7 @@ netdev_mangle_me_harder_failed:
                                ndev->stats.rx_dropped++;
                        }
                } else {
-                       kfree_skb(skb);
+                       dev_kfree_skb_irq(skb);
                }
 
                nr++;
@@ -1679,14 +1679,6 @@ static void ns83820_getmac(struct ns83820 *dev, u8 *mac)
        }
 }
 
-static int ns83820_change_mtu(struct net_device *ndev, int new_mtu)
-{
-       if (new_mtu > RX_BUF_SIZE)
-               return -EINVAL;
-       ndev->mtu = new_mtu;
-       return 0;
-}
-
 static void ns83820_set_multicast(struct net_device *ndev)
 {
        struct ns83820 *dev = PRIV(ndev);
@@ -1933,7 +1925,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_stop               = ns83820_stop,
        .ndo_start_xmit         = ns83820_hard_start_xmit,
        .ndo_get_stats          = ns83820_get_stats,
-       .ndo_change_mtu         = ns83820_change_mtu,
        .ndo_set_rx_mode        = ns83820_set_multicast,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
@@ -2190,6 +2181,8 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
        ndev->features |= NETIF_F_SG;
        ndev->features |= NETIF_F_IP_CSUM;
 
+       ndev->min_mtu = 0;
+
 #ifdef NS83820_VLAN_ACCEL_SUPPORT
        /* We also support hardware vlan acceleration */
        ndev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
index 7007d212f3e4ef6c574fb4d39b59f349d85bc3e7..9ee0f69a83c05cd6876013305350758bf1368f7e 100644 (file)
@@ -124,7 +124,6 @@ static const struct net_device_ops xtsonic_netdev_ops = {
        .ndo_set_rx_mode        = sonic_multicast_list,
        .ndo_tx_timeout         = sonic_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
index eaa37c079a7cd740058b366c4c5e7855447bdc58..564f682fa4dc326dba8f5bc142a62c881479ed12 100644 (file)
@@ -6678,11 +6678,6 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
        struct s2io_nic *sp = netdev_priv(dev);
        int ret = 0;
 
-       if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
-               DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n", dev->name);
-               return -EPERM;
-       }
-
        dev->mtu = new_mtu;
        if (netif_running(dev)) {
                s2io_stop_all_tx_queue(sp);
@@ -8019,6 +8014,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                config->mc_start_offset = S2IO_HERC_MC_ADDR_START_OFFSET;
        }
 
+       /* MTU range: 46 - 9600 */
+       dev->min_mtu = MIN_MTU;
+       dev->max_mtu = S2IO_JUMBO_SIZE;
+
        /* store mac addresses from CAM to s2io_nic structure */
        do_s2io_store_unicast_mc(sp);
 
index 6ce4412fcc1ad90b676965effafa7af65d012648..cfa970417f818036bc83d6ed22deeb47cea28e90 100644 (file)
@@ -27,7 +27,7 @@
        (((size) - (((u64)adrs) & ((size)-1))) & ((size)-1))
 #endif
 
-#define VXGE_HW_MIN_MTU                                68
+#define VXGE_HW_MIN_MTU                                ETH_MIN_MTU
 #define VXGE_HW_MAX_MTU                                9600
 #define VXGE_HW_DEFAULT_MTU                    1500
 
index e0993eba5df3f8081bff6329a97b4753e876cbe3..e07b936f64ecc85babfe4eeadaf4b666dcd8d335 100644 (file)
@@ -3074,11 +3074,6 @@ static int vxge_change_mtu(struct net_device *dev, int new_mtu)
 
        vxge_debug_entryexit(vdev->level_trace,
                "%s:%d", __func__, __LINE__);
-       if ((new_mtu < VXGE_HW_MIN_MTU) || (new_mtu > VXGE_HW_MAX_MTU)) {
-               vxge_debug_init(vdev->level_err,
-                       "%s: mtu size is invalid", dev->name);
-               return -EPERM;
-       }
 
        /* check if device is down already */
        if (unlikely(!is_vxge_card_up(vdev))) {
@@ -3462,6 +3457,10 @@ static int vxge_device_register(struct __vxge_hw_device *hldev,
                        "%s : using High DMA", __func__);
        }
 
+       /* MTU range: 68 - 9600 */
+       ndev->min_mtu = VXGE_HW_MIN_MTU;
+       ndev->max_mtu = VXGE_HW_MAX_MTU;
+
        ret = register_netdev(ndev);
        if (ret) {
                vxge_debug_init(vxge_hw_device_trace_level_get(hldev),
index aee3fd2b6538d809a6acf50cf16ac066347db438..d365760fa75b7e9f299b66c0e9d6ecdf14640ab2 100644 (file)
@@ -2278,11 +2278,6 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu)
        struct nfp_net_rx_ring *tmp_rings;
        int err;
 
-       if (new_mtu < 68 || new_mtu > nn->max_mtu) {
-               nn_err(nn, "New MTU (%d) is not valid\n", new_mtu);
-               return -EINVAL;
-       }
-
        old_mtu = netdev->mtu;
        old_fl_bufsz = nn->fl_bufsz;
        new_fl_bufsz = NFP_NET_MAX_PREPEND + ETH_HLEN + VLAN_HLEN * 2 + new_mtu;
@@ -2930,6 +2925,11 @@ int nfp_net_netdev_init(struct net_device *netdev)
        ether_setup(netdev);
        netdev->netdev_ops = &nfp_net_netdev_ops;
        netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000);
+
+       /* MTU range: 68 - hw-specific max */
+       netdev->min_mtu = ETH_MIN_MTU;
+       netdev->max_mtu = nn->max_mtu;
+
        netif_carrier_off(netdev);
 
        nfp_net_set_ethtool_ops(netdev);
index 8acfb631a0eae4595ce9c17cfa1fa7d46286f221..cfed40c0e310aaacb524202141a808db944caa48 100644 (file)
@@ -128,7 +128,7 @@ nfp_net_bpf_get_act(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
                if (is_tcf_gact_shot(a))
                        return NN_ACT_TC_DROP;
 
-               if (is_tcf_mirred_redirect(a) &&
+               if (is_tcf_mirred_egress_redirect(a) &&
                    tcf_mirred_ifindex(a) == nn->netdev->ifindex)
                        return NN_ACT_TC_REDIR;
        }
index adbc47f2d132d4f7c70b10329253cc5b13c7ab94..df4188cb43e0bb86722216d7f5c08c652642ef15 100644 (file)
@@ -304,7 +304,6 @@ static const struct net_device_ops netx_eth_netdev_ops = {
        .ndo_start_xmit         = netx_eth_hard_start_xmit,
        .ndo_tx_timeout         = netx_eth_timeout,
        .ndo_set_rx_mode        = netx_eth_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 };
index 712d8bcb7d8cac7b1e4ae24284c098b1c11e1188..119f6dca71f051883a01f4ebb6d151c0b784df62 100644 (file)
@@ -915,7 +915,6 @@ static const struct net_device_ops w90p910_ether_netdev_ops = {
        .ndo_set_mac_address    = w90p910_set_mac_address,
        .ndo_do_ioctl           = w90p910_ether_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static void __init get_mac_address(struct net_device *dev)
index 9b0d7f463ff3a052713d648a2b3eba0a8078a2be..3913f07279d2baef43db0a89cc4c594bcab26dcd 100644 (file)
@@ -3008,17 +3008,12 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
        struct fe_priv *np = netdev_priv(dev);
        int old_mtu;
 
-       if (new_mtu < 64 || new_mtu > np->pkt_limit)
-               return -EINVAL;
-
        old_mtu = dev->mtu;
        dev->mtu = new_mtu;
 
        /* return early if the buffer sizes will not change */
        if (old_mtu <= ETH_DATA_LEN && new_mtu <= ETH_DATA_LEN)
                return 0;
-       if (old_mtu == new_mtu)
-               return 0;
 
        /* synchronized against open : rtnl_lock() held by caller */
        if (netif_running(dev)) {
@@ -5719,6 +5714,10 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
        /* Add loopback capability to the device. */
        dev->hw_features |= NETIF_F_LOOPBACK;
 
+       /* MTU range: 64 - 1500 or 9100 */
+       dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN;
+       dev->max_mtu = np->pkt_limit;
+
        np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG;
        if ((id->driver_data & DEV_HAS_PAUSEFRAME_TX_V1) ||
            (id->driver_data & DEV_HAS_PAUSEFRAME_TX_V2) ||
index 8e13ec84c53812e92bbabd88a12a25e12c353a75..dd6b0d0f7fa504e33cbb873546137bf1d89e1979 100644 (file)
@@ -1256,7 +1256,6 @@ static const struct net_device_ops lpc_netdev_ops = {
        .ndo_do_ioctl           = lpc_eth_ioctl,
        .ndo_set_mac_address    = lpc_set_mac_address,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int lpc_eth_drv_probe(struct platform_device *pdev)
index 3cd87a41ac92c42f4f75716753dccd57eaba9c1a..d461f419948ea4179c161786047050a44ba457e4 100644 (file)
@@ -2260,16 +2260,10 @@ static int pch_gbe_set_mac(struct net_device *netdev, void *addr)
 static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-       int max_frame;
+       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
        unsigned long old_rx_buffer_len = adapter->rx_buffer_len;
        int err;
 
-       max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-       if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
-               (max_frame > PCH_GBE_MAX_JUMBO_FRAME_SIZE)) {
-               netdev_err(netdev, "Invalid MTU setting\n");
-               return -EINVAL;
-       }
        if (max_frame <= PCH_GBE_FRAME_SIZE_2048)
                adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_2048;
        else if (max_frame <= PCH_GBE_FRAME_SIZE_4096)
@@ -2633,6 +2627,11 @@ static int pch_gbe_probe(struct pci_dev *pdev,
        netdev->features = netdev->hw_features;
        pch_gbe_set_ethtool_ops(netdev);
 
+       /* MTU range: 46 - 10300 */
+       netdev->min_mtu = ETH_ZLEN - ETH_HLEN;
+       netdev->max_mtu = PCH_GBE_MAX_JUMBO_FRAME_SIZE -
+                         (ETH_HLEN + ETH_FCS_LEN);
+
        pch_gbe_mac_load_mac_addr(&adapter->hw);
        pch_gbe_mac_reset_hw(&adapter->hw);
 
index 91be2f02ef1cf9d5654a5e7a124506908637a951..2d04679a923a71454511e572a2714796b760bc69 100644 (file)
@@ -568,7 +568,6 @@ static const struct net_device_ops hamachi_netdev_ops = {
        .ndo_start_xmit         = hamachi_start_xmit,
        .ndo_get_stats          = hamachi_get_stats,
        .ndo_set_rx_mode        = set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_tx_timeout         = hamachi_tx_timeout,
index fb1d1031b0916044ea48ed1d287465827fb0d578..2a2ca5fa0c690281cbb433b450340279fdd91857 100644 (file)
@@ -360,7 +360,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_stop               = yellowfin_close,
        .ndo_start_xmit         = yellowfin_start_xmit,
        .ndo_set_rx_mode        = set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_do_ioctl           = netdev_ioctl,
index 2f4a837f0d6adcb066d6deb952859d6a711026e4..badfa1d562a41e9860ccd425addf936f78b2a04b 100644 (file)
@@ -53,7 +53,7 @@
  * - Multiqueue RX/TX
  */
 
-#define PE_MIN_MTU     64
+#define PE_MIN_MTU     (ETH_ZLEN + ETH_HLEN)
 #define PE_MAX_MTU     9000
 #define PE_DEF_MTU     ETH_DATA_LEN
 
@@ -1611,9 +1611,6 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
        int running;
        int ret = 0;
 
-       if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
-               return -EINVAL;
-
        running = netif_running(dev);
 
        if (running) {
@@ -1635,7 +1632,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
        }
 
        /* Setup checksum channels if large MTU and none already allocated */
-       if (new_mtu > 1500 && !mac->num_cs) {
+       if (new_mtu > PE_DEF_MTU && !mac->num_cs) {
                pasemi_mac_setup_csrings(mac);
                if (!mac->num_cs) {
                        ret = -ENOMEM;
@@ -1757,6 +1754,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        dev->netdev_ops = &pasemi_netdev_ops;
        dev->mtu = PE_DEF_MTU;
+
+       /* MTU range: 64 - 9000 */
+       dev->min_mtu = PE_MIN_MTU;
+       dev->max_mtu = PE_MAX_MTU;
+
        /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
        mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
 
index 2b10f1bcd1517458b2cfcb22e6ce4677995181a8..a996801d442dd87ed47e572355e497bde8f6c846 100644 (file)
@@ -987,20 +987,8 @@ int netxen_send_lro_cleanup(struct netxen_adapter *adapter)
 int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
 {
        struct netxen_adapter *adapter = netdev_priv(netdev);
-       int max_mtu;
        int rc = 0;
 
-       if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-               max_mtu = P3_MAX_MTU;
-       else
-               max_mtu = P2_MAX_MTU;
-
-       if (mtu > max_mtu) {
-               printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
-                               netdev->name, max_mtu);
-               return -EINVAL;
-       }
-
        if (adapter->set_mtu)
                rc = adapter->set_mtu(adapter, mtu);
 
index 7a0281a36c2818a002a8fc2bc00ceb6ae7221921..561fb94c72670ecf51db5eb51a963de4d8030eb6 100644 (file)
@@ -1572,6 +1572,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        adapter->physical_port = i;
        }
 
+       /* MTU range: 0 - 8000 (P2) or 9600 (P3) */
+       netdev->min_mtu = 0;
+       if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+               netdev->max_mtu = P3_MAX_MTU;
+       else
+               netdev->max_mtu = P2_MAX_MTU;
+
        netxen_nic_clear_stats(adapter);
 
        err = netxen_setup_intr(adapter);
index ddd410a91e1369a5fd586f4e2769d0fdb973b5d7..6b0e22d9fe4cf1c5b40df81606ec36d6f45364c2 100644 (file)
@@ -1652,6 +1652,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
 
        if (IS_PF(cdev)) {
                int max_vf_vlan_filters = 0;
+               int max_vf_mac_filters = 0;
 
                if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
                        for_each_hwfn(cdev, i)
@@ -1665,11 +1666,18 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
                        info->num_queues = cdev->num_hwfns;
                }
 
-               if (IS_QED_SRIOV(cdev))
+               if (IS_QED_SRIOV(cdev)) {
                        max_vf_vlan_filters = cdev->p_iov_info->total_vfs *
                                              QED_ETH_VF_NUM_VLAN_FILTERS;
-               info->num_vlan_filters = RESC_NUM(&cdev->hwfns[0], QED_VLAN) -
+                       max_vf_mac_filters = cdev->p_iov_info->total_vfs *
+                                            QED_ETH_VF_NUM_MAC_FILTERS;
+               }
+               info->num_vlan_filters = RESC_NUM(QED_LEADING_HWFN(cdev),
+                                                 QED_VLAN) -
                                         max_vf_vlan_filters;
+               info->num_mac_filters = RESC_NUM(QED_LEADING_HWFN(cdev),
+                                                QED_MAC) -
+                                       max_vf_mac_filters;
 
                ether_addr_copy(info->port_mac,
                                cdev->hwfns[0].hw_info.hw_mac_addr);
index f3a825a8f8d52dda6aff03074e61c830370d0594..6a353ffb87a494117e62cb65a2dda056bc1cf648 100644 (file)
@@ -2658,7 +2658,6 @@ static int qed_roce_ll2_start(struct qed_dev *cdev,
                DP_ERR(cdev, "qed roce ll2 start: failed memory allocation\n");
                return -ENOMEM;
        }
-       memset(roce_ll2, 0, sizeof(*roce_ll2));
        roce_ll2->handle = QED_LL2_UNUSED_HANDLE;
        roce_ll2->cbs = params->cbs;
        roce_ll2->cb_cookie = params->cb_cookie;
index b2c08e4d2a9b9de9c2042bc2afa22c6bd51c3618..9c897bc68d05545a88cfddf582ef19616042ce89 100644 (file)
@@ -110,8 +110,8 @@ union qed_spq_req_comp {
 };
 
 struct qed_spq_comp_done {
-       u64     done;
-       u8      fw_return_code;
+       unsigned int    done;
+       u8              fw_return_code;
 };
 
 struct qed_spq_entry {
index 9fbaf9429fd0a20c2e48616e2397c70f38fd3d14..019960b7855a9162a6c2fe75262bcc63551cac74 100644 (file)
 ***************************************************************************/
 
 #define SPQ_HIGH_PRI_RESERVE_DEFAULT    (1)
-#define SPQ_BLOCK_SLEEP_LENGTH          (1000)
+
+#define SPQ_BLOCK_DELAY_MAX_ITER        (10)
+#define SPQ_BLOCK_DELAY_US              (10)
+#define SPQ_BLOCK_SLEEP_MAX_ITER        (1000)
+#define SPQ_BLOCK_SLEEP_MS              (5)
 
 /***************************************************************************
 * Blocking Imp. (BLOCK/EBLOCK mode)
@@ -48,60 +52,88 @@ static void qed_spq_blocking_cb(struct qed_hwfn *p_hwfn,
 
        comp_done = (struct qed_spq_comp_done *)cookie;
 
-       comp_done->done                 = 0x1;
-       comp_done->fw_return_code       = fw_return_code;
+       comp_done->fw_return_code = fw_return_code;
 
-       /* make update visible to waiting thread */
-       smp_wmb();
+       /* Make sure completion done is visible on waiting thread */
+       smp_store_release(&comp_done->done, 0x1);
 }
 
-static int qed_spq_block(struct qed_hwfn *p_hwfn,
-                        struct qed_spq_entry *p_ent,
-                        u8 *p_fw_ret)
+static int __qed_spq_block(struct qed_hwfn *p_hwfn,
+                          struct qed_spq_entry *p_ent,
+                          u8 *p_fw_ret, bool sleep_between_iter)
 {
-       int sleep_count = SPQ_BLOCK_SLEEP_LENGTH;
        struct qed_spq_comp_done *comp_done;
-       int rc;
+       u32 iter_cnt;
 
        comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie;
-       while (sleep_count) {
-               /* validate we receive completion update */
-               smp_rmb();
-               if (comp_done->done == 1) {
+       iter_cnt = sleep_between_iter ? SPQ_BLOCK_SLEEP_MAX_ITER
+                                     : SPQ_BLOCK_DELAY_MAX_ITER;
+
+       while (iter_cnt--) {
+               /* Validate we receive completion update */
+               if (READ_ONCE(comp_done->done) == 1) {
+                       /* Read updated FW return value */
+                       smp_read_barrier_depends();
                        if (p_fw_ret)
                                *p_fw_ret = comp_done->fw_return_code;
                        return 0;
                }
-               usleep_range(5000, 10000);
-               sleep_count--;
+
+               if (sleep_between_iter)
+                       msleep(SPQ_BLOCK_SLEEP_MS);
+               else
+                       udelay(SPQ_BLOCK_DELAY_US);
+       }
+
+       return -EBUSY;
+}
+
+static int qed_spq_block(struct qed_hwfn *p_hwfn,
+                        struct qed_spq_entry *p_ent,
+                        u8 *p_fw_ret, bool skip_quick_poll)
+{
+       struct qed_spq_comp_done *comp_done;
+       int rc;
+
+       /* A relatively short polling period w/o sleeping, to allow the FW to
+        * complete the ramrod and thus possibly to avoid the following sleeps.
+        */
+       if (!skip_quick_poll) {
+               rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, false);
+               if (!rc)
+                       return 0;
        }
 
+       /* Move to polling with a sleeping period between iterations */
+       rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, true);
+       if (!rc)
+               return 0;
+
        DP_INFO(p_hwfn, "Ramrod is stuck, requesting MCP drain\n");
        rc = qed_mcp_drain(p_hwfn, p_hwfn->p_main_ptt);
-       if (rc != 0)
+       if (rc) {
                DP_NOTICE(p_hwfn, "MCP drain failed\n");
+               goto err;
+       }
 
        /* Retry after drain */
-       sleep_count = SPQ_BLOCK_SLEEP_LENGTH;
-       while (sleep_count) {
-               /* validate we receive completion update */
-               smp_rmb();
-               if (comp_done->done == 1) {
-                       if (p_fw_ret)
-                               *p_fw_ret = comp_done->fw_return_code;
-                       return 0;
-               }
-               usleep_range(5000, 10000);
-               sleep_count--;
-       }
+       rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, true);
+       if (!rc)
+               return 0;
 
+       comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie;
        if (comp_done->done == 1) {
                if (p_fw_ret)
                        *p_fw_ret = comp_done->fw_return_code;
                return 0;
        }
-
-       DP_NOTICE(p_hwfn, "Ramrod is stuck, MCP drain failed\n");
+err:
+       DP_NOTICE(p_hwfn,
+                 "Ramrod is stuck [CID %08x cmd %02x protocol %02x echo %04x]\n",
+                 le32_to_cpu(p_ent->elem.hdr.cid),
+                 p_ent->elem.hdr.cmd_id,
+                 p_ent->elem.hdr.protocol_id,
+                 le16_to_cpu(p_ent->elem.hdr.echo));
 
        return -EBUSY;
 }
@@ -725,7 +757,8 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
                 * access p_ent here to see whether it's successful or not.
                 * Thus, after gaining the answer perform the cleanup here.
                 */
-               rc = qed_spq_block(p_hwfn, p_ent, fw_return_code);
+               rc = qed_spq_block(p_hwfn, p_ent, fw_return_code,
+                                  p_ent->queue == &p_spq->unlimited_pending);
 
                if (p_ent->queue == &p_spq->unlimited_pending) {
                        /* This is an allocated p_ent which does not need to
index d2d6621fe0e591047912dfc5bef20307f8012bbb..6f029f91e4dee76494c3bfd0a6170b591a91654a 100644 (file)
@@ -109,7 +109,8 @@ static int qed_sp_vf_stop(struct qed_hwfn *p_hwfn,
 }
 
 static bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn,
-                                 int rel_vf_id, bool b_enabled_only)
+                                 int rel_vf_id,
+                                 bool b_enabled_only, bool b_non_malicious)
 {
        if (!p_hwfn->pf_iov_info) {
                DP_NOTICE(p_hwfn->cdev, "No iov info\n");
@@ -124,6 +125,10 @@ static bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn,
            b_enabled_only)
                return false;
 
+       if ((p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_malicious) &&
+           b_non_malicious)
+               return false;
+
        return true;
 }
 
@@ -138,7 +143,8 @@ static struct qed_vf_info *qed_iov_get_vf_info(struct qed_hwfn *p_hwfn,
                return NULL;
        }
 
-       if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id, b_enabled_only))
+       if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id,
+                                 b_enabled_only, false))
                vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id];
        else
                DP_ERR(p_hwfn, "qed_iov_get_vf_info: VF[%d] is not enabled\n",
@@ -542,7 +548,8 @@ int qed_iov_hw_info(struct qed_hwfn *p_hwfn)
        return 0;
 }
 
-static bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid)
+bool _qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn,
+                             int vfid, bool b_fail_malicious)
 {
        /* Check PF supports sriov */
        if (IS_VF(p_hwfn->cdev) || !IS_QED_SRIOV(p_hwfn->cdev) ||
@@ -550,12 +557,17 @@ static bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid)
                return false;
 
        /* Check VF validity */
-       if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true))
+       if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true, b_fail_malicious))
                return false;
 
        return true;
 }
 
+bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid)
+{
+       return _qed_iov_pf_sanity_check(p_hwfn, vfid, true);
+}
+
 static void qed_iov_set_vf_to_disable(struct qed_dev *cdev,
                                      u16 rel_vf_id, u8 to_disable)
 {
@@ -652,6 +664,9 @@ static int qed_iov_enable_vf_access(struct qed_hwfn *p_hwfn,
 
        qed_iov_vf_igu_reset(p_hwfn, p_ptt, vf);
 
+       /* It's possible VF was previously considered malicious */
+       vf->b_malicious = false;
+
        rc = qed_mcp_config_vf_msix(p_hwfn, p_ptt, vf->abs_vf_id, vf->num_sbs);
        if (rc)
                return rc;
@@ -2804,6 +2819,13 @@ qed_iov_execute_vf_flr_cleanup(struct qed_hwfn *p_hwfn,
                        return rc;
                }
 
+               /* Workaround to make VF-PF channel ready, as FW
+                * doesn't do that as a part of FLR.
+                */
+               REG_WR(p_hwfn,
+                      GTT_BAR0_MAP_REG_USDM_RAM +
+                      USTORM_VF_PF_CHANNEL_READY_OFFSET(vfid), 1);
+
                /* VF_STOPPED has to be set only after final cleanup
                 * but prior to re-enabling the VF.
                 */
@@ -2942,7 +2964,8 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn,
        mbx->first_tlv = mbx->req_virt->first_tlv;
 
        /* check if tlv type is known */
-       if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) {
+       if (qed_iov_tlv_supported(mbx->first_tlv.tl.type) &&
+           !p_vf->b_malicious) {
                switch (mbx->first_tlv.tl.type) {
                case CHANNEL_TLV_ACQUIRE:
                        qed_iov_vf_mbx_acquire(p_hwfn, p_ptt, p_vf);
@@ -2984,6 +3007,15 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn,
                        qed_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf);
                        break;
                }
+       } else if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) {
+               DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+                          "VF [%02x] - considered malicious; Ignoring TLV [%04x]\n",
+                          p_vf->abs_vf_id, mbx->first_tlv.tl.type);
+
+               qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf,
+                                    mbx->first_tlv.tl.type,
+                                    sizeof(struct pfvf_def_resp_tlv),
+                                    PFVF_STATUS_MALICIOUS);
        } else {
                /* unknown TLV - this may belong to a VF driver from the future
                 * - a version written after this PF driver was written, which
@@ -3033,20 +3065,30 @@ static void qed_iov_pf_get_and_clear_pending_events(struct qed_hwfn *p_hwfn,
        memset(p_pending_events, 0, sizeof(u64) * QED_VF_ARRAY_LENGTH);
 }
 
-static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
-                             u16 abs_vfid, struct regpair *vf_msg)
+static struct qed_vf_info *qed_sriov_get_vf_from_absid(struct qed_hwfn *p_hwfn,
+                                                      u16 abs_vfid)
 {
-       u8 min = (u8)p_hwfn->cdev->p_iov_info->first_vf_in_pf;
-       struct qed_vf_info *p_vf;
+       u8 min = (u8) p_hwfn->cdev->p_iov_info->first_vf_in_pf;
 
-       if (!qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min)) {
+       if (!_qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min, false)) {
                DP_VERBOSE(p_hwfn,
                           QED_MSG_IOV,
-                          "Got a message from VF [abs 0x%08x] that cannot be handled by PF\n",
+                          "Got indication for VF [abs 0x%08x] that cannot be handled by PF\n",
                           abs_vfid);
-               return 0;
+               return NULL;
        }
-       p_vf = &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min];
+
+       return &p_hwfn->pf_iov_info->vfs_array[(u8) abs_vfid - min];
+}
+
+static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
+                             u16 abs_vfid, struct regpair *vf_msg)
+{
+       struct qed_vf_info *p_vf = qed_sriov_get_vf_from_absid(p_hwfn,
+                          abs_vfid);
+
+       if (!p_vf)
+               return 0;
 
        /* List the physical address of the request so that handler
         * could later on copy the message from it.
@@ -3060,6 +3102,23 @@ static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
        return 0;
 }
 
+static void qed_sriov_vfpf_malicious(struct qed_hwfn *p_hwfn,
+                                    struct malicious_vf_eqe_data *p_data)
+{
+       struct qed_vf_info *p_vf;
+
+       p_vf = qed_sriov_get_vf_from_absid(p_hwfn, p_data->vf_id);
+
+       if (!p_vf)
+               return;
+
+       DP_INFO(p_hwfn,
+               "VF [%d] - Malicious behavior [%02x]\n",
+               p_vf->abs_vf_id, p_data->err_id);
+
+       p_vf->b_malicious = true;
+}
+
 int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn,
                        u8 opcode, __le16 echo, union event_ring_data *data)
 {
@@ -3067,6 +3126,9 @@ int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn,
        case COMMON_EVENT_VF_PF_CHANNEL:
                return qed_sriov_vfpf_msg(p_hwfn, le16_to_cpu(echo),
                                          &data->vf_pf_channel.msg_addr);
+       case COMMON_EVENT_MALICIOUS_VF:
+               qed_sriov_vfpf_malicious(p_hwfn, &data->malicious_vf);
+               return 0;
        default:
                DP_INFO(p_hwfn->cdev, "Unknown sriov eqe event 0x%02x\n",
                        opcode);
@@ -3083,7 +3145,7 @@ u16 qed_iov_get_next_active_vf(struct qed_hwfn *p_hwfn, u16 rel_vf_id)
                goto out;
 
        for (i = rel_vf_id; i < p_iov->total_vfs; i++)
-               if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true))
+               if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true, false))
                        return i;
 
 out:
@@ -3130,6 +3192,12 @@ static void qed_iov_bulletin_set_forced_mac(struct qed_hwfn *p_hwfn,
                return;
        }
 
+       if (vf_info->b_malicious) {
+               DP_NOTICE(p_hwfn->cdev,
+                         "Can't set forced MAC to malicious VF [%d]\n", vfid);
+               return;
+       }
+
        feature = 1 << MAC_ADDR_FORCED;
        memcpy(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN);
 
@@ -3153,6 +3221,12 @@ static void qed_iov_bulletin_set_forced_vlan(struct qed_hwfn *p_hwfn,
                return;
        }
 
+       if (vf_info->b_malicious) {
+               DP_NOTICE(p_hwfn->cdev,
+                         "Can't set forced vlan to malicious VF [%d]\n", vfid);
+               return;
+       }
+
        feature = 1 << VLAN_ADDR_FORCED;
        vf_info->bulletin.p_virt->pvid = pvid;
        if (pvid)
@@ -3367,7 +3441,7 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled)
                qed_for_each_vf(hwfn, j) {
                        int k;
 
-                       if (!qed_iov_is_valid_vfid(hwfn, j, true))
+                       if (!qed_iov_is_valid_vfid(hwfn, j, true, false))
                                continue;
 
                        /* Wait until VF is disabled before releasing */
@@ -3425,7 +3499,7 @@ static int qed_sriov_enable(struct qed_dev *cdev, int num)
                num_sbs = min_t(int, sb_cnt_info.sb_free_blk, limit);
 
                for (i = 0; i < num; i++) {
-                       if (!qed_iov_is_valid_vfid(hwfn, i, false))
+                       if (!qed_iov_is_valid_vfid(hwfn, i, false, true))
                                continue;
 
                        rc = qed_iov_init_hw_for_vf(hwfn,
@@ -3477,7 +3551,7 @@ static int qed_sriov_pf_set_mac(struct qed_dev *cdev, u8 *mac, int vfid)
                return -EINVAL;
        }
 
-       if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) {
+       if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) {
                DP_VERBOSE(cdev, QED_MSG_IOV,
                           "Cannot set VF[%d] MAC (VF is not active)\n", vfid);
                return -EINVAL;
@@ -3509,7 +3583,7 @@ static int qed_sriov_pf_set_vlan(struct qed_dev *cdev, u16 vid, int vfid)
                return -EINVAL;
        }
 
-       if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) {
+       if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) {
                DP_VERBOSE(cdev, QED_MSG_IOV,
                           "Cannot set VF[%d] MAC (VF is not active)\n", vfid);
                return -EINVAL;
@@ -3543,7 +3617,7 @@ static int qed_get_vf_config(struct qed_dev *cdev,
        if (IS_VF(cdev))
                return -EINVAL;
 
-       if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) {
+       if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, false)) {
                DP_VERBOSE(cdev, QED_MSG_IOV,
                           "VF index [%d] isn't active\n", vf_id);
                return -EINVAL;
@@ -3647,7 +3721,7 @@ static int qed_set_vf_link_state(struct qed_dev *cdev,
        if (IS_VF(cdev))
                return -EINVAL;
 
-       if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) {
+       if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, true)) {
                DP_VERBOSE(cdev, QED_MSG_IOV,
                           "VF index [%d] isn't active\n", vf_id);
                return -EINVAL;
index 0dd23e409b3ff500bab9da2c311555e3dcd1b557..3cf515b1b4278fe5697923958b1e4eb7aaf54913 100644 (file)
@@ -132,6 +132,7 @@ struct qed_vf_info {
        struct qed_iov_vf_mbx vf_mbx;
        enum vf_state state;
        bool b_init;
+       bool b_malicious;
        u8 to_disable;
 
        struct qed_bulletin bulletin;
index abf5bf11f865669c33c9428f98776bc7858e3abe..f580bf4c97f0950b53c1b960f2a4cb3223723e79 100644 (file)
@@ -1230,8 +1230,8 @@ static void qed_handle_bulletin_change(struct qed_hwfn *hwfn)
 
        is_mac_exist = qed_vf_bulletin_get_forced_mac(hwfn, mac,
                                                      &is_mac_forced);
-       if (is_mac_exist && is_mac_forced && cookie)
-               ops->force_mac(cookie, mac);
+       if (is_mac_exist && cookie)
+               ops->force_mac(cookie, mac, !!is_mac_forced);
 
        /* Always update link configuration according to bulletin */
        qed_link_update(hwfn);
index 35db7a28aa13ececdb9efa735864e64e90ff6c5f..944745b7c4c0f107d8aea0c618421af1668a2728 100644 (file)
@@ -40,6 +40,7 @@ enum {
        PFVF_STATUS_NOT_SUPPORTED,
        PFVF_STATUS_NO_RESOURCE,
        PFVF_STATUS_FORCED,
+       PFVF_STATUS_MALICIOUS,
 };
 
 /* vf pf channel tlvs */
index 974689a133372152238e1cd3033a1838222c1bc5..cf8d3547aecf8bba81fc441f260a376c346d635b 100644 (file)
@@ -320,6 +320,7 @@ struct qede_fastpath {
 #define XMIT_L4_CSUM           BIT(0)
 #define XMIT_LSO               BIT(1)
 #define XMIT_ENC               BIT(2)
+#define XMIT_ENC_GSO_L4_CSUM   BIT(3)
 
 #define QEDE_CSUM_ERROR                        BIT(0)
 #define QEDE_CSUM_UNNECESSARY          BIT(1)
@@ -362,8 +363,9 @@ void qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq);
 #define NUM_TX_BDS_MIN         128
 #define NUM_TX_BDS_DEF         NUM_TX_BDS_MAX
 
-#define QEDE_MIN_PKT_LEN       64
-#define QEDE_RX_HDR_SIZE       256
+#define QEDE_MIN_PKT_LEN               64
+#define QEDE_RX_HDR_SIZE               256
+#define QEDE_MAX_JUMBO_PACKET_SIZE     9600
 #define        for_each_queue(i) for (i = 0; i < edev->num_queues; i++)
 
 #endif /* _QEDE_H_ */
index 12251a1032d19b58368fa8ee8c722091b288d6e4..0100f5c0a4ec3a21eccb81fb923c5c9f66f61f9d 100644 (file)
@@ -723,19 +723,11 @@ static void qede_update_mtu(struct qede_dev *edev, union qede_reload_args *args)
 }
 
 /* Netdevice NDOs */
-#define ETH_MAX_JUMBO_PACKET_SIZE      9600
-#define ETH_MIN_PACKET_SIZE            60
 int qede_change_mtu(struct net_device *ndev, int new_mtu)
 {
        struct qede_dev *edev = netdev_priv(ndev);
        union qede_reload_args args;
 
-       if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) ||
-           ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) {
-               DP_ERR(edev, "Can't support requested MTU size\n");
-               return -EINVAL;
-       }
-
        DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
                   "Configuring MTU size of %d\n", new_mtu);
 
index 7def29aaf65c962b63b483cb33cea9fd397b63bb..8488ad36a2b8cf5a209e8d5a6436eed5e57e695c 100644 (file)
@@ -171,10 +171,14 @@ static struct pci_driver qede_pci_driver = {
 #endif
 };
 
-static void qede_force_mac(void *dev, u8 *mac)
+static void qede_force_mac(void *dev, u8 *mac, bool forced)
 {
        struct qede_dev *edev = dev;
 
+       /* MAC hints take effect only if we haven't set one already */
+       if (is_valid_ether_addr(edev->ndev->dev_addr) && !forced)
+               return;
+
        ether_addr_copy(edev->ndev->dev_addr, mac);
        ether_addr_copy(edev->primary_mac, mac);
 }
@@ -396,8 +400,19 @@ static u32 qede_xmit_type(struct qede_dev *edev,
            (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
                *ipv6_ext = 1;
 
-       if (skb->encapsulation)
+       if (skb->encapsulation) {
                rc |= XMIT_ENC;
+               if (skb_is_gso(skb)) {
+                       unsigned short gso_type = skb_shinfo(skb)->gso_type;
+
+                       if ((gso_type & SKB_GSO_UDP_TUNNEL_CSUM) ||
+                           (gso_type & SKB_GSO_GRE_CSUM))
+                               rc |= XMIT_ENC_GSO_L4_CSUM;
+
+                       rc |= XMIT_LSO;
+                       return rc;
+               }
+       }
 
        if (skb_is_gso(skb))
                rc |= XMIT_LSO;
@@ -633,6 +648,12 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
                if (unlikely(xmit_type & XMIT_ENC)) {
                        first_bd->data.bd_flags.bitfields |=
                                1 << ETH_TX_1ST_BD_FLAGS_TUNN_IP_CSUM_SHIFT;
+
+                       if (xmit_type & XMIT_ENC_GSO_L4_CSUM) {
+                               u8 tmp = ETH_TX_1ST_BD_FLAGS_TUNN_L4_CSUM_SHIFT;
+
+                               first_bd->data.bd_flags.bitfields |= 1 << tmp;
+                       }
                        hlen = qede_get_skb_hlen(skb, true);
                } else {
                        first_bd->data.bd_flags.bitfields |=
@@ -2218,6 +2239,40 @@ static void qede_udp_tunnel_del(struct net_device *dev,
        schedule_delayed_work(&edev->sp_task, 0);
 }
 
+/* 8B udp header + 8B base tunnel header + 32B option length */
+#define QEDE_MAX_TUN_HDR_LEN 48
+
+static netdev_features_t qede_features_check(struct sk_buff *skb,
+                                            struct net_device *dev,
+                                            netdev_features_t features)
+{
+       if (skb->encapsulation) {
+               u8 l4_proto = 0;
+
+               switch (vlan_get_protocol(skb)) {
+               case htons(ETH_P_IP):
+                       l4_proto = ip_hdr(skb)->protocol;
+                       break;
+               case htons(ETH_P_IPV6):
+                       l4_proto = ipv6_hdr(skb)->nexthdr;
+                       break;
+               default:
+                       return features;
+               }
+
+               /* Disable offloads for geneve tunnels, as HW can't parse
+                * the geneve header which has option length greater than 32B.
+                */
+               if ((l4_proto == IPPROTO_UDP) &&
+                   ((skb_inner_mac_header(skb) -
+                     skb_transport_header(skb)) > QEDE_MAX_TUN_HDR_LEN))
+                       return features & ~(NETIF_F_CSUM_MASK |
+                                           NETIF_F_GSO_MASK);
+       }
+
+       return features;
+}
+
 static const struct net_device_ops qede_netdev_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
@@ -2242,6 +2297,7 @@ static const struct net_device_ops qede_netdev_ops = {
 #endif
        .ndo_udp_tunnel_add = qede_udp_tunnel_add,
        .ndo_udp_tunnel_del = qede_udp_tunnel_del,
+       .ndo_features_check = qede_features_check,
 };
 
 /* -------------------------------------------------------------------------
@@ -2308,6 +2364,8 @@ static void qede_init_ndev(struct qede_dev *edev)
 
        qede_set_ethtool_ops(ndev);
 
+       ndev->priv_flags = IFF_UNICAST_FLT;
+
        /* user-changeble features */
        hw_features = NETIF_F_GRO | NETIF_F_SG |
                      NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
@@ -2315,11 +2373,14 @@ static void qede_init_ndev(struct qede_dev *edev)
 
        /* Encap features*/
        hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL |
-                      NETIF_F_TSO_ECN;
+                      NETIF_F_TSO_ECN | NETIF_F_GSO_UDP_TUNNEL_CSUM |
+                      NETIF_F_GSO_GRE_CSUM;
        ndev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                                NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO_ECN |
                                NETIF_F_TSO6 | NETIF_F_GSO_GRE |
-                               NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM;
+                               NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM |
+                               NETIF_F_GSO_UDP_TUNNEL_CSUM |
+                               NETIF_F_GSO_GRE_CSUM;
 
        ndev->vlan_features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM |
                              NETIF_F_HIGHDMA;
@@ -2329,6 +2390,10 @@ static void qede_init_ndev(struct qede_dev *edev)
 
        ndev->hw_features = hw_features;
 
+       /* MTU range: 46 - 9600 */
+       ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
+       ndev->max_mtu = QEDE_MAX_JUMBO_PACKET_SIZE;
+
        /* Set network device HW mac */
        ether_addr_copy(edev->ndev->dev_addr, edev->dev_info.common.hw_mac);
 }
@@ -3877,7 +3942,7 @@ static void qede_config_rx_mode(struct net_device *ndev)
 
        /* Check for promiscuous */
        if ((ndev->flags & IFF_PROMISC) ||
-           (uc_count > 15)) { /* @@@TBD resource allocation - 1 */
+           (uc_count > edev->dev_info.num_mac_filters - 1)) {
                accept_flags = QED_FILTER_RX_MODE_TYPE_PROMISC;
        } else {
                /* Add MAC filters according to the unicast secondary macs */
index b09a6b80d10719c967994ed54618c50e25fdec0f..5c100ab86c0046ec72a011e5f806d6557ac7482c 100644 (file)
@@ -3755,7 +3755,6 @@ static const struct net_device_ops ql3xxx_netdev_ops = {
        .ndo_open               = ql3xxx_open,
        .ndo_start_xmit         = ql3xxx_send,
        .ndo_stop               = ql3xxx_close,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ql3xxx_set_mac_address,
        .ndo_tx_timeout         = ql3xxx_tx_timeout,
index 509b596cf1e8612436af6886dc0e2a6e78acdc1d..838cc0ceafd8d0824495206bf30cdaf53f98bc59 100644 (file)
@@ -1024,12 +1024,6 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        int rc = 0;
 
-       if (mtu < P3P_MIN_MTU || mtu > P3P_MAX_MTU) {
-               dev_err(&adapter->netdev->dev, "%d bytes < mtu < %d bytes"
-                       " not supported\n", P3P_MAX_MTU, P3P_MIN_MTU);
-               return -EINVAL;
-       }
-
        rc = qlcnic_fw_cmd_set_mtu(adapter, mtu);
 
        if (!rc)
index 3ae3968b0edf5ec260f8eaca3255a503ddc74278..4c0cce962585f61b61a43d780b0cbe64217de02e 100644 (file)
@@ -2342,6 +2342,10 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
        netdev->priv_flags |= IFF_UNICAST_FLT;
        netdev->irq = adapter->msix_entries[0].vector;
 
+       /* MTU range: 68 - 9600 */
+       netdev->min_mtu = P3P_MIN_MTU;
+       netdev->max_mtu = P3P_MAX_MTU;
+
        err = qlcnic_set_real_num_queues(adapter, adapter->drv_tx_rings,
                                         adapter->drv_sds_rings);
        if (err)
index fd4a8e473f11180b75bf7949845cdbcdd84486f6..1409412ab39da7a7a58e3100fdd8461b8b87992b 100644 (file)
@@ -4788,6 +4788,13 @@ static int qlge_probe(struct pci_dev *pdev,
        ndev->ethtool_ops = &qlge_ethtool_ops;
        ndev->watchdog_timeo = 10 * HZ;
 
+       /* MTU range: this driver only supports 1500 or 9000, so this only
+        * filters out values above or below, and we'll rely on
+        * qlge_change_mtu to make sure only 1500 or 9000 are allowed
+        */
+       ndev->min_mtu = ETH_DATA_LEN;
+       ndev->max_mtu = 9000;
+
        err = register_netdev(ndev);
        if (err) {
                dev_err(&pdev->dev, "net device registration failed.\n");
index 4fede4b8653861e88335759f052051e1fda9183d..8be526af659a5d81a91a31bfdf464ed780cd5114 100644 (file)
@@ -239,15 +239,8 @@ static void emac_rx_mode_set(struct net_device *netdev)
 /* Change the Maximum Transfer Unit (MTU) */
 static int emac_change_mtu(struct net_device *netdev, int new_mtu)
 {
-       unsigned int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
        struct emac_adapter *adpt = netdev_priv(netdev);
 
-       if ((max_frame < EMAC_MIN_ETH_FRAME_SIZE) ||
-           (max_frame > EMAC_MAX_ETH_FRAME_SIZE)) {
-               netdev_err(adpt->netdev, "error: invalid MTU setting\n");
-               return -EINVAL;
-       }
-
        netif_info(adpt, hw, adpt->netdev,
                   "changing MTU from %d to %d\n", netdev->mtu,
                   new_mtu);
@@ -680,6 +673,12 @@ static int emac_probe(struct platform_device *pdev)
        netdev->vlan_features |= NETIF_F_SG | NETIF_F_HW_CSUM |
                                 NETIF_F_TSO | NETIF_F_TSO6;
 
+       /* MTU range: 46 - 9194 */
+       netdev->min_mtu = EMAC_MIN_ETH_FRAME_SIZE -
+                         (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+       netdev->max_mtu = EMAC_MAX_ETH_FRAME_SIZE -
+                         (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
        INIT_WORK(&adpt->work_thread, emac_work_thread);
 
        /* Initialize queues */
index 5d965959c978efa7d0c07094b948652e87e5dad0..d5e795dcdf47ae824d663707f3353eb1563d6ba4 100644 (file)
@@ -43,9 +43,9 @@
 /* Frame length is invalid */
 #define QCAFRM_INVFRAME (QCAFRM_ERR_BASE - 4)
 
-/* Min/Max Ethernet MTU */
-#define QCAFRM_ETHMINMTU 46
-#define QCAFRM_ETHMAXMTU 1500
+/* Min/Max Ethernet MTU: 46/1500 */
+#define QCAFRM_ETHMINMTU (ETH_ZLEN - ETH_HLEN)
+#define QCAFRM_ETHMAXMTU ETH_DATA_LEN
 
 /* Min/Max frame lengths */
 #define QCAFRM_ETHMINLEN (QCAFRM_ETHMINMTU + ETH_HLEN)
index 6e2add97947128804668a9cdb08bac22f1b888d2..513e6c74e1990b6fb2c8b00ee9f5a4b70076115d 100644 (file)
@@ -780,24 +780,12 @@ qcaspi_netdev_uninit(struct net_device *dev)
                dev_kfree_skb(qca->rx_skb);
 }
 
-static int
-qcaspi_netdev_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < QCAFRM_ETHMINMTU) || (new_mtu > QCAFRM_ETHMAXMTU))
-               return -EINVAL;
-
-       dev->mtu = new_mtu;
-
-       return 0;
-}
-
 static const struct net_device_ops qcaspi_netdev_ops = {
        .ndo_init = qcaspi_netdev_init,
        .ndo_uninit = qcaspi_netdev_uninit,
        .ndo_open = qcaspi_netdev_open,
        .ndo_stop = qcaspi_netdev_close,
        .ndo_start_xmit = qcaspi_netdev_xmit,
-       .ndo_change_mtu = qcaspi_netdev_change_mtu,
        .ndo_set_mac_address = eth_mac_addr,
        .ndo_tx_timeout = qcaspi_netdev_tx_timeout,
        .ndo_validate_addr = eth_validate_addr,
@@ -814,6 +802,10 @@ qcaspi_netdev_setup(struct net_device *dev)
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        dev->tx_queue_len = 100;
 
+       /* MTU range: 46 - 1500 */
+       dev->min_mtu = QCAFRM_ETHMINMTU;
+       dev->max_mtu = QCAFRM_ETHMAXMTU;
+
        qca = netdev_priv(dev);
        memset(qca, 0, sizeof(struct qcaspi));
 
index 5ef5d728c2505e0977d056541552d204c108eb42..4ff4e0491406b1b2a06d5e05b9b4871bebc203e6 100644 (file)
@@ -969,7 +969,6 @@ static const struct net_device_ops r6040_netdev_ops = {
        .ndo_start_xmit         = r6040_start_xmit,
        .ndo_get_stats          = r6040_get_stats,
        .ndo_set_rx_mode        = r6040_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_do_ioctl           = r6040_ioctl,
index 5297bf77211cf344c7a8556c2778abc9c1e4a9cd..b7c89ebcf4a24552f5517aeb90041e760c8dc15e 100644 (file)
@@ -1277,10 +1277,6 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct cp_private *cp = netdev_priv(dev);
 
-       /* check for invalid MTU, according to hardware limits */
-       if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU)
-               return -EINVAL;
-
        /* if network interface not up, no need for complexity */
        if (!netif_running(dev)) {
                dev->mtu = new_mtu;
@@ -2010,6 +2006,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
                NETIF_F_HIGHDMA;
 
+       /* MTU range: 60 - 4096 */
+       dev->min_mtu = CP_MIN_MTU;
+       dev->max_mtu = CP_MAX_MTU;
+
        rc = register_netdev(dev);
        if (rc)
                goto err_out_iomap;
index da4c2d8a4173f89ca8b18e8a81be7c053c0f48a5..9bc047ac883bf91397a4eb4b6bb9cdb7812acaf0 100644 (file)
@@ -924,19 +924,10 @@ static int rtl8139_set_features(struct net_device *dev, netdev_features_t featur
        return 0;
 }
 
-static int rtl8139_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu < 68 || new_mtu > MAX_ETH_DATA_SIZE)
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static const struct net_device_ops rtl8139_netdev_ops = {
        .ndo_open               = rtl8139_open,
        .ndo_stop               = rtl8139_close,
        .ndo_get_stats64        = rtl8139_get_stats64,
-       .ndo_change_mtu         = rtl8139_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = rtl8139_set_mac_address,
        .ndo_start_xmit         = rtl8139_start_xmit,
@@ -1022,6 +1013,10 @@ static int rtl8139_init_one(struct pci_dev *pdev,
        dev->hw_features |= NETIF_F_RXALL;
        dev->hw_features |= NETIF_F_RXFCS;
 
+       /* MTU range: 68 - 1770 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = MAX_ETH_DATA_SIZE;
+
        /* tp zeroed and aligned in alloc_etherdev */
        tp = netdev_priv(dev);
 
index 5cb96785fb632703de8e9c08fe7fca0f37949cbd..570ed3bd3cbfcd0cbe1dc0ce5764823d1fc70ff6 100644 (file)
@@ -245,7 +245,6 @@ static const struct net_device_ops atp_netdev_ops = {
        .ndo_start_xmit         = atp_send_packet,
        .ndo_set_rx_mode        = set_rx_mode,
        .ndo_tx_timeout         = tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index bf000d819a21a0150e5db96c5cb660b8c8fe5caf..2830190aaacec38444344348f232bf555e2f963a 100644 (file)
@@ -6673,10 +6673,6 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
 
-       if (new_mtu < ETH_ZLEN ||
-           new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
-               return -EINVAL;
-
        if (new_mtu > ETH_DATA_LEN)
                rtl_hw_jumbo_enable(tp);
        else
@@ -8431,6 +8427,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->hw_features |= NETIF_F_RXALL;
        dev->hw_features |= NETIF_F_RXFCS;
 
+       /* MTU range: 60 - hw-specific max */
+       dev->min_mtu = ETH_ZLEN;
+       dev->max_mtu = rtl_chip_infos[chipset].jumbo_max;
+
        tp->hw_start = cfg->hw_start;
        tp->event_slow = cfg->event_slow;
 
index 630536bc72f975a171bd3ae85d105b6b2ccbbbf1..27cfec3154c8e0f2c1bdc582e325a836a5ad9f0f 100644 (file)
@@ -1780,7 +1780,6 @@ static const struct net_device_ops ravb_netdev_ops = {
        .ndo_do_ioctl           = ravb_do_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 /* MDIO bus init function */
index 05b0dc55de774f486699e066ec24370129b42061..e443695c27574d462610967050294a8deb59ff9f 100644 (file)
@@ -2914,7 +2914,6 @@ static const struct net_device_ops sh_eth_netdev_ops = {
        .ndo_do_ioctl           = sh_eth_do_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static const struct net_device_ops sh_eth_netdev_ops_tsu = {
@@ -2929,7 +2928,6 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = {
        .ndo_do_ioctl           = sh_eth_do_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 #ifdef CONFIG_OF
index 24b746406bc7a505ee08c75ef3713a0be5e6dba7..67df4cf93362eaa1a7e9eeda9d3aab3dcc333f75 100644 (file)
@@ -1953,12 +1953,6 @@ static int rocker_port_change_mtu(struct net_device *dev, int new_mtu)
        int running = netif_running(dev);
        int err;
 
-#define ROCKER_PORT_MIN_MTU    68
-#define ROCKER_PORT_MAX_MTU    9000
-
-       if (new_mtu < ROCKER_PORT_MIN_MTU || new_mtu > ROCKER_PORT_MAX_MTU)
-               return -EINVAL;
-
        if (running)
                rocker_port_stop(dev);
 
@@ -2536,9 +2530,11 @@ static void rocker_port_dev_addr_init(struct rocker_port *rocker_port)
        }
 }
 
+#define ROCKER_PORT_MIN_MTU    ETH_MIN_MTU
+#define ROCKER_PORT_MAX_MTU    9000
 static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
 {
-       const struct pci_dev *pdev = rocker->pdev;
+       struct pci_dev *pdev = rocker->pdev;
        struct rocker_port *rocker_port;
        struct net_device *dev;
        int err;
@@ -2546,6 +2542,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
        dev = alloc_etherdev(sizeof(struct rocker_port));
        if (!dev)
                return -ENOMEM;
+       SET_NETDEV_DEV(dev, &pdev->dev);
        rocker_port = netdev_priv(dev);
        rocker_port->dev = dev;
        rocker_port->rocker = rocker;
@@ -2570,6 +2567,10 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
 
        dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_SG;
 
+       /* MTU range: 68 - 9000 */
+       dev->min_mtu = ROCKER_PORT_MIN_MTU;
+       dev->max_mtu = ROCKER_PORT_MAX_MTU;
+
        err = rocker_world_port_pre_init(rocker_port);
        if (err) {
                dev_err(&pdev->dev, "port world pre-init failed\n");
@@ -2839,20 +2840,37 @@ static bool rocker_port_dev_check_under(const struct net_device *dev,
        return true;
 }
 
+struct rocker_walk_data {
+       struct rocker *rocker;
+       struct rocker_port *port;
+};
+
+static int rocker_lower_dev_walk(struct net_device *lower_dev, void *_data)
+{
+       struct rocker_walk_data *data = _data;
+       int ret = 0;
+
+       if (rocker_port_dev_check_under(lower_dev, data->rocker)) {
+               data->port = netdev_priv(lower_dev);
+               ret = 1;
+       }
+
+       return ret;
+}
+
 struct rocker_port *rocker_port_dev_lower_find(struct net_device *dev,
                                               struct rocker *rocker)
 {
-       struct net_device *lower_dev;
-       struct list_head *iter;
+       struct rocker_walk_data data;
 
        if (rocker_port_dev_check_under(dev, rocker))
                return netdev_priv(dev);
 
-       netdev_for_each_all_lower_dev(dev, lower_dev, iter) {
-               if (rocker_port_dev_check_under(lower_dev, rocker))
-                       return netdev_priv(lower_dev);
-       }
-       return NULL;
+       data.rocker = rocker;
+       data.port = NULL;
+       netdev_walk_all_lower_dev(dev, rocker_lower_dev_walk, &data);
+
+       return data.port;
 }
 
 static int rocker_netdevice_event(struct notifier_block *unused,
index ea44a2456ce16128e093afe56ad2ac85d826d247..5dbe40640da6931c35e9dd763b6cb6e28d141d9f 100644 (file)
@@ -1820,19 +1820,6 @@ static int sxgbe_set_features(struct net_device *dev,
  */
 static int sxgbe_change_mtu(struct net_device *dev, int new_mtu)
 {
-       /* RFC 791, page 25, "Every internet module must be able to forward
-        * a datagram of 68 octets without further fragmentation."
-        */
-       if (new_mtu < MIN_MTU || (new_mtu > MAX_MTU)) {
-               netdev_err(dev, "invalid MTU, MTU should be in between %d and %d\n",
-                          MIN_MTU, MAX_MTU);
-               return -EINVAL;
-       }
-
-       /* Return if the buffer sizes will not change */
-       if (dev->mtu == new_mtu)
-               return 0;
-
        dev->mtu = new_mtu;
 
        if (!netif_running(dev))
@@ -2144,6 +2131,10 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
        /* assign filtering support */
        ndev->priv_flags |= IFF_UNICAST_FLT;
 
+       /* MTU range: 68 - 9000 */
+       ndev->min_mtu = MIN_MTU;
+       ndev->max_mtu = MAX_MTU;
+
        priv->msg_enable = netif_msg_init(debug, default_msg_level);
 
        /* Enable TCP segmentation offload for all DMA channels */
index bdac936a68bc2b12d0baf302551337c79702b265..244c1e1710173847395dcc9b65739205620fa011 100644 (file)
@@ -745,7 +745,6 @@ static const struct net_device_ops ether3_netdev_ops = {
        .ndo_set_rx_mode        = ether3_setmulticastlist,
        .ndo_tx_timeout         = ether3_timeout,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
index c2bd5378ffdaf005d039785bccfe59f52b2d6c8d..ed34196028b8e8bb8db5b913f61c1d5718000492 100644 (file)
@@ -714,7 +714,6 @@ static const struct net_device_ops sgiseeq_netdev_ops = {
        .ndo_tx_timeout         = timeout,
        .ndo_set_rx_mode        = sgiseeq_set_multicast,
        .ndo_set_mac_address    = sgiseeq_set_mac_address,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 3cf3557106c22f335ca5e04d2065e01d41056572..b626da6e80a59a1a8fd673554b66e38dee4219e9 100644 (file)
@@ -2263,18 +2263,6 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
        rc = efx_check_disabled(efx);
        if (rc)
                return rc;
-       if (new_mtu > EFX_MAX_MTU) {
-               netif_err(efx, drv, efx->net_dev,
-                         "Requested MTU of %d too big (max: %d)\n",
-                         new_mtu, EFX_MAX_MTU);
-               return -EINVAL;
-       }
-       if (new_mtu < EFX_MIN_MTU) {
-               netif_err(efx, drv, efx->net_dev,
-                         "Requested MTU of %d too small (min: %d)\n",
-                         new_mtu, EFX_MIN_MTU);
-               return -EINVAL;
-       }
 
        netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
 
@@ -2478,6 +2466,8 @@ static int efx_register_netdev(struct efx_nic *efx)
                net_dev->priv_flags |= IFF_UNICAST_FLT;
        net_dev->ethtool_ops = &efx_ethtool_ops;
        net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
+       net_dev->min_mtu = EFX_MIN_MTU;
+       net_dev->max_mtu = EFX_MAX_MTU;
 
        rtnl_lock();
 
index 7a254da85dd789f7d4de8f62c6a13e17a1629004..42051ab98cf003dc2ae49a57d29f958508375269 100644 (file)
@@ -1225,7 +1225,6 @@ static const struct net_device_ops ioc3_netdev_ops = {
        .ndo_do_ioctl           = ioc3_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ioc3_set_mac_address,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
index aaa80f13859b160f81b19e776a0cac422e302008..69d2d30e5ef13b9026ecdcd4ff090540ac1385ef 100644 (file)
@@ -815,7 +815,6 @@ static const struct net_device_ops meth_netdev_ops = {
        .ndo_start_xmit         = meth_tx,
        .ndo_do_ioctl           = meth_ioctl,
        .ndo_tx_timeout         = meth_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_set_rx_mode        = meth_set_rx_mode,
index 7426f8b21252c1df07cd5330b8dd94a484112972..6c2e2b311c16d396f3969a90183648d7e77a7858 100644 (file)
@@ -1386,7 +1386,6 @@ static const struct net_device_ops sc92031_netdev_ops = {
        .ndo_open               = sc92031_open,
        .ndo_stop               = sc92031_stop,
        .ndo_set_rx_mode        = sc92031_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_tx_timeout         = sc92031_tx_timeout,
index 27be6c8693150a2c52a81d42b68281ca07df21f0..210e35d079dd88672fe5c419955a04913d49ad62 100644 (file)
@@ -1833,7 +1833,6 @@ static const struct net_device_ops sis190_netdev_ops = {
        .ndo_start_xmit         = sis190_start_xmit,
        .ndo_tx_timeout         = sis190_tx_timeout,
        .ndo_set_rx_mode        = sis190_set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = sis190_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 6f85276376e8eeec0309cabffabf3ae83e5dfbf7..39fca6c0b68dbf62454c1c4092770b0509f50946 100644 (file)
@@ -400,7 +400,6 @@ static const struct net_device_ops sis900_netdev_ops = {
        .ndo_start_xmit         = sis900_start_xmit,
        .ndo_set_config         = sis900_set_config,
        .ndo_set_rx_mode        = set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_do_ioctl           = mii_ioctl,
index 7186b89269ad718a2723a9b2f6f79d77e1061aef..fe9760ffab517b9cfef43f8f7fe0f66fc33dedd0 100644 (file)
@@ -313,7 +313,6 @@ static const struct net_device_ops epic_netdev_ops = {
        .ndo_get_stats          = epic_get_stats,
        .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = netdev_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index cb49c9654f0a7c2d8d0bb922bc4b38c7e6180419..4f19c6166182e780b77222c566390c5acdf2ad3e 100644 (file)
@@ -1753,7 +1753,6 @@ static const struct net_device_ops smc911x_netdev_ops = {
        .ndo_start_xmit         = smc911x_hard_start_xmit,
        .ndo_tx_timeout         = smc911x_timeout,
        .ndo_set_rx_mode        = smc911x_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index d496888b85d34b89331c37c9768d07e6eff7ea64..c8d84679ede74ed2d3e3ebd87fe3acefa4d1d77d 100644 (file)
@@ -809,7 +809,6 @@ static const struct net_device_ops smc_netdev_ops = {
        .ndo_start_xmit         = smc_wait_to_send_packet,
        .ndo_tx_timeout         = smc_timeout,
        .ndo_set_rx_mode        = smc_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index db3c696d7002ad921bbf8d4d3257f7e738c36c07..f1c75e291e55ba4324a34bd84948f95f317039be 100644 (file)
@@ -294,7 +294,6 @@ static const struct net_device_ops smc_netdev_ops = {
        .ndo_set_config         = s9k_config,
        .ndo_set_rx_mode        = set_rx_mode,
        .ndo_do_ioctl           = smc_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 73212590d04a362e055039d90b11e1329592d21a..65077c77082a2f042117a0889c2b15099c58eae5 100644 (file)
@@ -602,7 +602,8 @@ static void smc_hardware_send_pkt(unsigned long data)
        SMC_PUSH_DATA(lp, buf, len & ~1);
 
        /* Send final ctl word with the last byte if there is one */
-       SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));
+       SMC_outw(lp, ((len & 1) ? (0x2000 | buf[len - 1]) : 0), ioaddr,
+                DATA_REG(lp));
 
        /*
         * If THROTTLE_TX_PKTS is set, we stop the queue here. This will
@@ -1762,7 +1763,6 @@ static const struct net_device_ops smc_netdev_ops = {
        .ndo_start_xmit         = smc_hard_start_xmit,
        .ndo_tx_timeout         = smc_timeout,
        .ndo_set_rx_mode        = smc_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2326,6 +2326,8 @@ static int smc_drv_probe(struct platform_device *pdev)
                if (!device_property_read_u32(&pdev->dev, "reg-shift",
                                              &val))
                        lp->io_shift = val;
+               lp->cfg.pxa_u16_align4 =
+                       device_property_read_bool(&pdev->dev, "pxa-u16-align4");
        }
 #endif
 
index ea846546746937d76d68e49da0e8e5847a457c27..08b17adf0a658bd1d471588c0dd8376a61776a94 100644 (file)
 
 #define SMC_inl(a, r)          readl((a) + (r))
 #define SMC_outb(v, a, r)      writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)                                              \
+#define SMC_outw(lp, v, a, r)                                          \
        do {                                                            \
                unsigned int __v = v, __smc_r = r;                      \
                if (SMC_16BIT(lp))                                      \
-                       __SMC_outw(__v, a, __smc_r);                    \
+                       __SMC_outw(lp, __v, a, __smc_r);                \
                else if (SMC_8BIT(lp))                                  \
                        SMC_outw_b(__v, a, __smc_r);                    \
                else                                                    \
 #define SMC_IRQ_FLAGS          (-1)    /* from resource */
 
 /* We actually can't write halfwords properly if not word aligned */
-static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
+static inline void _SMC_outw_align4(u16 val, void __iomem *ioaddr, int reg,
+                                   bool use_align4_workaround)
 {
-       if ((machine_is_mainstone() || machine_is_stargate2() ||
-            machine_is_pxa_idp()) && reg & 2) {
+       if (use_align4_workaround) {
                unsigned int v = val << 16;
                v |= readl(ioaddr + (reg & ~2)) & 0xffff;
                writel(v, ioaddr + (reg & ~2));
@@ -119,6 +119,12 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
        }
 }
 
+#define __SMC_outw(lp, v, a, r)                                                \
+       _SMC_outw_align4((v), (a), (r),                                 \
+                        IS_BUILTIN(CONFIG_ARCH_PXA) && ((r) & 2) &&    \
+                        (lp)->cfg.pxa_u16_align4)
+
+
 #elif  defined(CONFIG_SH_SH4202_MICRODEV)
 
 #define SMC_CAN_USE_8BIT       0
@@ -129,7 +135,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_inw(a, r)          inw((a) + (r) - 0xa0000000)
 #define SMC_inl(a, r)          inl((a) + (r) - 0xa0000000)
 #define SMC_outb(v, a, r)      outb(v, (a) + (r) - 0xa0000000)
-#define SMC_outw(v, a, r)      outw(v, (a) + (r) - 0xa0000000)
+#define SMC_outw(lp, v, a, r)  outw(v, (a) + (r) - 0xa0000000)
 #define SMC_outl(v, a, r)      outl(v, (a) + (r) - 0xa0000000)
 #define SMC_insl(a, r, p, l)   insl((a) + (r) - 0xa0000000, p, l)
 #define SMC_outsl(a, r, p, l)  outsl((a) + (r) - 0xa0000000, p, l)
@@ -147,7 +153,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_inb(a, r)          inb(((u32)a) + (r))
 #define SMC_inw(a, r)          inw(((u32)a) + (r))
 #define SMC_outb(v, a, r)      outb(v, ((u32)a) + (r))
-#define SMC_outw(v, a, r)      outw(v, ((u32)a) + (r))
+#define SMC_outw(lp, v, a, r)  outw(v, ((u32)a) + (r))
 #define SMC_insw(a, r, p, l)   insw(((u32)a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)  outsw(((u32)a) + (r), p, l)
 
@@ -175,7 +181,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_inw(a, r)           readw((a) + (r))
 #define SMC_inl(a, r)           readl((a) + (r))
 #define SMC_outb(v, a, r)       writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)       writew(v, (a) + (r))
+#define SMC_outw(lp, v, a, r)   writew(v, (a) + (r))
 #define SMC_outl(v, a, r)       writel(v, (a) + (r))
 #define SMC_insw(a, r, p, l)    readsw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)   writesw((a) + (r), p, l)
@@ -207,7 +213,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
 }
 
 #define SMC_inw(a, r)          _swapw(readw((a) + (r)))
-#define SMC_outw(v, a, r)      writew(_swapw(v), (a) + (r))
+#define SMC_outw(lp, v, a, r)  writew(_swapw(v), (a) + (r))
 #define SMC_insw(a, r, p, l)   mcf_insw(a + r, p, l)
 #define SMC_outsw(a, r, p, l)  mcf_outsw(a + r, p, l)
 
@@ -241,7 +247,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
 #define SMC_inw(a, r)          ioread16((a) + (r))
 #define SMC_inl(a, r)          ioread32((a) + (r))
 #define SMC_outb(v, a, r)      iowrite8(v, (a) + (r))
-#define SMC_outw(v, a, r)      iowrite16(v, (a) + (r))
+#define SMC_outw(lp, v, a, r)  iowrite16(v, (a) + (r))
 #define SMC_outl(v, a, r)      iowrite32(v, (a) + (r))
 #define SMC_insw(a, r, p, l)   ioread16_rep((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)  iowrite16_rep((a) + (r), p, l)
@@ -303,6 +309,8 @@ struct smc_local {
 
        /* the low address lines on some platforms aren't connected... */
        int     io_shift;
+       /* on some platforms a u16 write must be 4-bytes aligned */
+       bool    half_word_align4;
 
        struct smc91x_platdata cfg;
 };
@@ -457,7 +465,7 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 
 #if ! SMC_CAN_USE_16BIT
 
-#define SMC_outw(x, ioaddr, reg)       SMC_outw_b(x, ioaddr, reg)
+#define SMC_outw(lp, x, ioaddr, reg)   SMC_outw_b(x, ioaddr, reg)
 #define SMC_inw(ioaddr, reg)           SMC_inw_b(ioaddr, reg)
 #define SMC_insw(a, r, p, l)           BUG()
 #define SMC_outsw(a, r, p, l)          BUG()
@@ -909,7 +917,7 @@ static const char * chip_ids[ 16 ] =  {
                else if (SMC_8BIT(lp))                          \
                        SMC_outb(x, ioaddr, PN_REG(lp));                \
                else                                                    \
-                       SMC_outw(x, ioaddr, PN_REG(lp));                \
+                       SMC_outw(lp, x, ioaddr, PN_REG(lp));            \
        } while (0)
 
 #define SMC_GET_AR(lp)                                         \
@@ -937,7 +945,7 @@ static const char * chip_ids[ 16 ] =  {
                        int __mask;                                     \
                        local_irq_save(__flags);                        \
                        __mask = SMC_inw(ioaddr, INT_REG(lp)) & ~0xff; \
-                       SMC_outw(__mask | (x), ioaddr, INT_REG(lp));    \
+                       SMC_outw(lp, __mask | (x), ioaddr, INT_REG(lp)); \
                        local_irq_restore(__flags);                     \
                }                                                       \
        } while (0)
@@ -951,7 +959,7 @@ static const char * chip_ids[ 16 ] =  {
                if (SMC_8BIT(lp))                                       \
                        SMC_outb(x, ioaddr, IM_REG(lp));                \
                else                                                    \
-                       SMC_outw((x) << 8, ioaddr, INT_REG(lp));        \
+                       SMC_outw(lp, (x) << 8, ioaddr, INT_REG(lp));    \
        } while (0)
 
 #define SMC_CURRENT_BANK(lp)   SMC_inw(ioaddr, BANK_SELECT)
@@ -961,22 +969,22 @@ static const char * chip_ids[ 16 ] =  {
                if (SMC_MUST_ALIGN_WRITE(lp))                           \
                        SMC_outl((x)<<16, ioaddr, 12<<SMC_IO_SHIFT);    \
                else                                                    \
-                       SMC_outw(x, ioaddr, BANK_SELECT);               \
+                       SMC_outw(lp, x, ioaddr, BANK_SELECT);           \
        } while (0)
 
 #define SMC_GET_BASE(lp)               SMC_inw(ioaddr, BASE_REG(lp))
 
-#define SMC_SET_BASE(lp, x)            SMC_outw(x, ioaddr, BASE_REG(lp))
+#define SMC_SET_BASE(lp, x)    SMC_outw(lp, x, ioaddr, BASE_REG(lp))
 
 #define SMC_GET_CONFIG(lp)     SMC_inw(ioaddr, CONFIG_REG(lp))
 
-#define SMC_SET_CONFIG(lp, x)  SMC_outw(x, ioaddr, CONFIG_REG(lp))
+#define SMC_SET_CONFIG(lp, x)  SMC_outw(lp, x, ioaddr, CONFIG_REG(lp))
 
 #define SMC_GET_COUNTER(lp)    SMC_inw(ioaddr, COUNTER_REG(lp))
 
 #define SMC_GET_CTL(lp)                SMC_inw(ioaddr, CTL_REG(lp))
 
-#define SMC_SET_CTL(lp, x)             SMC_outw(x, ioaddr, CTL_REG(lp))
+#define SMC_SET_CTL(lp, x)     SMC_outw(lp, x, ioaddr, CTL_REG(lp))
 
 #define SMC_GET_MII(lp)                SMC_inw(ioaddr, MII_REG(lp))
 
@@ -987,20 +995,20 @@ static const char * chip_ids[ 16 ] =  {
                if (SMC_MUST_ALIGN_WRITE(lp))                           \
                        SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 1));   \
                else                                                    \
-                       SMC_outw(x, ioaddr, GP_REG(lp));                \
+                       SMC_outw(lp, x, ioaddr, GP_REG(lp));            \
        } while (0)
 
-#define SMC_SET_MII(lp, x)             SMC_outw(x, ioaddr, MII_REG(lp))
+#define SMC_SET_MII(lp, x)     SMC_outw(lp, x, ioaddr, MII_REG(lp))
 
 #define SMC_GET_MIR(lp)                SMC_inw(ioaddr, MIR_REG(lp))
 
-#define SMC_SET_MIR(lp, x)             SMC_outw(x, ioaddr, MIR_REG(lp))
+#define SMC_SET_MIR(lp, x)     SMC_outw(lp, x, ioaddr, MIR_REG(lp))
 
 #define SMC_GET_MMU_CMD(lp)    SMC_inw(ioaddr, MMU_CMD_REG(lp))
 
-#define SMC_SET_MMU_CMD(lp, x) SMC_outw(x, ioaddr, MMU_CMD_REG(lp))
+#define SMC_SET_MMU_CMD(lp, x) SMC_outw(lp, x, ioaddr, MMU_CMD_REG(lp))
 
-#define SMC_GET_FIFO(lp)               SMC_inw(ioaddr, FIFO_REG(lp))
+#define SMC_GET_FIFO(lp)       SMC_inw(ioaddr, FIFO_REG(lp))
 
 #define SMC_GET_PTR(lp)                SMC_inw(ioaddr, PTR_REG(lp))
 
@@ -1009,14 +1017,14 @@ static const char * chip_ids[ 16 ] =  {
                if (SMC_MUST_ALIGN_WRITE(lp))                           \
                        SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 4, 2));   \
                else                                                    \
-                       SMC_outw(x, ioaddr, PTR_REG(lp));               \
+                       SMC_outw(lp, x, ioaddr, PTR_REG(lp));           \
        } while (0)
 
 #define SMC_GET_EPH_STATUS(lp) SMC_inw(ioaddr, EPH_STATUS_REG(lp))
 
 #define SMC_GET_RCR(lp)                SMC_inw(ioaddr, RCR_REG(lp))
 
-#define SMC_SET_RCR(lp, x)             SMC_outw(x, ioaddr, RCR_REG(lp))
+#define SMC_SET_RCR(lp, x)             SMC_outw(lp, x, ioaddr, RCR_REG(lp))
 
 #define SMC_GET_REV(lp)                SMC_inw(ioaddr, REV_REG(lp))
 
@@ -1027,12 +1035,12 @@ static const char * chip_ids[ 16 ] =  {
                if (SMC_MUST_ALIGN_WRITE(lp))                           \
                        SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 0));   \
                else                                                    \
-                       SMC_outw(x, ioaddr, RPC_REG(lp));               \
+                       SMC_outw(lp, x, ioaddr, RPC_REG(lp));           \
        } while (0)
 
 #define SMC_GET_TCR(lp)                SMC_inw(ioaddr, TCR_REG(lp))
 
-#define SMC_SET_TCR(lp, x)             SMC_outw(x, ioaddr, TCR_REG(lp))
+#define SMC_SET_TCR(lp, x)     SMC_outw(lp, x, ioaddr, TCR_REG(lp))
 
 #ifndef SMC_GET_MAC_ADDR
 #define SMC_GET_MAC_ADDR(lp, addr)                                     \
@@ -1049,18 +1057,18 @@ static const char * chip_ids[ 16 ] =  {
 
 #define SMC_SET_MAC_ADDR(lp, addr)                                     \
        do {                                                            \
-               SMC_outw(addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
-               SMC_outw(addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
-               SMC_outw(addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
+               SMC_outw(lp, addr[0] | (addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
+               SMC_outw(lp, addr[2] | (addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
+               SMC_outw(lp, addr[4] | (addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
        } while (0)
 
 #define SMC_SET_MCAST(lp, x)                                           \
        do {                                                            \
                const unsigned char *mt = (x);                          \
-               SMC_outw(mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
-               SMC_outw(mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
-               SMC_outw(mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
-               SMC_outw(mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
+               SMC_outw(lp, mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
+               SMC_outw(lp, mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
+               SMC_outw(lp, mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
+               SMC_outw(lp, mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
        } while (0)
 
 #define SMC_PUT_PKT_HDR(lp, status, length)                            \
@@ -1069,8 +1077,8 @@ static const char * chip_ids[ 16 ] =  {
                        SMC_outl((status) | (length)<<16, ioaddr,       \
                                 DATA_REG(lp));                 \
                else {                                                  \
-                       SMC_outw(status, ioaddr, DATA_REG(lp)); \
-                       SMC_outw(length, ioaddr, DATA_REG(lp)); \
+                       SMC_outw(lp, status, ioaddr, DATA_REG(lp));     \
+                       SMC_outw(lp, length, ioaddr, DATA_REG(lp));     \
                }                                                       \
        } while (0)
 
index e9b8579e6241476bd2c82486a0e1a91b2cafcad7..cdb343f0c6e0a92178d94f8078f1398a659c5218 100644 (file)
@@ -2152,7 +2152,6 @@ static const struct net_device_ops smsc911x_netdev_ops = {
        .ndo_get_stats          = smsc911x_get_stats,
        .ndo_set_rx_mode        = smsc911x_set_multicast_list,
        .ndo_do_ioctl           = smsc911x_do_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = smsc911x_set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index bec6963ac71e978e8959fce41607e06ceb955518..5ad1dfb40f2b4f790b9636319a087623752e4566 100644 (file)
@@ -367,8 +367,8 @@ static int socfpga_dwmac_resume(struct device *dev)
         * control register 0, and can be modified by the phy driver
         * framework.
         */
-       if (priv->phydev)
-               phy_resume(priv->phydev);
+       if (ndev->phydev)
+               phy_resume(ndev->phydev);
 
        return stmmac_resume(dev);
 }
index b15fc55f1b96ae10ad5333f4a5c2f7fe669dd234..758b4e2c783c130a14d00516bdc7b8a0c5a90d61 100644 (file)
@@ -90,7 +90,6 @@ struct stmmac_priv {
        struct mac_device_info *hw;
        spinlock_t lock;
 
-       struct phy_device *phydev ____cacheline_aligned_in_smp;
        int oldlink;
        int speed;
        int oldduplex;
index 1e06173fc9d733d63c1e5ccbbc12c03506d0a44c..3fe9340b748f511739d8cbbed6a62cda7a09bd23 100644 (file)
@@ -269,25 +269,26 @@ static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
        strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
 }
 
-static int stmmac_ethtool_getsettings(struct net_device *dev,
-                                     struct ethtool_cmd *cmd)
+static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
+                                            struct ethtool_link_ksettings *cmd)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
-       struct phy_device *phy = priv->phydev;
+       struct phy_device *phy = dev->phydev;
        int rc;
 
        if (priv->hw->pcs & STMMAC_PCS_RGMII ||
            priv->hw->pcs & STMMAC_PCS_SGMII) {
                struct rgmii_adv adv;
+               u32 supported, advertising, lp_advertising;
 
                if (!priv->xstats.pcs_link) {
-                       ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
-                       cmd->duplex = DUPLEX_UNKNOWN;
+                       cmd->base.speed = SPEED_UNKNOWN;
+                       cmd->base.duplex = DUPLEX_UNKNOWN;
                        return 0;
                }
-               cmd->duplex = priv->xstats.pcs_duplex;
+               cmd->base.duplex = priv->xstats.pcs_duplex;
 
-               ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed);
+               cmd->base.speed = priv->xstats.pcs_speed;
 
                /* Get and convert ADV/LP_ADV from the HW AN registers */
                if (!priv->hw->mac->pcs_get_adv_lp)
@@ -297,45 +298,59 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
 
                /* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */
 
+               ethtool_convert_link_mode_to_legacy_u32(
+                       &supported, cmd->link_modes.supported);
+               ethtool_convert_link_mode_to_legacy_u32(
+                       &advertising, cmd->link_modes.advertising);
+               ethtool_convert_link_mode_to_legacy_u32(
+                       &lp_advertising, cmd->link_modes.lp_advertising);
+
                if (adv.pause & STMMAC_PCS_PAUSE)
-                       cmd->advertising |= ADVERTISED_Pause;
+                       advertising |= ADVERTISED_Pause;
                if (adv.pause & STMMAC_PCS_ASYM_PAUSE)
-                       cmd->advertising |= ADVERTISED_Asym_Pause;
+                       advertising |= ADVERTISED_Asym_Pause;
                if (adv.lp_pause & STMMAC_PCS_PAUSE)
-                       cmd->lp_advertising |= ADVERTISED_Pause;
+                       lp_advertising |= ADVERTISED_Pause;
                if (adv.lp_pause & STMMAC_PCS_ASYM_PAUSE)
-                       cmd->lp_advertising |= ADVERTISED_Asym_Pause;
+                       lp_advertising |= ADVERTISED_Asym_Pause;
 
                /* Reg49[3] always set because ANE is always supported */
-               cmd->autoneg = ADVERTISED_Autoneg;
-               cmd->supported |= SUPPORTED_Autoneg;
-               cmd->advertising |= ADVERTISED_Autoneg;
-               cmd->lp_advertising |= ADVERTISED_Autoneg;
+               cmd->base.autoneg = ADVERTISED_Autoneg;
+               supported |= SUPPORTED_Autoneg;
+               advertising |= ADVERTISED_Autoneg;
+               lp_advertising |= ADVERTISED_Autoneg;
 
                if (adv.duplex) {
-                       cmd->supported |= (SUPPORTED_1000baseT_Full |
-                                          SUPPORTED_100baseT_Full |
-                                          SUPPORTED_10baseT_Full);
-                       cmd->advertising |= (ADVERTISED_1000baseT_Full |
-                                            ADVERTISED_100baseT_Full |
-                                            ADVERTISED_10baseT_Full);
+                       supported |= (SUPPORTED_1000baseT_Full |
+                                     SUPPORTED_100baseT_Full |
+                                     SUPPORTED_10baseT_Full);
+                       advertising |= (ADVERTISED_1000baseT_Full |
+                                       ADVERTISED_100baseT_Full |
+                                       ADVERTISED_10baseT_Full);
                } else {
-                       cmd->supported |= (SUPPORTED_1000baseT_Half |
-                                          SUPPORTED_100baseT_Half |
-                                          SUPPORTED_10baseT_Half);
-                       cmd->advertising |= (ADVERTISED_1000baseT_Half |
-                                            ADVERTISED_100baseT_Half |
-                                            ADVERTISED_10baseT_Half);
+                       supported |= (SUPPORTED_1000baseT_Half |
+                                     SUPPORTED_100baseT_Half |
+                                     SUPPORTED_10baseT_Half);
+                       advertising |= (ADVERTISED_1000baseT_Half |
+                                       ADVERTISED_100baseT_Half |
+                                       ADVERTISED_10baseT_Half);
                }
                if (adv.lp_duplex)
-                       cmd->lp_advertising |= (ADVERTISED_1000baseT_Full |
-                                               ADVERTISED_100baseT_Full |
-                                               ADVERTISED_10baseT_Full);
+                       lp_advertising |= (ADVERTISED_1000baseT_Full |
+                                          ADVERTISED_100baseT_Full |
+                                          ADVERTISED_10baseT_Full);
                else
-                       cmd->lp_advertising |= (ADVERTISED_1000baseT_Half |
-                                               ADVERTISED_100baseT_Half |
-                                               ADVERTISED_10baseT_Half);
-               cmd->port = PORT_OTHER;
+                       lp_advertising |= (ADVERTISED_1000baseT_Half |
+                                          ADVERTISED_100baseT_Half |
+                                          ADVERTISED_10baseT_Half);
+               cmd->base.port = PORT_OTHER;
+
+               ethtool_convert_legacy_u32_to_link_mode(
+                       cmd->link_modes.supported, supported);
+               ethtool_convert_legacy_u32_to_link_mode(
+                       cmd->link_modes.advertising, advertising);
+               ethtool_convert_legacy_u32_to_link_mode(
+                       cmd->link_modes.lp_advertising, lp_advertising);
 
                return 0;
        }
@@ -350,16 +365,16 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
                "link speed / duplex setting\n", dev->name);
                return -EBUSY;
        }
-       cmd->transceiver = XCVR_INTERNAL;
-       rc = phy_ethtool_gset(phy, cmd);
+       rc = phy_ethtool_ksettings_get(phy, cmd);
        return rc;
 }
 
-static int stmmac_ethtool_setsettings(struct net_device *dev,
-                                     struct ethtool_cmd *cmd)
+static int
+stmmac_ethtool_set_link_ksettings(struct net_device *dev,
+                                 const struct ethtool_link_ksettings *cmd)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
-       struct phy_device *phy = priv->phydev;
+       struct phy_device *phy = dev->phydev;
        int rc;
 
        if (priv->hw->pcs & STMMAC_PCS_RGMII ||
@@ -367,7 +382,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
                u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;
 
                /* Only support ANE */
-               if (cmd->autoneg != AUTONEG_ENABLE)
+               if (cmd->base.autoneg != AUTONEG_ENABLE)
                        return -EINVAL;
 
                mask &= (ADVERTISED_1000baseT_Half |
@@ -389,7 +404,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
        }
 
        spin_lock(&priv->lock);
-       rc = phy_ethtool_sset(phy, cmd);
+       rc = phy_ethtool_ksettings_set(phy, cmd);
        spin_unlock(&priv->lock);
 
        return rc;
@@ -468,12 +483,12 @@ stmmac_get_pauseparam(struct net_device *netdev,
                if (!adv_lp.pause)
                        return;
        } else {
-               if (!(priv->phydev->supported & SUPPORTED_Pause) ||
-                   !(priv->phydev->supported & SUPPORTED_Asym_Pause))
+               if (!(netdev->phydev->supported & SUPPORTED_Pause) ||
+                   !(netdev->phydev->supported & SUPPORTED_Asym_Pause))
                        return;
        }
 
-       pause->autoneg = priv->phydev->autoneg;
+       pause->autoneg = netdev->phydev->autoneg;
 
        if (priv->flow_ctrl & FLOW_RX)
                pause->rx_pause = 1;
@@ -487,7 +502,7 @@ stmmac_set_pauseparam(struct net_device *netdev,
                      struct ethtool_pauseparam *pause)
 {
        struct stmmac_priv *priv = netdev_priv(netdev);
-       struct phy_device *phy = priv->phydev;
+       struct phy_device *phy = netdev->phydev;
        int new_pause = FLOW_OFF;
 
        if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
@@ -547,7 +562,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
                        }
                }
                if (priv->eee_enabled) {
-                       int val = phy_get_eee_err(priv->phydev);
+                       int val = phy_get_eee_err(dev->phydev);
                        if (val)
                                priv->xstats.phy_eee_wakeup_error_n = val;
                }
@@ -666,7 +681,7 @@ static int stmmac_ethtool_op_get_eee(struct net_device *dev,
        edata->eee_active = priv->eee_active;
        edata->tx_lpi_timer = priv->tx_lpi_timer;
 
-       return phy_ethtool_get_eee(priv->phydev, edata);
+       return phy_ethtool_get_eee(dev->phydev, edata);
 }
 
 static int stmmac_ethtool_op_set_eee(struct net_device *dev,
@@ -691,7 +706,7 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
                priv->tx_lpi_timer = edata->tx_lpi_timer;
        }
 
-       return phy_ethtool_set_eee(priv->phydev, edata);
+       return phy_ethtool_set_eee(dev->phydev, edata);
 }
 
 static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
@@ -850,8 +865,6 @@ static int stmmac_set_tunable(struct net_device *dev,
 static const struct ethtool_ops stmmac_ethtool_ops = {
        .begin = stmmac_check_if_running,
        .get_drvinfo = stmmac_ethtool_getdrvinfo,
-       .get_settings = stmmac_ethtool_getsettings,
-       .set_settings = stmmac_ethtool_setsettings,
        .get_msglevel = stmmac_ethtool_getmsglevel,
        .set_msglevel = stmmac_ethtool_setmsglevel,
        .get_regs = stmmac_ethtool_gregs,
@@ -871,6 +884,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
        .set_coalesce = stmmac_set_coalesce,
        .get_tunable = stmmac_get_tunable,
        .set_tunable = stmmac_set_tunable,
+       .get_link_ksettings = stmmac_ethtool_get_link_ksettings,
+       .set_link_ksettings = stmmac_ethtool_set_link_ksettings,
 };
 
 void stmmac_set_ethtool_ops(struct net_device *netdev)
index 48e71fad42103737334224da7b2789e8cd4c446f..10909c9c0033f2ec5c6faad1687a49cb49e3dfbb 100644 (file)
@@ -221,7 +221,8 @@ static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv)
  */
 static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
 {
-       struct phy_device *phydev = priv->phydev;
+       struct net_device *ndev = priv->dev;
+       struct phy_device *phydev = ndev->phydev;
 
        if (likely(priv->plat->fix_mac_speed))
                priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
@@ -279,6 +280,7 @@ static void stmmac_eee_ctrl_timer(unsigned long arg)
  */
 bool stmmac_eee_init(struct stmmac_priv *priv)
 {
+       struct net_device *ndev = priv->dev;
        unsigned long flags;
        bool ret = false;
 
@@ -295,7 +297,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                int tx_lpi_timer = priv->tx_lpi_timer;
 
                /* Check if the PHY supports EEE */
-               if (phy_init_eee(priv->phydev, 1)) {
+               if (phy_init_eee(ndev->phydev, 1)) {
                        /* To manage at run-time if the EEE cannot be supported
                         * anymore (for example because the lp caps have been
                         * changed).
@@ -327,7 +329,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                                                     tx_lpi_timer);
                }
                /* Set HW EEE according to the speed */
-               priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
+               priv->hw->mac->set_eee_pls(priv->hw, ndev->phydev->link);
 
                ret = true;
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -700,7 +702,7 @@ static void stmmac_release_ptp(struct stmmac_priv *priv)
 static void stmmac_adjust_link(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
-       struct phy_device *phydev = priv->phydev;
+       struct phy_device *phydev = dev->phydev;
        unsigned long flags;
        int new_state = 0;
        unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
@@ -883,8 +885,6 @@ static int stmmac_init_phy(struct net_device *dev)
        pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
                 " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
 
-       priv->phydev = phydev;
-
        return 0;
 }
 
@@ -1809,8 +1809,8 @@ static int stmmac_open(struct net_device *dev)
 
        stmmac_init_tx_coalesce(priv);
 
-       if (priv->phydev)
-               phy_start(priv->phydev);
+       if (dev->phydev)
+               phy_start(dev->phydev);
 
        /* Request the IRQ lines */
        ret = request_irq(dev->irq, stmmac_interrupt,
@@ -1857,8 +1857,8 @@ wolirq_error:
 init_error:
        free_dma_desc_resources(priv);
 dma_desc_error:
-       if (priv->phydev)
-               phy_disconnect(priv->phydev);
+       if (dev->phydev)
+               phy_disconnect(dev->phydev);
 
        return ret;
 }
@@ -1877,10 +1877,9 @@ static int stmmac_release(struct net_device *dev)
                del_timer_sync(&priv->eee_ctrl_timer);
 
        /* Stop and disconnect the PHY */
-       if (priv->phydev) {
-               phy_stop(priv->phydev);
-               phy_disconnect(priv->phydev);
-               priv->phydev = NULL;
+       if (dev->phydev) {
+               phy_stop(dev->phydev);
+               phy_disconnect(dev->phydev);
        }
 
        netif_stop_queue(dev);
@@ -2718,27 +2717,11 @@ static void stmmac_set_rx_mode(struct net_device *dev)
  */
 static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
 {
-       struct stmmac_priv *priv = netdev_priv(dev);
-       int max_mtu;
-
        if (netif_running(dev)) {
                pr_err("%s: must be stopped to change its MTU\n", dev->name);
                return -EBUSY;
        }
 
-       if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00))
-               max_mtu = JUMBO_LEN;
-       else
-               max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
-
-       if (priv->plat->maxmtu < max_mtu)
-               max_mtu = priv->plat->maxmtu;
-
-       if ((new_mtu < 46) || (new_mtu > max_mtu)) {
-               pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
-               return -EINVAL;
-       }
-
        dev->mtu = new_mtu;
 
        netdev_update_features(dev);
@@ -2872,7 +2855,6 @@ static void stmmac_poll_controller(struct net_device *dev)
  */
 static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct stmmac_priv *priv = netdev_priv(dev);
        int ret = -EOPNOTSUPP;
 
        if (!netif_running(dev))
@@ -2882,9 +2864,9 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        case SIOCGMIIPHY:
        case SIOCGMIIREG:
        case SIOCSMIIREG:
-               if (!priv->phydev)
+               if (!dev->phydev)
                        return -EINVAL;
-               ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+               ret = phy_mii_ioctl(dev->phydev, rq, cmd);
                break;
        case SIOCSHWTSTAMP:
                ret = stmmac_hwtstamp_ioctl(dev, rq);
@@ -3321,6 +3303,15 @@ int stmmac_dvr_probe(struct device *device,
 #endif
        priv->msg_enable = netif_msg_init(debug, default_msg_level);
 
+       /* MTU range: 46 - hw-specific max */
+       ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
+       if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00))
+               ndev->max_mtu = JUMBO_LEN;
+       else
+               ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
+       if (priv->plat->maxmtu < ndev->max_mtu)
+               ndev->max_mtu = priv->plat->maxmtu;
+
        if (flow_ctrl)
                priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */
 
@@ -3437,8 +3428,8 @@ int stmmac_suspend(struct device *dev)
        if (!ndev || !netif_running(ndev))
                return 0;
 
-       if (priv->phydev)
-               phy_stop(priv->phydev);
+       if (ndev->phydev)
+               phy_stop(ndev->phydev);
 
        spin_lock_irqsave(&priv->lock, flags);
 
@@ -3532,8 +3523,8 @@ int stmmac_resume(struct device *dev)
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       if (priv->phydev)
-               phy_start(priv->phydev);
+       if (ndev->phydev)
+               phy_start(ndev->phydev);
 
        return 0;
 }
index 062bce9acde6f555794376cc25e24981033e0868..e9e5ef241c6f9f37bc14766611e21dee728088f9 100644 (file)
@@ -3863,9 +3863,6 @@ static int cas_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct cas *cp = netdev_priv(dev);
 
-       if (new_mtu < CAS_MIN_MTU || new_mtu > CAS_MAX_MTU)
-               return -EINVAL;
-
        dev->mtu = new_mtu;
        if (!netif_running(dev) || !netif_device_present(dev))
                return 0;
@@ -5115,6 +5112,10 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (pci_using_dac)
                dev->features |= NETIF_F_HIGHDMA;
 
+       /* MTU range: 60 - varies or 9000 */
+       dev->min_mtu = CAS_MIN_MTU;
+       dev->max_mtu = CAS_MAX_MTU;
+
        if (register_netdev(dev)) {
                dev_err(&pdev->dev, "Cannot register net device, aborting\n");
                goto err_out_free_consistent;
index 0ac449acaf5b734052ee3d4d2b98e90475148c9a..335b8766063807a42ae9a9cb0b82aa7ea396a809 100644 (file)
@@ -139,7 +139,6 @@ static const struct net_device_ops vsw_ops = {
        .ndo_set_mac_address    = sunvnet_set_mac_addr_common,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = sunvnet_tx_timeout_common,
-       .ndo_change_mtu         = sunvnet_change_mtu_common,
        .ndo_start_xmit         = vsw_start_xmit,
        .ndo_select_queue       = vsw_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -239,6 +238,10 @@ static struct net_device *vsw_alloc_netdev(u8 hwaddr[],
                           NETIF_F_HW_CSUM | NETIF_F_SG;
        dev->features = dev->hw_features;
 
+       /* MTU range: 68 - 65535 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = VNET_MAX_MTU;
+
        SET_NETDEV_DEV(dev, &vdev->dev);
 
        return dev;
index a2371aa14a49f840702b5867f5ad80f6b520ee16..f90d1af6d390654cec17a52572191df4ddc4b4ba 100644 (file)
@@ -6754,9 +6754,6 @@ static int niu_change_mtu(struct net_device *dev, int new_mtu)
        struct niu *np = netdev_priv(dev);
        int err, orig_jumbo, new_jumbo;
 
-       if (new_mtu < 68 || new_mtu > NIU_MAX_MTU)
-               return -EINVAL;
-
        orig_jumbo = (dev->mtu > ETH_DATA_LEN);
        new_jumbo = (new_mtu > ETH_DATA_LEN);
 
@@ -9823,6 +9820,10 @@ static int niu_pci_init_one(struct pci_dev *pdev,
 
        dev->irq = pdev->irq;
 
+       /* MTU range: 68 - 9216 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = NIU_MAX_MTU;
+
        niu_assign_netdev_ops(dev);
 
        err = niu_get_invariants(np);
index aa4f9d2d8fa98f2b5c4a63710c24ad5387f5a73f..ea89ef3b48fb82524ec431e89178763a93f42d78 100644 (file)
@@ -1064,7 +1064,6 @@ static const struct net_device_ops bigmac_ops = {
        .ndo_get_stats          = bigmac_get_stats,
        .ndo_set_rx_mode        = bigmac_set_multicast,
        .ndo_tx_timeout         = bigmac_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index d6ad0fbd054e10bf34d48d2f522b0660781de02d..66ecf0fcc3309f89b832770d3c7644871170c0fa 100644 (file)
@@ -2476,9 +2476,9 @@ static void gem_set_multicast(struct net_device *dev)
 }
 
 /* Jumbo-grams don't seem to work :-( */
-#define GEM_MIN_MTU    68
+#define GEM_MIN_MTU    ETH_MIN_MTU
 #if 1
-#define GEM_MAX_MTU    1500
+#define GEM_MAX_MTU    ETH_DATA_LEN
 #else
 #define GEM_MAX_MTU    9000
 #endif
@@ -2487,9 +2487,6 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct gem *gp = netdev_priv(dev);
 
-       if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
-               return -EINVAL;
-
        dev->mtu = new_mtu;
 
        /* We'll just catch it later when the device is up'd or resumed */
@@ -2977,6 +2974,10 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (pci_using_dac)
                dev->features |= NETIF_F_HIGHDMA;
 
+       /* MTU range: 68 - 1500 (Jumbo mode is broken) */
+       dev->min_mtu = GEM_MIN_MTU;
+       dev->max_mtu = GEM_MAX_MTU;
+
        /* Register with kernel */
        if (register_netdev(dev)) {
                pr_err("Cannot register net device, aborting\n");
index cf4dcff051d5b9d3fb3edf20552501cc44c72a5b..ca96408058b05d49a2c64daba4591f512db0da28 100644 (file)
@@ -2669,7 +2669,6 @@ static const struct net_device_ops hme_netdev_ops = {
        .ndo_tx_timeout         = happy_meal_tx_timeout,
        .ndo_get_stats          = happy_meal_get_stats,
        .ndo_set_rx_mode        = happy_meal_set_multicast,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 9b825780b3be02829b54799b0e287ed2c8976a09..c5ef711f656707888f8c71c3d346e4da81eb6836 100644 (file)
@@ -823,7 +823,6 @@ static const struct net_device_ops qec_ops = {
        .ndo_start_xmit         = qe_start_xmit,
        .ndo_set_rx_mode        = qe_set_multicast,
        .ndo_tx_timeout         = qe_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index a2f9b47de1873110f6c2a3037de520105930afc3..5356a7074796caafe0ce30284dc859ab75a61e05 100644 (file)
@@ -159,7 +159,6 @@ static const struct net_device_ops vnet_ops = {
        .ndo_set_mac_address    = sunvnet_set_mac_addr_common,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = sunvnet_tx_timeout_common,
-       .ndo_change_mtu         = sunvnet_change_mtu_common,
        .ndo_start_xmit         = vnet_start_xmit,
        .ndo_select_queue       = vnet_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -202,6 +201,10 @@ static struct vnet *vnet_new(const u64 *local_mac,
                           NETIF_F_HW_CSUM | NETIF_F_SG;
        dev->features = dev->hw_features;
 
+       /* MTU range: 68 - 65535 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = VNET_MAX_MTU;
+
        SET_NETDEV_DEV(dev, &vdev->dev);
 
        err = register_netdev(dev);
index 904a5a12a85d0a8480f65a7f1ea2c109b3bcd8d3..58efe69b7ba7ea6b326d7082e70465ca57e2c24a 100644 (file)
@@ -1583,16 +1583,6 @@ void sunvnet_set_rx_mode_common(struct net_device *dev, struct vnet *vp)
 }
 EXPORT_SYMBOL_GPL(sunvnet_set_rx_mode_common);
 
-int sunvnet_change_mtu_common(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu < 68 || new_mtu > 65535)
-               return -EINVAL;
-
-       dev->mtu = new_mtu;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(sunvnet_change_mtu_common);
-
 int sunvnet_set_mac_addr_common(struct net_device *dev, void *p)
 {
        return -EINVAL;
index bd36528af97213adc2048b8c1e447840e3d52f46..ce5c824128a3698acb31ddbac42555657863b10f 100644 (file)
@@ -15,6 +15,8 @@
 #define        VNET_MINTSO      2048   /* VIO protocol's minimum TSO len */
 #define        VNET_MAXTSO     65535   /* VIO protocol's maximum TSO len */
 
+#define VNET_MAX_MTU   65535
+
 /* VNET packets are sent in buffers with the first 6 bytes skipped
  * so that after the ethernet header the IPv4/IPv6 headers are aligned
  * properly.
@@ -125,7 +127,6 @@ int sunvnet_close_common(struct net_device *dev);
 void sunvnet_set_rx_mode_common(struct net_device *dev, struct vnet *vp);
 int sunvnet_set_mac_addr_common(struct net_device *dev, void *p);
 void sunvnet_tx_timeout_common(struct net_device *dev);
-int sunvnet_change_mtu_common(struct net_device *dev, int new_mtu);
 int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev,
                           struct vnet_port *(*vnet_tx_port)
                           (struct sk_buff *, struct net_device *));
index 5eedac49507789788392d8d570572e1dc445afeb..70533017aaa799f4fbffd05f968b3f41fce33b8f 100644 (file)
@@ -2213,7 +2213,7 @@ static int dwceqos_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 tx_error:
        dwceqos_tx_rollback(lp, &trans);
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        return 0;
 }
 
index 7108c68f16d3e970713e239c88126efde8b95cea..baa3e4a5731c7388c3f97a4e2e7be31a7df60706 100644 (file)
@@ -761,16 +761,6 @@ static int bdx_change_mtu(struct net_device *ndev, int new_mtu)
 {
        ENTER;
 
-       if (new_mtu == ndev->mtu)
-               RET(0);
-
-       /* enforce minimum frame size */
-       if (new_mtu < ETH_ZLEN) {
-               netdev_err(ndev, "mtu %d is less then minimal %d\n",
-                          new_mtu, ETH_ZLEN);
-               RET(-EINVAL);
-       }
-
        ndev->mtu = new_mtu;
        if (netif_running(ndev)) {
                bdx_close(ndev);
@@ -2057,6 +2047,10 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 #ifdef BDX_LLTX
                ndev->features |= NETIF_F_LLTX;
 #endif
+               /* MTU range: 60 - 16384 */
+               ndev->min_mtu = ETH_ZLEN;
+               ndev->max_mtu = BDX_MAX_MTU;
+
                spin_lock_init(&priv->tx_lock);
 
                /*bdx_hw_reset(priv); */
index 709ebd6e28b4a35696f3fad0a23b3446d48afeb3..8e7b4c9abf214174c6ae4d3e8c30cb5b8a03cd28 100644 (file)
@@ -74,6 +74,9 @@
  * ifcontig eth1 txqueuelen 3000 - to change it at runtime */
 #define BDX_NDEV_TXQ_LEN 3000
 
+/* Max MTU for Jumbo Frame mode, per tehutinetworks.net Features FAQ is 16k */
+#define BDX_MAX_MTU    (16 * 1024)
+
 #define FIFO_SIZE  4096
 #define FIFO_EXTRA_SPACE            1024
 
index fa0cfda24fd9caaf44d47812d5b1b13a2af73dcf..c56e7030c44edff69b473ebac1aaa464917f7295 100644 (file)
@@ -1068,7 +1068,6 @@ static const struct net_device_ops cpmac_netdev_ops = {
        .ndo_tx_timeout         = cpmac_tx_timeout,
        .ndo_set_rx_mode        = cpmac_set_multicast_list,
        .ndo_do_ioctl           = cpmac_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 };
index c6cff3d2ff050c33c65416a1c8e6c06c44358936..b1ddf89a19bea4748e1f31755267f1bb8c52019d 100644 (file)
@@ -1883,7 +1883,6 @@ static const struct net_device_ops cpsw_netdev_ops = {
        .ndo_set_mac_address    = cpsw_ndo_set_mac_address,
        .ndo_do_ioctl           = cpsw_ndo_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_tx_timeout         = cpsw_ndo_tx_timeout,
        .ndo_set_rx_mode        = cpsw_ndo_set_rx_mode,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1967,27 +1966,30 @@ static int cpsw_get_ts_info(struct net_device *ndev,
        return 0;
 }
 
-static int cpsw_get_settings(struct net_device *ndev,
-                            struct ethtool_cmd *ecmd)
+static int cpsw_get_link_ksettings(struct net_device *ndev,
+                                  struct ethtool_link_ksettings *ecmd)
 {
        struct cpsw_priv *priv = netdev_priv(ndev);
        struct cpsw_common *cpsw = priv->cpsw;
        int slave_no = cpsw_slave_index(cpsw, priv);
 
        if (cpsw->slaves[slave_no].phy)
-               return phy_ethtool_gset(cpsw->slaves[slave_no].phy, ecmd);
+               return phy_ethtool_ksettings_get(cpsw->slaves[slave_no].phy,
+                                                ecmd);
        else
                return -EOPNOTSUPP;
 }
 
-static int cpsw_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
+static int cpsw_set_link_ksettings(struct net_device *ndev,
+                                  const struct ethtool_link_ksettings *ecmd)
 {
        struct cpsw_priv *priv = netdev_priv(ndev);
        struct cpsw_common *cpsw = priv->cpsw;
        int slave_no = cpsw_slave_index(cpsw, priv);
 
        if (cpsw->slaves[slave_no].phy)
-               return phy_ethtool_sset(cpsw->slaves[slave_no].phy, ecmd);
+               return phy_ethtool_ksettings_set(cpsw->slaves[slave_no].phy,
+                                                ecmd);
        else
                return -EOPNOTSUPP;
 }
@@ -2245,8 +2247,6 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
        .set_msglevel   = cpsw_set_msglevel,
        .get_link       = ethtool_op_get_link,
        .get_ts_info    = cpsw_get_ts_info,
-       .get_settings   = cpsw_get_settings,
-       .set_settings   = cpsw_set_settings,
        .get_coalesce   = cpsw_get_coalesce,
        .set_coalesce   = cpsw_set_coalesce,
        .get_sset_count         = cpsw_get_sset_count,
@@ -2262,6 +2262,8 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
        .complete       = cpsw_ethtool_op_complete,
        .get_channels   = cpsw_get_channels,
        .set_channels   = cpsw_set_channels,
+       .get_link_ksettings     = cpsw_get_link_ksettings,
+       .set_link_ksettings     = cpsw_set_link_ksettings,
 };
 
 static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_common *cpsw,
index 32516661f180bcc1ad7e3bb37a8d130c717290bd..78b4c831f5ad39757bebd9259ed8e259c292bc84 100644 (file)
@@ -1766,21 +1766,6 @@ out:
        return (ret == 0) ? 0 : err;
 }
 
-static int netcp_ndo_change_mtu(struct net_device *ndev, int new_mtu)
-{
-       struct netcp_intf *netcp = netdev_priv(ndev);
-
-       /* MTU < 68 is an error for IPv4 traffic */
-       if ((new_mtu < 68) ||
-           (new_mtu > (NETCP_MAX_FRAME_SIZE - ETH_HLEN - ETH_FCS_LEN))) {
-               dev_err(netcp->ndev_dev, "Invalid mtu size = %d\n", new_mtu);
-               return -EINVAL;
-       }
-
-       ndev->mtu = new_mtu;
-       return 0;
-}
-
 static void netcp_ndo_tx_timeout(struct net_device *ndev)
 {
        struct netcp_intf *netcp = netdev_priv(ndev);
@@ -1886,7 +1871,6 @@ static const struct net_device_ops netcp_netdev_ops = {
        .ndo_start_xmit         = netcp_ndo_start_xmit,
        .ndo_set_rx_mode        = netcp_set_rx_mode,
        .ndo_do_ioctl           = netcp_ndo_ioctl,
-       .ndo_change_mtu         = netcp_ndo_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_vlan_rx_add_vid    = netcp_rx_add_vid,
@@ -1923,6 +1907,10 @@ static int netcp_create_interface(struct netcp_device *netcp_device,
        ndev->hw_features = ndev->features;
        ndev->vlan_features |=  NETIF_F_SG;
 
+       /* MTU range: 68 - 9486 */
+       ndev->min_mtu = ETH_MIN_MTU;
+       ndev->max_mtu = NETCP_MAX_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
+
        netcp = netdev_priv(ndev);
        spin_lock_init(&netcp->lock);
        INIT_LIST_HEAD(&netcp->module_head);
@@ -2070,7 +2058,6 @@ static void netcp_delete_interface(struct netcp_device *netcp_device,
                if (module->release)
                        module->release(intf_modpriv->module_priv);
                list_del(&intf_modpriv->intf_list);
-               kfree(intf_modpriv);
        }
        WARN(!list_empty(&netcp->module_head), "%s interface module list is not empty!\n",
             ndev->name);
@@ -2133,6 +2120,8 @@ static int netcp_probe(struct platform_device *pdev)
                }
        }
 
+       of_node_put(interfaces);
+
        /* Add the device instance to the list */
        list_add_tail(&netcp_device->device_list, &netcp_devices);
 
@@ -2145,6 +2134,8 @@ probe_quit_interface:
                netcp_delete_interface(netcp_device, netcp_intf->ndev);
        }
 
+       of_node_put(interfaces);
+
 probe_quit:
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
@@ -2165,7 +2156,6 @@ static int netcp_remove(struct platform_device *pdev)
                dev_dbg(&pdev->dev, "Removing module \"%s\"\n", module->name);
                module->remove(netcp_device, inst_modpriv->module_priv);
                list_del(&inst_modpriv->inst_list);
-               kfree(inst_modpriv);
        }
 
        /* now that all modules are removed, clean up the interfaces */
index d543298d6750a238162e27b6a8f1ddbe76c05431..48cb04fb7e0ce8fd53504e57531eb2e5d449d222 100644 (file)
@@ -1840,8 +1840,8 @@ static void keystone_get_ethtool_stats(struct net_device *ndev,
        spin_unlock_bh(&gbe_dev->hw_stats_lock);
 }
 
-static int keystone_get_settings(struct net_device *ndev,
-                                struct ethtool_cmd *cmd)
+static int keystone_get_link_ksettings(struct net_device *ndev,
+                                      struct ethtool_link_ksettings *cmd)
 {
        struct netcp_intf *netcp = netdev_priv(ndev);
        struct phy_device *phy = ndev->phydev;
@@ -1858,20 +1858,28 @@ static int keystone_get_settings(struct net_device *ndev,
        if (!gbe_intf->slave)
                return -EINVAL;
 
-       ret = phy_ethtool_gset(phy, cmd);
+       ret = phy_ethtool_ksettings_get(phy, cmd);
        if (!ret)
-               cmd->port = gbe_intf->slave->phy_port_t;
+               cmd->base.port = gbe_intf->slave->phy_port_t;
 
        return ret;
 }
 
-static int keystone_set_settings(struct net_device *ndev,
-                                struct ethtool_cmd *cmd)
+static int keystone_set_link_ksettings(struct net_device *ndev,
+                                      const struct ethtool_link_ksettings *cmd)
 {
        struct netcp_intf *netcp = netdev_priv(ndev);
        struct phy_device *phy = ndev->phydev;
        struct gbe_intf *gbe_intf;
-       u32 features = cmd->advertising & cmd->supported;
+       u8 port = cmd->base.port;
+       u32 advertising, supported;
+       u32 features;
+
+       ethtool_convert_link_mode_to_legacy_u32(&advertising,
+                                               cmd->link_modes.advertising);
+       ethtool_convert_link_mode_to_legacy_u32(&supported,
+                                               cmd->link_modes.supported);
+       features = advertising & supported;
 
        if (!phy)
                return -EINVAL;
@@ -1883,25 +1891,25 @@ static int keystone_set_settings(struct net_device *ndev,
        if (!gbe_intf->slave)
                return -EINVAL;
 
-       if (cmd->port != gbe_intf->slave->phy_port_t) {
-               if ((cmd->port == PORT_TP) && !(features & ADVERTISED_TP))
+       if (port != gbe_intf->slave->phy_port_t) {
+               if ((port == PORT_TP) && !(features & ADVERTISED_TP))
                        return -EINVAL;
 
-               if ((cmd->port == PORT_AUI) && !(features & ADVERTISED_AUI))
+               if ((port == PORT_AUI) && !(features & ADVERTISED_AUI))
                        return -EINVAL;
 
-               if ((cmd->port == PORT_BNC) && !(features & ADVERTISED_BNC))
+               if ((port == PORT_BNC) && !(features & ADVERTISED_BNC))
                        return -EINVAL;
 
-               if ((cmd->port == PORT_MII) && !(features & ADVERTISED_MII))
+               if ((port == PORT_MII) && !(features & ADVERTISED_MII))
                        return -EINVAL;
 
-               if ((cmd->port == PORT_FIBRE) && !(features & ADVERTISED_FIBRE))
+               if ((port == PORT_FIBRE) && !(features & ADVERTISED_FIBRE))
                        return -EINVAL;
        }
 
-       gbe_intf->slave->phy_port_t = cmd->port;
-       return phy_ethtool_sset(phy, cmd);
+       gbe_intf->slave->phy_port_t = port;
+       return phy_ethtool_ksettings_set(phy, cmd);
 }
 
 static const struct ethtool_ops keystone_ethtool_ops = {
@@ -1912,8 +1920,8 @@ static const struct ethtool_ops keystone_ethtool_ops = {
        .get_strings            = keystone_get_stat_strings,
        .get_sset_count         = keystone_get_sset_count,
        .get_ethtool_stats      = keystone_get_ethtool_stats,
-       .get_settings           = keystone_get_settings,
-       .set_settings           = keystone_set_settings,
+       .get_link_ksettings     = keystone_get_link_ksettings,
+       .set_link_ksettings     = keystone_set_link_ksettings,
 };
 
 #define mac_hi(mac)    (((mac)[0] << 0) | ((mac)[1] << 8) |    \
index 6c7ec1ddd475afd2e30254b3b159166b01f8eb0e..c8d53d8c83eeb0fbe4111be7840ac3463da704c5 100644 (file)
@@ -772,7 +772,6 @@ static const struct net_device_ops tlan_netdev_ops = {
        .ndo_get_stats          = tlan_get_stats,
        .ndo_set_rx_mode        = tlan_set_multicast_list,
        .ndo_do_ioctl           = tlan_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 11213a38c7952be27cd032933881df9124ed5ac8..0aaf975bb3470cfdc6fb218058fc2d8f0e87959d 100644 (file)
@@ -59,6 +59,9 @@
 /* Maximum number of packets to handle per "poll". */
 #define TILE_NET_WEIGHT 64
 
+/* Maximum Jumbo Packet MTU */
+#define TILE_JUMBO_MAX_MTU 9000
+
 /* Number of entries in each iqueue. */
 #define IQUEUE_ENTRIES 512
 
@@ -2101,17 +2104,6 @@ static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        return -EOPNOTSUPP;
 }
 
-/* Change the MTU. */
-static int tile_net_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu < 68)
-               return -EINVAL;
-       if (new_mtu > ((jumbo_num != 0) ? 9000 : 1500))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 /* Change the Ethernet address of the NIC.
  *
  * The hypervisor driver does not support changing MAC address.  However,
@@ -2154,7 +2146,6 @@ static const struct net_device_ops tile_net_ops = {
        .ndo_start_xmit = tile_net_tx,
        .ndo_select_queue = tile_net_select_queue,
        .ndo_do_ioctl = tile_net_ioctl,
-       .ndo_change_mtu = tile_net_change_mtu,
        .ndo_tx_timeout = tile_net_tx_timeout,
        .ndo_set_mac_address = tile_net_set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2174,7 +2165,11 @@ static void tile_net_setup(struct net_device *dev)
        ether_setup(dev);
        dev->netdev_ops = &tile_net_ops;
        dev->watchdog_timeo = TILE_NET_TIMEOUT;
-       dev->mtu = 1500;
+
+       /* MTU range: 68 - 1500 or 9000 */
+       dev->mtu = ETH_DATA_LEN;
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = jumbo_num ? TILE_JUMBO_MAX_MTU : ETH_DATA_LEN;
 
        features |= NETIF_F_HW_CSUM;
        features |= NETIF_F_SG;
index 4ef605a9024752d85596c4b1e120148b70a7f561..0a3b7dafa3ba4e14e12b977030f1e93657d622db 100644 (file)
@@ -87,7 +87,7 @@
 /* This should be 1500 if "jumbo" is not set in LIPP. */
 /* This should be at most 10226 (10240 - 14) if "jumbo" is set in LIPP. */
 /* ISSUE: This has not been thoroughly tested (except at 1500). */
-#define TILE_NET_MTU 1500
+#define TILE_NET_MTU ETH_DATA_LEN
 
 /* HACK: Define this to verify incoming packets. */
 /* #define TILE_NET_VERIFY_INGRESS */
@@ -2095,26 +2095,6 @@ static struct rtnl_link_stats64 *tile_net_get_stats64(struct net_device *dev,
 }
 
 
-/*
- * Change the "mtu".
- *
- * The "change_mtu" method is usually not needed.
- * If you need it, it must be like this.
- */
-static int tile_net_change_mtu(struct net_device *dev, int new_mtu)
-{
-       PDEBUG("tile_net_change_mtu()\n");
-
-       /* Check ranges. */
-       if ((new_mtu < 68) || (new_mtu > 1500))
-               return -EINVAL;
-
-       /* Accept the value. */
-       dev->mtu = new_mtu;
-
-       return 0;
-}
-
 
 /*
  * Change the Ethernet Address of the NIC.
@@ -2229,7 +2209,6 @@ static const struct net_device_ops tile_net_ops = {
        .ndo_start_xmit = tile_net_tx,
        .ndo_do_ioctl = tile_net_ioctl,
        .ndo_get_stats64 = tile_net_get_stats64,
-       .ndo_change_mtu = tile_net_change_mtu,
        .ndo_tx_timeout = tile_net_tx_timeout,
        .ndo_set_mac_address = tile_net_set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2252,7 +2231,11 @@ static void tile_net_setup(struct net_device *dev)
        dev->netdev_ops = &tile_net_ops;
        dev->watchdog_timeo = TILE_NET_TIMEOUT;
        dev->tx_queue_len = TILE_NET_TX_QUEUE_LEN;
+
+       /* MTU range: 68 - 1500 */
        dev->mtu = TILE_NET_MTU;
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = TILE_NET_MTU;
 
        features |= NETIF_F_HW_CSUM;
        features |= NETIF_F_SG;
index 272f2b1cb7add6bf95da8e9c25794aaf0404d6f1..345316c749e761a168d4364362770f90441e5242 100644 (file)
@@ -1114,24 +1114,6 @@ static int gelic_net_poll(struct napi_struct *napi, int budget)
        }
        return packets_done;
 }
-/**
- * gelic_net_change_mtu - changes the MTU of an interface
- * @netdev: interface device structure
- * @new_mtu: new MTU value
- *
- * returns 0 on success, <0 on failure
- */
-int gelic_net_change_mtu(struct net_device *netdev, int new_mtu)
-{
-       /* no need to re-alloc skbs or so -- the max mtu is about 2.3k
-        * and mtu is outbound only anyway */
-       if ((new_mtu < GELIC_NET_MIN_MTU) ||
-           (new_mtu > GELIC_NET_MAX_MTU)) {
-               return -EINVAL;
-       }
-       netdev->mtu = new_mtu;
-       return 0;
-}
 
 /**
  * gelic_card_interrupt - event handler for gelic_net
@@ -1446,7 +1428,6 @@ static const struct net_device_ops gelic_netdevice_ops = {
        .ndo_stop = gelic_net_stop,
        .ndo_start_xmit = gelic_net_xmit,
        .ndo_set_rx_mode = gelic_net_set_multi,
-       .ndo_change_mtu = gelic_net_change_mtu,
        .ndo_tx_timeout = gelic_net_tx_timeout,
        .ndo_set_mac_address = eth_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
@@ -1513,6 +1494,10 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
                netdev->features |= NETIF_F_VLAN_CHALLENGED;
        }
 
+       /* MTU range: 64 - 1518 */
+       netdev->min_mtu = GELIC_NET_MIN_MTU;
+       netdev->max_mtu = GELIC_NET_MAX_MTU;
+
        status = register_netdev(netdev);
        if (status) {
                dev_err(ctodev(card), "%s:Couldn't register %s %d\n",
index 8505196be9f52bd7a982ec9dcb91f850379cfd07..003d0452d9cb157b1b7b2418341d2b9099342ceb 100644 (file)
@@ -373,7 +373,6 @@ int gelic_net_stop(struct net_device *netdev);
 int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev);
 void gelic_net_set_multi(struct net_device *netdev);
 void gelic_net_tx_timeout(struct net_device *netdev);
-int gelic_net_change_mtu(struct net_device *netdev, int new_mtu);
 int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card);
 
 /* shared ethtool ops */
index 446ea580ad42ff308b2c6fd305c86a25ff4057c3..b3abd02dc94925c865f56f739e90fb54eb886e88 100644 (file)
@@ -2558,7 +2558,6 @@ static const struct net_device_ops gelic_wl_netdevice_ops = {
        .ndo_stop = gelic_wl_stop,
        .ndo_start_xmit = gelic_net_xmit,
        .ndo_set_rx_mode = gelic_net_set_multi,
-       .ndo_change_mtu = gelic_net_change_mtu,
        .ndo_tx_timeout = gelic_net_tx_timeout,
        .ndo_set_mac_address = eth_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
index 36a6e8b54d9415d65bf1b6d2804a53949372eaa6..cb341dfe65ad562d78ad9ac4ad0bade83e2bffb2 100644 (file)
@@ -1278,25 +1278,6 @@ static int spider_net_poll(struct napi_struct *napi, int budget)
        return packets_done;
 }
 
-/**
- * spider_net_change_mtu - changes the MTU of an interface
- * @netdev: interface device structure
- * @new_mtu: new MTU value
- *
- * returns 0 on success, <0 on failure
- */
-static int
-spider_net_change_mtu(struct net_device *netdev, int new_mtu)
-{
-       /* no need to re-alloc skbs or so -- the max mtu is about 2.3k
-        * and mtu is outbound only anyway */
-       if ( (new_mtu < SPIDER_NET_MIN_MTU ) ||
-               (new_mtu > SPIDER_NET_MAX_MTU) )
-               return -EINVAL;
-       netdev->mtu = new_mtu;
-       return 0;
-}
-
 /**
  * spider_net_set_mac - sets the MAC of an interface
  * @netdev: interface device structure
@@ -2229,7 +2210,6 @@ static const struct net_device_ops spider_net_ops = {
        .ndo_start_xmit         = spider_net_xmit,
        .ndo_set_rx_mode        = spider_net_set_multi,
        .ndo_set_mac_address    = spider_net_set_mac,
-       .ndo_change_mtu         = spider_net_change_mtu,
        .ndo_do_ioctl           = spider_net_do_ioctl,
        .ndo_tx_timeout         = spider_net_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
@@ -2299,6 +2279,10 @@ spider_net_setup_netdev(struct spider_net_card *card)
        /* some time: NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
         *              NETIF_F_HW_VLAN_CTAG_FILTER */
 
+       /* MTU range: 64 - 2294 */
+       netdev->min_mtu = SPIDER_NET_MIN_MTU;
+       netdev->max_mtu = SPIDER_NET_MAX_MTU;
+
        netdev->irq = card->pdev->irq;
        card->num_rx_ints = 0;
        card->ignore_rx_ramfull = 0;
index 5b01b3fa9fec966b7bf562e935b6b8216ba9f368..3be61ed28741ae7d763322c7d28c81cc69f2eeb5 100644 (file)
@@ -747,7 +747,6 @@ static const struct net_device_ops tc35815_netdev_ops = {
        .ndo_tx_timeout         = tc35815_tx_timeout,
        .ndo_do_ioctl           = tc35815_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = tc35815_poll_controller,
index 8fd131207ee106b8c198ed607473947cedc851c1..f153ad729ce5b20cefe8c98ffb6f82761062d935 100644 (file)
@@ -1548,7 +1548,6 @@ static const struct net_device_ops tsi108_netdev_ops = {
        .ndo_do_ioctl           = tsi108_do_ioctl,
        .ndo_set_mac_address    = tsi108_set_mac,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int
index 9d14731cdcb10ff28d839694ba7b3113d505708a..ba5c5424905512074f86fa52145d806813a6ea1b 100644 (file)
@@ -890,7 +890,6 @@ static const struct net_device_ops rhine_netdev_ops = {
        .ndo_start_xmit          = rhine_start_tx,
        .ndo_get_stats64         = rhine_get_stats64,
        .ndo_set_rx_mode         = rhine_set_rx_mode,
-       .ndo_change_mtu          = eth_change_mtu,
        .ndo_validate_addr       = eth_validate_addr,
        .ndo_set_mac_address     = eth_mac_addr,
        .ndo_do_ioctl            = netdev_ioctl,
index 908e72e18ef7189e64fd99524d88798a8f60a1a5..4716e60e2ccbbc7c9aae9c168638a70c07ed2c1e 100644 (file)
@@ -2284,13 +2284,6 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
        struct velocity_info *vptr = netdev_priv(dev);
        int ret = 0;
 
-       if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) {
-               VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n",
-                               vptr->netdev->name);
-               ret = -EINVAL;
-               goto out_0;
-       }
-
        if (!netif_running(dev)) {
                dev->mtu = new_mtu;
                goto out_0;
@@ -2864,6 +2857,10 @@ static int velocity_probe(struct device *dev, int irq,
                        NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX |
                        NETIF_F_IP_CSUM;
 
+       /* MTU range: 64 - 9000 */
+       netdev->min_mtu = VELOCITY_MIN_MTU;
+       netdev->max_mtu = VELOCITY_MAX_MTU;
+
        ret = register_netdev(netdev);
        if (ret < 0)
                goto err_iounmap;
index d2349a1bc6baeec283c5df070cbf0d4b49f0b5e3..e1296ef2cf66183d7c8596184c69f122f7d54331 100644 (file)
@@ -1045,7 +1045,6 @@ static const struct net_device_ops w5100_netdev_ops = {
        .ndo_set_rx_mode        = w5100_set_rx_mode,
        .ndo_set_mac_address    = w5100_set_macaddr,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int w5100_mmio_probe(struct platform_device *pdev)
index ca31a57dbc862de2e99f351a3e110b7426e2d94e..724fabd38a23edd6473cdf7ab712c0c54e4a0e7e 100644 (file)
@@ -536,7 +536,6 @@ static const struct net_device_ops w5300_netdev_ops = {
        .ndo_set_rx_mode        = w5300_set_rx_mode,
        .ndo_set_mac_address    = w5300_set_macaddr,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static int w5300_hw_probe(struct platform_device *pdev)
index c688d68c39aaa75c832b2c4bb949f2676dd23aa8..c9c8a3be9f1ba9c045c49b0b1365a2655d467701 100644 (file)
@@ -1034,9 +1034,6 @@ static int axienet_change_mtu(struct net_device *ndev, int new_mtu)
                XAE_TRL_SIZE) > lp->rxmem)
                return -EINVAL;
 
-       if ((new_mtu > XAE_JUMBO_MTU) || (new_mtu < 64))
-               return -EINVAL;
-
        ndev->mtu = new_mtu;
 
        return 0;
@@ -1475,6 +1472,10 @@ static int axienet_probe(struct platform_device *pdev)
        ndev->netdev_ops = &axienet_netdev_ops;
        ndev->ethtool_ops = &axienet_ethtool_ops;
 
+       /* MTU range: 64 - 9000 */
+       ndev->min_mtu = 64;
+       ndev->max_mtu = XAE_JUMBO_MTU;
+
        lp = netdev_priv(ndev);
        lp->ndev = ndev;
        lp->dev = &pdev->dev;
index ddced28e824799679332c36bbcb7b1c26e83bbec..3b08ec766076aa46de255a826468f5fe2ac4a3fb 100644 (file)
@@ -466,7 +466,6 @@ static const struct net_device_ops netdev_ops = {
        .ndo_set_config         = do_config,
        .ndo_do_ioctl           = do_ioctl,
        .ndo_set_rx_mode        = set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 7f127dc1b7baa03b76ffaac0f2cf6dfc9e8164b5..46cc33b9e9263c572cb34b05ec17f8ab021eb648 100644 (file)
@@ -1379,7 +1379,6 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
        .ndo_start_xmit = eth_xmit,
        .ndo_set_rx_mode = eth_set_mcast_list,
        .ndo_do_ioctl = eth_ioctl,
-       .ndo_change_mtu = eth_change_mtu,
        .ndo_set_mac_address = eth_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
 };
index 51acc6d86e910fa657eb0720f57dcc896a1a0cde..3a639180e4a016bb003da2c3417d58f61f797635 100644 (file)
@@ -166,7 +166,6 @@ static const struct net_device_ops skfp_netdev_ops = {
        .ndo_stop               = skfp_close,
        .ndo_start_xmit         = skfp_send_pkt,
        .ndo_get_stats          = skfp_ctl_get_stats,
-       .ndo_change_mtu         = fddi_change_mtu,
        .ndo_set_rx_mode        = skfp_ctl_set_multicast_list,
        .ndo_set_mac_address    = skfp_ctl_set_mac_address,
        .ndo_do_ioctl           = skfp_ioctl,
index 523e3d7cf7aa47cc42e34aecf461d99995625ff8..bc47b354c104df0c631d852d70b988002bcbbf08 100644 (file)
@@ -27,4 +27,4 @@
 
 obj-$(CONFIG_FUJITSU_ES) += fjes.o
 
-fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o
+fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o fjes_trace.o fjes_debugfs.o
index a592fe21c698fe7f9c8dfcd536d55d18f769acda..0372be3ad8e3756535e6dea6c6a299ae3d3d691a 100644 (file)
@@ -66,6 +66,10 @@ struct fjes_adapter {
        bool interrupt_watch_enable;
 
        struct fjes_hw hw;
+
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *dbg_adapter;
+#endif
 };
 
 extern char fjes_driver_name[];
@@ -74,4 +78,16 @@ extern const u32 fjes_support_mtu[];
 
 void fjes_set_ethtool_ops(struct net_device *);
 
+#ifdef CONFIG_DEBUG_FS
+void fjes_dbg_adapter_init(struct fjes_adapter *adapter);
+void fjes_dbg_adapter_exit(struct fjes_adapter *adapter);
+void fjes_dbg_init(void);
+void fjes_dbg_exit(void);
+#else
+static inline void fjes_dbg_adapter_init(struct fjes_adapter *adapter) {}
+static inline void fjes_dbg_adapter_exit(struct fjes_adapter *adapter) {}
+static inline void fjes_dbg_init(void) {}
+static inline void fjes_dbg_exit(void) {}
+#endif /* CONFIG_DEBUG_FS */
+
 #endif /* FJES_H_ */
diff --git a/drivers/net/fjes/fjes_debugfs.c b/drivers/net/fjes/fjes_debugfs.c
new file mode 100644 (file)
index 0000000..30052eb
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  FUJITSU Extended Socket Network Device driver
+ *  Copyright (c) 2015-2016 FUJITSU LIMITED
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+/* debugfs support for fjes driver */
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+
+#include "fjes.h"
+
+static struct dentry *fjes_debug_root;
+
+static const char * const ep_status_string[] = {
+       "unshared",
+       "shared",
+       "waiting",
+       "complete",
+};
+
+static int fjes_dbg_status_show(struct seq_file *m, void *v)
+{
+       struct fjes_adapter *adapter = m->private;
+       struct fjes_hw *hw = &adapter->hw;
+       int max_epid = hw->max_epid;
+       int my_epid = hw->my_epid;
+       int epidx;
+
+       seq_puts(m, "EPID\tSTATUS           SAME_ZONE        CONNECTED\n");
+       for (epidx = 0; epidx < max_epid; epidx++) {
+               if (epidx == my_epid) {
+                       seq_printf(m, "ep%d\t%-16c %-16c %-16c\n",
+                                  epidx, '-', '-', '-');
+               } else {
+                       seq_printf(m, "ep%d\t%-16s %-16c %-16c\n",
+                                  epidx,
+                                  ep_status_string[fjes_hw_get_partner_ep_status(hw, epidx)],
+                                  fjes_hw_epid_is_same_zone(hw, epidx) ? 'Y' : 'N',
+                                  fjes_hw_epid_is_shared(hw->hw_info.share, epidx) ? 'Y' : 'N');
+               }
+       }
+
+       return 0;
+}
+
+static int fjes_dbg_status_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, fjes_dbg_status_show, inode->i_private);
+}
+
+static const struct file_operations fjes_dbg_status_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fjes_dbg_status_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+void fjes_dbg_adapter_init(struct fjes_adapter *adapter)
+{
+       const char *name = dev_name(&adapter->plat_dev->dev);
+       struct dentry *pfile;
+
+       adapter->dbg_adapter = debugfs_create_dir(name, fjes_debug_root);
+       if (!adapter->dbg_adapter) {
+               dev_err(&adapter->plat_dev->dev,
+                       "debugfs entry for %s failed\n", name);
+               return;
+       }
+
+       pfile = debugfs_create_file("status", 0444, adapter->dbg_adapter,
+                                   adapter, &fjes_dbg_status_fops);
+       if (!pfile)
+               dev_err(&adapter->plat_dev->dev,
+                       "debugfs status for %s failed\n", name);
+}
+
+void fjes_dbg_adapter_exit(struct fjes_adapter *adapter)
+{
+       debugfs_remove_recursive(adapter->dbg_adapter);
+       adapter->dbg_adapter = NULL;
+}
+
+void fjes_dbg_init(void)
+{
+       fjes_debug_root = debugfs_create_dir(fjes_driver_name, NULL);
+       if (!fjes_debug_root)
+               pr_info("init of debugfs failed\n");
+}
+
+void fjes_dbg_exit(void)
+{
+       debugfs_remove_recursive(fjes_debug_root);
+       fjes_debug_root = NULL;
+}
+
+#endif /* CONFIG_DEBUG_FS */
index 9c218e140c41ad7a546a6534e38796c34298895b..6575f880f1be52fb9daa91ea7f88eb3199b614f5 100644 (file)
@@ -49,10 +49,18 @@ static const struct fjes_stats fjes_gstrings_stats[] = {
        FJES_STAT("tx_dropped", stats64.tx_dropped),
 };
 
+#define FJES_EP_STATS_LEN 14
+#define FJES_STATS_LEN \
+       (ARRAY_SIZE(fjes_gstrings_stats) + \
+        ((&((struct fjes_adapter *)netdev_priv(netdev))->hw)->max_epid - 1) * \
+        FJES_EP_STATS_LEN)
+
 static void fjes_get_ethtool_stats(struct net_device *netdev,
                                   struct ethtool_stats *stats, u64 *data)
 {
        struct fjes_adapter *adapter = netdev_priv(netdev);
+       struct fjes_hw *hw = &adapter->hw;
+       int epidx;
        char *p;
        int i;
 
@@ -61,11 +69,39 @@ static void fjes_get_ethtool_stats(struct net_device *netdev,
                data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64))
                        ? *(u64 *)p : *(u32 *)p;
        }
+       for (epidx = 0; epidx < hw->max_epid; epidx++) {
+               if (epidx == hw->my_epid)
+                       continue;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats
+                               .com_regist_buf_exec;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats
+                               .com_unregist_buf_exec;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_rx;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_unshare;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats
+                               .send_intr_zoneupdate;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_rx;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_unshare;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_stop;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats
+                               .recv_intr_zoneupdate;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats.tx_buffer_full;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats
+                               .tx_dropped_not_shared;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats
+                               .tx_dropped_ver_mismatch;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats
+                               .tx_dropped_buf_size_mismatch;
+               data[i++] = hw->ep_shm_info[epidx].ep_stats
+                               .tx_dropped_vlanid_mismatch;
+       }
 }
 
 static void fjes_get_strings(struct net_device *netdev,
                             u32 stringset, u8 *data)
 {
+       struct fjes_adapter *adapter = netdev_priv(netdev);
+       struct fjes_hw *hw = &adapter->hw;
        u8 *p = data;
        int i;
 
@@ -76,6 +112,38 @@ static void fjes_get_strings(struct net_device *netdev,
                               ETH_GSTRING_LEN);
                        p += ETH_GSTRING_LEN;
                }
+               for (i = 0; i < hw->max_epid; i++) {
+                       if (i == hw->my_epid)
+                               continue;
+                       sprintf(p, "ep%u_com_regist_buf_exec", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_com_unregist_buf_exec", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_send_intr_rx", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_send_intr_unshare", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_send_intr_zoneupdate", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_recv_intr_rx", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_recv_intr_unshare", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_recv_intr_stop", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_recv_intr_zoneupdate", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_tx_buffer_full", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_tx_dropped_not_shared", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_tx_dropped_ver_mismatch", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_tx_dropped_buf_size_mismatch", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "ep%u_tx_dropped_vlanid_mismatch", i);
+                       p += ETH_GSTRING_LEN;
+               }
                break;
        }
 }
@@ -84,7 +152,7 @@ static int fjes_get_sset_count(struct net_device *netdev, int sset)
 {
        switch (sset) {
        case ETH_SS_STATS:
-               return ARRAY_SIZE(fjes_gstrings_stats);
+               return FJES_STATS_LEN;
        default:
                return -EOPNOTSUPP;
        }
@@ -121,12 +189,123 @@ static int fjes_get_settings(struct net_device *netdev,
        return 0;
 }
 
+static int fjes_get_regs_len(struct net_device *netdev)
+{
+#define FJES_REGS_LEN  37
+       return FJES_REGS_LEN * sizeof(u32);
+}
+
+static void fjes_get_regs(struct net_device *netdev,
+                         struct ethtool_regs *regs, void *p)
+{
+       struct fjes_adapter *adapter = netdev_priv(netdev);
+       struct fjes_hw *hw = &adapter->hw;
+       u32 *regs_buff = p;
+
+       memset(p, 0, FJES_REGS_LEN * sizeof(u32));
+
+       regs->version = 1;
+
+       /* Information registers */
+       regs_buff[0] = rd32(XSCT_OWNER_EPID);
+       regs_buff[1] = rd32(XSCT_MAX_EP);
+
+       /* Device Control registers */
+       regs_buff[4] = rd32(XSCT_DCTL);
+
+       /* Command Control registers */
+       regs_buff[8] = rd32(XSCT_CR);
+       regs_buff[9] = rd32(XSCT_CS);
+       regs_buff[10] = rd32(XSCT_SHSTSAL);
+       regs_buff[11] = rd32(XSCT_SHSTSAH);
+
+       regs_buff[13] = rd32(XSCT_REQBL);
+       regs_buff[14] = rd32(XSCT_REQBAL);
+       regs_buff[15] = rd32(XSCT_REQBAH);
+
+       regs_buff[17] = rd32(XSCT_RESPBL);
+       regs_buff[18] = rd32(XSCT_RESPBAL);
+       regs_buff[19] = rd32(XSCT_RESPBAH);
+
+       /* Interrupt Control registers */
+       regs_buff[32] = rd32(XSCT_IS);
+       regs_buff[33] = rd32(XSCT_IMS);
+       regs_buff[34] = rd32(XSCT_IMC);
+       regs_buff[35] = rd32(XSCT_IG);
+       regs_buff[36] = rd32(XSCT_ICTL);
+}
+
+static int fjes_set_dump(struct net_device *netdev, struct ethtool_dump *dump)
+{
+       struct fjes_adapter *adapter = netdev_priv(netdev);
+       struct fjes_hw *hw = &adapter->hw;
+       int ret = 0;
+
+       if (dump->flag) {
+               if (hw->debug_mode)
+                       return -EPERM;
+
+               hw->debug_mode = dump->flag;
+
+               /* enable debug mode */
+               mutex_lock(&hw->hw_info.lock);
+               ret = fjes_hw_start_debug(hw);
+               mutex_unlock(&hw->hw_info.lock);
+
+               if (ret)
+                       hw->debug_mode = 0;
+       } else {
+               if (!hw->debug_mode)
+                       return -EPERM;
+
+               /* disable debug mode */
+               mutex_lock(&hw->hw_info.lock);
+               ret = fjes_hw_stop_debug(hw);
+               mutex_unlock(&hw->hw_info.lock);
+       }
+
+       return ret;
+}
+
+static int fjes_get_dump_flag(struct net_device *netdev,
+                             struct ethtool_dump *dump)
+{
+       struct fjes_adapter *adapter = netdev_priv(netdev);
+       struct fjes_hw *hw = &adapter->hw;
+
+       dump->len = hw->hw_info.trace_size;
+       dump->version = 1;
+       dump->flag = hw->debug_mode;
+
+       return 0;
+}
+
+static int fjes_get_dump_data(struct net_device *netdev,
+                             struct ethtool_dump *dump, void *buf)
+{
+       struct fjes_adapter *adapter = netdev_priv(netdev);
+       struct fjes_hw *hw = &adapter->hw;
+       int ret = 0;
+
+       if (hw->hw_info.trace)
+               memcpy(buf, hw->hw_info.trace, hw->hw_info.trace_size);
+       else
+               ret = -EPERM;
+
+       return ret;
+}
+
 static const struct ethtool_ops fjes_ethtool_ops = {
                .get_settings           = fjes_get_settings,
                .get_drvinfo            = fjes_get_drvinfo,
                .get_ethtool_stats = fjes_get_ethtool_stats,
                .get_strings      = fjes_get_strings,
                .get_sset_count   = fjes_get_sset_count,
+               .get_regs               = fjes_get_regs,
+               .get_regs_len           = fjes_get_regs_len,
+               .set_dump               = fjes_set_dump,
+               .get_dump_flag          = fjes_get_dump_flag,
+               .get_dump_data          = fjes_get_dump_data,
 };
 
 void fjes_set_ethtool_ops(struct net_device *netdev)
index 0dbafedc0a347efac359a9bddc125448dbf62a27..9c652c04375bf562632fcda5729809186fd22e99 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "fjes_hw.h"
 #include "fjes.h"
+#include "fjes_trace.h"
 
 static void fjes_hw_update_zone_task(struct work_struct *);
 static void fjes_hw_epstop_task(struct work_struct *);
@@ -342,6 +343,9 @@ int fjes_hw_init(struct fjes_hw *hw)
 
        ret = fjes_hw_setup(hw);
 
+       hw->hw_info.trace = vzalloc(FJES_DEBUG_BUFFER_SIZE);
+       hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
+
        return ret;
 }
 
@@ -350,6 +354,18 @@ void fjes_hw_exit(struct fjes_hw *hw)
        int ret;
 
        if (hw->base) {
+
+               if (hw->debug_mode) {
+                       /* disable debug mode */
+                       mutex_lock(&hw->hw_info.lock);
+                       fjes_hw_stop_debug(hw);
+                       mutex_unlock(&hw->hw_info.lock);
+               }
+               vfree(hw->hw_info.trace);
+               hw->hw_info.trace = NULL;
+               hw->hw_info.trace_size = 0;
+               hw->debug_mode = 0;
+
                ret = fjes_hw_reset(hw);
                if (ret)
                        pr_err("%s: reset error", __func__);
@@ -371,7 +387,7 @@ fjes_hw_issue_request_command(struct fjes_hw *hw,
        enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
        union REG_CR cr;
        union REG_CS cs;
-       int timeout;
+       int timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
 
        cr.reg = 0;
        cr.bits.req_start = 1;
@@ -408,6 +424,8 @@ fjes_hw_issue_request_command(struct fjes_hw *hw,
                }
        }
 
+       trace_fjes_hw_issue_request_command(&cr, &cs, timeout, ret);
+
        return ret;
 }
 
@@ -427,11 +445,13 @@ int fjes_hw_request_info(struct fjes_hw *hw)
        res_buf->info.code = 0;
 
        ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
+       trace_fjes_hw_request_info(hw, res_buf);
 
        result = 0;
 
        if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw->hw_info.max_epid)) !=
                res_buf->info.length) {
+               trace_fjes_hw_request_info_err("Invalid res_buf");
                result = -ENOMSG;
        } else if (ret == FJES_CMD_STATUS_NORMAL) {
                switch (res_buf->info.code) {
@@ -448,6 +468,7 @@ int fjes_hw_request_info(struct fjes_hw *hw)
                        result = -EPERM;
                        break;
                case FJES_CMD_STATUS_TIMEOUT:
+                       trace_fjes_hw_request_info_err("Timeout");
                        result = -EBUSY;
                        break;
                case FJES_CMD_STATUS_ERROR_PARAM:
@@ -512,6 +533,8 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
        res_buf->share_buffer.length = 0;
        res_buf->share_buffer.code = 0;
 
+       trace_fjes_hw_register_buff_addr_req(req_buf, buf_pair);
+
        ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
 
        timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
@@ -532,16 +555,20 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
 
        result = 0;
 
+       trace_fjes_hw_register_buff_addr(res_buf, timeout);
+
        if (res_buf->share_buffer.length !=
-                       FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN)
+                       FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) {
+               trace_fjes_hw_register_buff_addr_err("Invalid res_buf");
                result = -ENOMSG;
-       else if (ret == FJES_CMD_STATUS_NORMAL) {
+       else if (ret == FJES_CMD_STATUS_NORMAL) {
                switch (res_buf->share_buffer.code) {
                case FJES_CMD_REQ_RES_CODE_NORMAL:
                        result = 0;
                        set_bit(dest_epid, &hw->hw_info.buffer_share_bit);
                        break;
                case FJES_CMD_REQ_RES_CODE_BUSY:
+                       trace_fjes_hw_register_buff_addr_err("Busy Timeout");
                        result = -EBUSY;
                        break;
                default:
@@ -554,6 +581,7 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
                        result = -EPERM;
                        break;
                case FJES_CMD_STATUS_TIMEOUT:
+                       trace_fjes_hw_register_buff_addr_err("Timeout");
                        result = -EBUSY;
                        break;
                case FJES_CMD_STATUS_ERROR_PARAM:
@@ -595,6 +623,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
        res_buf->unshare_buffer.length = 0;
        res_buf->unshare_buffer.code = 0;
 
+       trace_fjes_hw_unregister_buff_addr_req(req_buf);
        ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
 
        timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
@@ -616,8 +645,11 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
 
        result = 0;
 
+       trace_fjes_hw_unregister_buff_addr(res_buf, timeout);
+
        if (res_buf->unshare_buffer.length !=
                        FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN) {
+               trace_fjes_hw_unregister_buff_addr_err("Invalid res_buf");
                result = -ENOMSG;
        } else if (ret == FJES_CMD_STATUS_NORMAL) {
                switch (res_buf->unshare_buffer.code) {
@@ -626,6 +658,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
                        clear_bit(dest_epid, &hw->hw_info.buffer_share_bit);
                        break;
                case FJES_CMD_REQ_RES_CODE_BUSY:
+                       trace_fjes_hw_unregister_buff_addr_err("Busy Timeout");
                        result = -EBUSY;
                        break;
                default:
@@ -638,6 +671,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
                        result = -EPERM;
                        break;
                case FJES_CMD_STATUS_TIMEOUT:
+                       trace_fjes_hw_unregister_buff_addr_err("Timeout");
                        result = -EBUSY;
                        break;
                case FJES_CMD_STATUS_ERROR_PARAM:
@@ -752,6 +786,7 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw)
                case EP_PARTNER_SHARED:
                        fjes_hw_raise_interrupt(hw, epidx,
                                                REG_ICTL_MASK_TXRX_STOP_REQ);
+                       hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
                        break;
                default:
                        break;
@@ -1062,6 +1097,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
                                break;
                        }
                        mutex_unlock(&hw->hw_info.lock);
+
+                       hw->ep_shm_info[epidx].ep_stats
+                                             .com_regist_buf_exec += 1;
                }
 
                if (test_bit(epidx, &unshare_bit)) {
@@ -1085,6 +1123,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
 
                        mutex_unlock(&hw->hw_info.lock);
 
+                       hw->ep_shm_info[epidx].ep_stats
+                                             .com_unregist_buf_exec += 1;
+
                        if (ret == 0) {
                                spin_lock_irqsave(&hw->rx_status_lock, flags);
                                fjes_hw_setup_epbuf(
@@ -1099,6 +1140,8 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
                        fjes_hw_raise_interrupt(hw, epidx,
                                                REG_ICTL_MASK_TXRX_STOP_REQ);
 
+                       hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
+
                        set_bit(epidx, &hw->txrx_stop_req_bit);
                        spin_lock_irqsave(&hw->rx_status_lock, flags);
                        hw->ep_shm_info[epidx].tx.
@@ -1147,3 +1190,125 @@ static void fjes_hw_epstop_task(struct work_struct *work)
                }
        }
 }
+
+int fjes_hw_start_debug(struct fjes_hw *hw)
+{
+       union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
+       union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
+       enum fjes_dev_command_response_e ret;
+       int page_count;
+       int result = 0;
+       void *addr;
+       int i;
+
+       if (!hw->hw_info.trace)
+               return -EPERM;
+       memset(hw->hw_info.trace, 0, FJES_DEBUG_BUFFER_SIZE);
+
+       memset(req_buf, 0, hw->hw_info.req_buf_size);
+       memset(res_buf, 0, hw->hw_info.res_buf_size);
+
+       req_buf->start_trace.length =
+               FJES_DEV_COMMAND_START_DBG_REQ_LEN(hw->hw_info.trace_size);
+       req_buf->start_trace.mode = hw->debug_mode;
+       req_buf->start_trace.buffer_len = hw->hw_info.trace_size;
+       page_count = hw->hw_info.trace_size / FJES_DEBUG_PAGE_SIZE;
+       for (i = 0; i < page_count; i++) {
+               addr = ((u8 *)hw->hw_info.trace) + i * FJES_DEBUG_PAGE_SIZE;
+               req_buf->start_trace.buffer[i] =
+                       (__le64)(page_to_phys(vmalloc_to_page(addr)) +
+                       offset_in_page(addr));
+       }
+
+       res_buf->start_trace.length = 0;
+       res_buf->start_trace.code = 0;
+
+       trace_fjes_hw_start_debug_req(req_buf);
+       ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_START_DEBUG);
+       trace_fjes_hw_start_debug(res_buf);
+
+       if (res_buf->start_trace.length !=
+               FJES_DEV_COMMAND_START_DBG_RES_LEN) {
+               result = -ENOMSG;
+               trace_fjes_hw_start_debug_err("Invalid res_buf");
+       } else if (ret == FJES_CMD_STATUS_NORMAL) {
+               switch (res_buf->start_trace.code) {
+               case FJES_CMD_REQ_RES_CODE_NORMAL:
+                       result = 0;
+                       break;
+               default:
+                       result = -EPERM;
+                       break;
+               }
+       } else {
+               switch (ret) {
+               case FJES_CMD_STATUS_UNKNOWN:
+                       result = -EPERM;
+                       break;
+               case FJES_CMD_STATUS_TIMEOUT:
+                       trace_fjes_hw_start_debug_err("Busy Timeout");
+                       result = -EBUSY;
+                       break;
+               case FJES_CMD_STATUS_ERROR_PARAM:
+               case FJES_CMD_STATUS_ERROR_STATUS:
+               default:
+                       result = -EPERM;
+                       break;
+               }
+       }
+
+       return result;
+}
+
+int fjes_hw_stop_debug(struct fjes_hw *hw)
+{
+       union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
+       union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
+       enum fjes_dev_command_response_e ret;
+       int result = 0;
+
+       if (!hw->hw_info.trace)
+               return -EPERM;
+
+       memset(req_buf, 0, hw->hw_info.req_buf_size);
+       memset(res_buf, 0, hw->hw_info.res_buf_size);
+       req_buf->stop_trace.length = FJES_DEV_COMMAND_STOP_DBG_REQ_LEN;
+
+       res_buf->stop_trace.length = 0;
+       res_buf->stop_trace.code = 0;
+
+       ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_STOP_DEBUG);
+       trace_fjes_hw_stop_debug(res_buf);
+
+       if (res_buf->stop_trace.length != FJES_DEV_COMMAND_STOP_DBG_RES_LEN) {
+               trace_fjes_hw_stop_debug_err("Invalid res_buf");
+               result = -ENOMSG;
+       } else if (ret == FJES_CMD_STATUS_NORMAL) {
+               switch (res_buf->stop_trace.code) {
+               case FJES_CMD_REQ_RES_CODE_NORMAL:
+                       result = 0;
+                       hw->debug_mode = 0;
+                       break;
+               default:
+                       result = -EPERM;
+                       break;
+               }
+       } else {
+               switch (ret) {
+               case FJES_CMD_STATUS_UNKNOWN:
+                       result = -EPERM;
+                       break;
+               case FJES_CMD_STATUS_TIMEOUT:
+                       result = -EBUSY;
+                       trace_fjes_hw_stop_debug_err("Busy Timeout");
+                       break;
+               case FJES_CMD_STATUS_ERROR_PARAM:
+               case FJES_CMD_STATUS_ERROR_STATUS:
+               default:
+                       result = -EPERM;
+                       break;
+               }
+       }
+
+       return result;
+}
index 1445ac99d6e316da52f3534b67be34f53f0e30d7..3a6da0996a0e6d3b9b9804a997082bb42d9fb41f 100644 (file)
@@ -33,6 +33,9 @@ struct fjes_hw;
 #define EP_BUFFER_SUPPORT_VLAN_MAX 4
 #define EP_BUFFER_INFO_SIZE 4096
 
+#define FJES_DEBUG_PAGE_SIZE 4096
+#define FJES_DEBUG_BUFFER_SIZE (16 * FJES_DEBUG_PAGE_SIZE)
+
 #define FJES_DEVICE_RESET_TIMEOUT  ((17 + 1) * 3 * 8) /* sec */
 #define FJES_COMMAND_REQ_TIMEOUT  ((5 + 1) * 3 * 8) /* sec */
 #define FJES_COMMAND_REQ_BUFF_TIMEOUT  (60 * 3) /* sec */
@@ -94,6 +97,12 @@ struct fjes_hw;
 #define FJES_DEV_RES_BUF_SIZE(maxep) \
        FJES_DEV_COMMAND_INFO_RES_LEN(maxep)
 
+#define FJES_DEV_COMMAND_START_DBG_REQ_LEN(byte) \
+       (16 + (8 * (byte) / FJES_DEBUG_PAGE_SIZE))
+#define FJES_DEV_COMMAND_START_DBG_RES_LEN (8)
+#define FJES_DEV_COMMAND_STOP_DBG_REQ_LEN (4)
+#define FJES_DEV_COMMAND_STOP_DBG_RES_LEN (8)
+
 /* Frame & MTU */
 struct esmem_frame {
        __le32 frame_size;
@@ -173,6 +182,8 @@ enum fjes_dev_command_request_type {
        FJES_CMD_REQ_INFO               = 0x0001,
        FJES_CMD_REQ_SHARE_BUFFER       = 0x0002,
        FJES_CMD_REQ_UNSHARE_BUFFER     = 0x0004,
+       FJES_CMD_REQ_START_DEBUG        = 0x0100,
+       FJES_CMD_REQ_STOP_DEBUG         = 0x0200,
 };
 
 /* parameter for command control */
@@ -228,6 +239,24 @@ union ep_buffer_info {
 
 };
 
+/* statistics of EP */
+struct fjes_drv_ep_stats {
+       u64 com_regist_buf_exec;
+       u64 com_unregist_buf_exec;
+       u64 send_intr_rx;
+       u64 send_intr_unshare;
+       u64 send_intr_zoneupdate;
+       u64 recv_intr_rx;
+       u64 recv_intr_unshare;
+       u64 recv_intr_stop;
+       u64 recv_intr_zoneupdate;
+       u64 tx_buffer_full;
+       u64 tx_dropped_not_shared;
+       u64 tx_dropped_ver_mismatch;
+       u64 tx_dropped_buf_size_mismatch;
+       u64 tx_dropped_vlanid_mismatch;
+};
+
 /* buffer pair for Extended Partition */
 struct ep_share_mem_info {
        struct epbuf_handler {
@@ -238,6 +267,7 @@ struct ep_share_mem_info {
        } tx, rx;
 
        struct rtnl_link_stats64 net_stats;
+       struct fjes_drv_ep_stats ep_stats;
 
        u16 tx_status_work;
 
@@ -302,6 +332,8 @@ struct fjes_hw {
        struct fjes_hw_info hw_info;
 
        spinlock_t rx_status_lock; /* spinlock for rx_status */
+
+       u32 debug_mode;
 };
 
 int fjes_hw_init(struct fjes_hw *);
@@ -334,4 +366,6 @@ void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *, size_t *);
 void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *);
 int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t);
 
+int fjes_hw_start_debug(struct fjes_hw *);
+int fjes_hw_stop_debug(struct fjes_hw *);
 #endif /* FJES_HW_H_ */
index e46b1ebbbff4d88312510e42fc5e279c54ed34a4..b77e4ecf3cf2f5836bfe35c5686ef188859fd9d0 100644 (file)
 #include <linux/interrupt.h>
 
 #include "fjes.h"
+#include "fjes_trace.h"
 
 #define MAJ 1
-#define MIN 1
+#define MIN 2
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
 #define DRV_NAME       "fjes"
 char fjes_driver_name[] = DRV_NAME;
@@ -366,6 +367,8 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
                     FJES_ZONING_STATUS_ENABLE)) {
                        fjes_hw_raise_interrupt(hw, epidx,
                                                REG_ICTL_MASK_INFO_UPDATE);
+                       hw->ep_shm_info[epidx].ep_stats
+                               .send_intr_zoneupdate += 1;
                }
        }
 
@@ -397,6 +400,9 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
                                adapter->force_reset = true;
                                return result;
                        }
+
+                       hw->ep_shm_info[epidx].ep_stats
+                               .com_regist_buf_exec += 1;
                }
        }
 
@@ -422,6 +428,8 @@ static void fjes_free_resources(struct fjes_adapter *adapter)
                result = fjes_hw_unregister_buff_addr(hw, epidx);
                mutex_unlock(&hw->hw_info.lock);
 
+               hw->ep_shm_info[epidx].ep_stats.com_unregist_buf_exec += 1;
+
                if (result)
                        reset_flag = true;
 
@@ -567,6 +575,7 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work)
                      FJES_RX_POLL_WORK)) {
                        fjes_hw_raise_interrupt(hw, epid,
                                                REG_ICTL_MASK_RX_DATA);
+                       hw->ep_shm_info[epid].ep_stats.send_intr_rx += 1;
                }
        }
 
@@ -663,6 +672,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
                pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid);
                if (pstatus != EP_PARTNER_SHARED) {
+                       if (!is_multi)
+                               hw->ep_shm_info[dest_epid].ep_stats
+                                       .tx_dropped_not_shared += 1;
                        ret = NETDEV_TX_OK;
                } else if (!fjes_hw_check_epbuf_version(
                                &adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
@@ -670,6 +682,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                        adapter->stats64.tx_carrier_errors += 1;
                        hw->ep_shm_info[dest_epid].net_stats
                                                .tx_carrier_errors += 1;
+                       hw->ep_shm_info[dest_epid].ep_stats
+                                       .tx_dropped_ver_mismatch += 1;
 
                        ret = NETDEV_TX_OK;
                } else if (!fjes_hw_check_mtu(
@@ -679,12 +693,16 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                        hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1;
                        adapter->stats64.tx_errors += 1;
                        hw->ep_shm_info[dest_epid].net_stats.tx_errors += 1;
+                       hw->ep_shm_info[dest_epid].ep_stats
+                                       .tx_dropped_buf_size_mismatch += 1;
 
                        ret = NETDEV_TX_OK;
                } else if (vlan &&
                           !fjes_hw_check_vlan_id(
                                &adapter->hw.ep_shm_info[dest_epid].rx,
                                vlan_id)) {
+                       hw->ep_shm_info[dest_epid].ep_stats
+                               .tx_dropped_vlanid_mismatch += 1;
                        ret = NETDEV_TX_OK;
                } else {
                        if (len < VLAN_ETH_HLEN) {
@@ -718,6 +736,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                                        ret = NETDEV_TX_OK;
                                } else {
                                        netif_trans_update(netdev);
+                                       hw->ep_shm_info[dest_epid].ep_stats
+                                               .tx_buffer_full += 1;
                                        netif_tx_stop_queue(cur_queue);
 
                                        if (!work_pending(&adapter->tx_stall_task))
@@ -885,6 +905,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
        unsigned long flags;
 
        status = fjes_hw_get_partner_ep_status(hw, src_epid);
+       trace_fjes_txrx_stop_req_irq_pre(hw, src_epid, status);
        switch (status) {
        case EP_PARTNER_UNSHARE:
        case EP_PARTNER_COMPLETE:
@@ -915,6 +936,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
                }
                break;
        }
+       trace_fjes_txrx_stop_req_irq_post(hw, src_epid);
 }
 
 static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
@@ -926,6 +948,7 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
        set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit);
 
        status = fjes_hw_get_partner_ep_status(hw, src_epid);
+       trace_fjes_stop_req_irq_pre(hw, src_epid, status);
        switch (status) {
        case EP_PARTNER_WAITING:
                spin_lock_irqsave(&hw->rx_status_lock, flags);
@@ -949,6 +972,7 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
                        queue_work(adapter->control_wq, &hw->epstop_task);
                break;
        }
+       trace_fjes_stop_req_irq_post(hw, src_epid);
 }
 
 static void fjes_update_zone_irq(struct fjes_adapter *adapter,
@@ -970,21 +994,33 @@ static irqreturn_t fjes_intr(int irq, void *data)
        icr = fjes_hw_capture_interrupt_status(hw);
 
        if (icr & REG_IS_MASK_IS_ASSERT) {
-               if (icr & REG_ICTL_MASK_RX_DATA)
+               if (icr & REG_ICTL_MASK_RX_DATA) {
                        fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);
+                       hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
+                               .recv_intr_rx += 1;
+               }
 
-               if (icr & REG_ICTL_MASK_DEV_STOP_REQ)
+               if (icr & REG_ICTL_MASK_DEV_STOP_REQ) {
                        fjes_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
+                       hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
+                               .recv_intr_stop += 1;
+               }
 
-               if (icr & REG_ICTL_MASK_TXRX_STOP_REQ)
+               if (icr & REG_ICTL_MASK_TXRX_STOP_REQ) {
                        fjes_txrx_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
+                       hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
+                               .recv_intr_unshare += 1;
+               }
 
                if (icr & REG_ICTL_MASK_TXRX_STOP_DONE)
                        fjes_hw_set_irqmask(hw,
                                            REG_ICTL_MASK_TXRX_STOP_DONE, true);
 
-               if (icr & REG_ICTL_MASK_INFO_UPDATE)
+               if (icr & REG_ICTL_MASK_INFO_UPDATE) {
                        fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID);
+                       hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
+                               .recv_intr_zoneupdate += 1;
+               }
 
                ret = IRQ_HANDLED;
        } else {
@@ -1221,6 +1257,8 @@ static int fjes_probe(struct platform_device *plat_dev)
 
        netif_carrier_off(netdev);
 
+       fjes_dbg_adapter_init(adapter);
+
        return 0;
 
 err_hw_exit:
@@ -1238,6 +1276,8 @@ static int fjes_remove(struct platform_device *plat_dev)
        struct fjes_adapter *adapter = netdev_priv(netdev);
        struct fjes_hw *hw = &adapter->hw;
 
+       fjes_dbg_adapter_exit(adapter);
+
        cancel_delayed_work_sync(&adapter->interrupt_watch_task);
        cancel_work_sync(&adapter->unshare_watch_task);
        cancel_work_sync(&adapter->raise_intr_rxdata_task);
@@ -1276,6 +1316,8 @@ static void fjes_netdev_setup(struct net_device *netdev)
        netdev->netdev_ops = &fjes_netdev_ops;
        fjes_set_ethtool_ops(netdev);
        netdev->mtu = fjes_support_mtu[3];
+       netdev->min_mtu = fjes_support_mtu[0];
+       netdev->max_mtu = fjes_support_mtu[3];
        netdev->flags |= IFF_BROADCAST;
        netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
 }
@@ -1364,6 +1406,8 @@ static void fjes_watch_unshare_task(struct work_struct *work)
                                break;
                        }
                        mutex_unlock(&hw->hw_info.lock);
+                       hw->ep_shm_info[epidx].ep_stats
+                                       .com_unregist_buf_exec += 1;
 
                        spin_lock_irqsave(&hw->rx_status_lock, flags);
                        fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
@@ -1406,6 +1450,9 @@ static void fjes_watch_unshare_task(struct work_struct *work)
                                }
                                mutex_unlock(&hw->hw_info.lock);
 
+                               hw->ep_shm_info[epidx].ep_stats
+                                       .com_unregist_buf_exec += 1;
+
                                spin_lock_irqsave(&hw->rx_status_lock, flags);
                                fjes_hw_setup_epbuf(
                                        &hw->ep_shm_info[epidx].tx,
@@ -1437,9 +1484,13 @@ static int __init fjes_init_module(void)
        pr_info("%s - version %s - %s\n",
                fjes_driver_string, fjes_driver_version, fjes_copyright);
 
+       fjes_dbg_init();
+
        result = platform_driver_register(&fjes_driver);
-       if (result < 0)
+       if (result < 0) {
+               fjes_dbg_exit();
                return result;
+       }
 
        result = acpi_bus_register_driver(&fjes_acpi_driver);
        if (result < 0)
@@ -1449,6 +1500,7 @@ static int __init fjes_init_module(void)
 
 fail_acpi_driver:
        platform_driver_unregister(&fjes_driver);
+       fjes_dbg_exit();
        return result;
 }
 
@@ -1459,6 +1511,7 @@ static void __exit fjes_exit_module(void)
 {
        acpi_bus_unregister_driver(&fjes_acpi_driver);
        platform_driver_unregister(&fjes_driver);
+       fjes_dbg_exit();
 }
 
 module_exit(fjes_exit_module);
diff --git a/drivers/net/fjes/fjes_trace.c b/drivers/net/fjes/fjes_trace.c
new file mode 100644 (file)
index 0000000..066fa76
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  FUJITSU Extended Socket Network Device driver
+ *  Copyright (c) 2015-2016 FUJITSU LIMITED
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+#include <linux/module.h>
+
+#ifndef __CHECKER__
+#include "fjes_hw.h"
+
+#define CREATE_TRACE_POINTS
+#include "fjes_trace.h"
+
+#endif /* __CHECKER__ */
diff --git a/drivers/net/fjes/fjes_trace.h b/drivers/net/fjes/fjes_trace.h
new file mode 100644 (file)
index 0000000..cca01a1
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ *  FUJITSU Extended Socket Network Device driver
+ *  Copyright (c) 2015-2016 FUJITSU LIMITED
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+#if !defined(FJES_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define FJES_TRACE_H_
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM fjes
+
+/* tracepoints for fjes_hw.c */
+
+TRACE_EVENT(fjes_hw_issue_request_command,
+       TP_PROTO(union REG_CR *cr, union REG_CS *cs, int timeout,
+                enum fjes_dev_command_response_e ret),
+       TP_ARGS(cr, cs, timeout, ret),
+       TP_STRUCT__entry(
+               __field(u16, cr_req)
+               __field(u8, cr_error)
+               __field(u16, cr_err_info)
+               __field(u8, cr_req_start)
+               __field(u16, cs_req)
+               __field(u8, cs_busy)
+               __field(u8, cs_complete)
+               __field(int, timeout)
+               __field(int, ret);
+       ),
+       TP_fast_assign(
+               __entry->cr_req = cr->bits.req_code;
+               __entry->cr_error = cr->bits.error;
+               __entry->cr_err_info = cr->bits.err_info;
+               __entry->cr_req_start = cr->bits.req_start;
+               __entry->cs_req = cs->bits.req_code;
+               __entry->cs_busy = cs->bits.busy;
+               __entry->cs_complete = cs->bits.complete;
+               __entry->timeout = timeout;
+               __entry->ret = ret;
+       ),
+       TP_printk("CR=[req=%04x, error=%u, err_info=%04x, req_start=%u], CS=[req=%04x, busy=%u, complete=%u], timeout=%d, ret=%d",
+                 __entry->cr_req, __entry->cr_error, __entry->cr_err_info,
+                 __entry->cr_req_start, __entry->cs_req, __entry->cs_busy,
+                 __entry->cs_complete, __entry->timeout, __entry->ret)
+);
+
+TRACE_EVENT(fjes_hw_request_info,
+       TP_PROTO(struct fjes_hw *hw, union fjes_device_command_res *res_buf),
+       TP_ARGS(hw, res_buf),
+       TP_STRUCT__entry(
+               __field(int, length)
+               __field(int, code)
+               __dynamic_array(u8, zone, hw->max_epid)
+               __dynamic_array(u8, status, hw->max_epid)
+       ),
+       TP_fast_assign(
+               int x;
+
+               __entry->length = res_buf->info.length;
+               __entry->code = res_buf->info.code;
+               for (x = 0; x < hw->max_epid; x++) {
+                       *((u8 *)__get_dynamic_array(zone) + x) =
+                                       res_buf->info.info[x].zone;
+                       *((u8 *)__get_dynamic_array(status) + x) =
+                                       res_buf->info.info[x].es_status;
+               }
+       ),
+       TP_printk("res_buf=[length=%d, code=%d, es_zones=%s, es_status=%s]",
+                 __entry->length, __entry->code,
+                 __print_array(__get_dynamic_array(zone),
+                               __get_dynamic_array_len(zone) / sizeof(u8),
+                               sizeof(u8)),
+                 __print_array(__get_dynamic_array(status),
+                               __get_dynamic_array_len(status) / sizeof(u8),
+                               sizeof(u8)))
+);
+
+TRACE_EVENT(fjes_hw_request_info_err,
+       TP_PROTO(char *err),
+       TP_ARGS(err),
+       TP_STRUCT__entry(
+               __string(err, err)
+       ),
+       TP_fast_assign(
+               __assign_str(err, err);
+       ),
+       TP_printk("%s", __get_str(err))
+);
+
+TRACE_EVENT(fjes_hw_register_buff_addr_req,
+       TP_PROTO(union fjes_device_command_req *req_buf,
+                struct ep_share_mem_info *buf_pair),
+       TP_ARGS(req_buf, buf_pair),
+       TP_STRUCT__entry(
+               __field(int, length)
+               __field(int, epid)
+               __field(u64, tx)
+               __field(size_t, tx_size)
+               __field(u64, rx)
+               __field(size_t, rx_size)
+       ),
+       TP_fast_assign(
+               void *tx, *rx;
+
+               tx = (void *)buf_pair->tx.buffer;
+               rx = (void *)buf_pair->rx.buffer;
+               __entry->length = req_buf->share_buffer.length;
+               __entry->epid = req_buf->share_buffer.epid;
+               __entry->tx_size = buf_pair->tx.size;
+               __entry->rx_size = buf_pair->rx.size;
+               __entry->tx = page_to_phys(vmalloc_to_page(tx)) +
+                               offset_in_page(tx);
+               __entry->rx = page_to_phys(vmalloc_to_page(rx)) +
+                               offset_in_page(rx);
+       ),
+       TP_printk("req_buf=[length=%d, epid=%d], TX=[phy=0x%016llx, size=%zu], RX=[phy=0x%016llx, size=%zu]",
+                 __entry->length, __entry->epid, __entry->tx, __entry->tx_size,
+                 __entry->rx, __entry->rx_size)
+);
+
+TRACE_EVENT(fjes_hw_register_buff_addr,
+       TP_PROTO(union fjes_device_command_res *res_buf, int timeout),
+       TP_ARGS(res_buf, timeout),
+       TP_STRUCT__entry(
+               __field(int, length)
+               __field(int, code)
+               __field(int, timeout)
+       ),
+       TP_fast_assign(
+               __entry->length = res_buf->share_buffer.length;
+               __entry->code = res_buf->share_buffer.code;
+               __entry->timeout = timeout;
+       ),
+       TP_printk("res_buf=[length=%d, code=%d], timeout=%d",
+                 __entry->length, __entry->code, __entry->timeout)
+);
+
+TRACE_EVENT(fjes_hw_register_buff_addr_err,
+       TP_PROTO(char *err),
+       TP_ARGS(err),
+       TP_STRUCT__entry(
+               __string(err, err)
+       ),
+       TP_fast_assign(
+               __assign_str(err, err);
+       ),
+       TP_printk("%s", __get_str(err))
+);
+
+TRACE_EVENT(fjes_hw_unregister_buff_addr_req,
+       TP_PROTO(union fjes_device_command_req *req_buf),
+       TP_ARGS(req_buf),
+       TP_STRUCT__entry(
+               __field(int, length)
+               __field(int, epid)
+       ),
+       TP_fast_assign(
+               __entry->length = req_buf->unshare_buffer.length;
+               __entry->epid = req_buf->unshare_buffer.epid;
+       ),
+       TP_printk("req_buf=[length=%d, epid=%d]",
+                 __entry->length, __entry->epid)
+);
+
+TRACE_EVENT(fjes_hw_unregister_buff_addr,
+       TP_PROTO(union fjes_device_command_res *res_buf, int timeout),
+       TP_ARGS(res_buf, timeout),
+       TP_STRUCT__entry(
+               __field(int, length)
+               __field(int, code)
+               __field(int, timeout)
+       ),
+       TP_fast_assign(
+               __entry->length = res_buf->unshare_buffer.length;
+               __entry->code = res_buf->unshare_buffer.code;
+               __entry->timeout = timeout;
+       ),
+       TP_printk("res_buf=[length=%d, code=%d], timeout=%d",
+                 __entry->length, __entry->code, __entry->timeout)
+);
+
+TRACE_EVENT(fjes_hw_unregister_buff_addr_err,
+       TP_PROTO(char *err),
+       TP_ARGS(err),
+       TP_STRUCT__entry(
+               __string(err, err)
+       ),
+       TP_fast_assign(
+               __assign_str(err, err);
+       ),
+       TP_printk("%s", __get_str(err))
+);
+
+TRACE_EVENT(fjes_hw_start_debug_req,
+       TP_PROTO(union fjes_device_command_req *req_buf),
+       TP_ARGS(req_buf),
+       TP_STRUCT__entry(
+               __field(int, length)
+               __field(int, mode)
+               __field(phys_addr_t, buffer)
+       ),
+       TP_fast_assign(
+               __entry->length = req_buf->start_trace.length;
+               __entry->mode = req_buf->start_trace.mode;
+               __entry->buffer = req_buf->start_trace.buffer[0];
+       ),
+       TP_printk("req_buf=[length=%d, mode=%d, buffer=%pap]",
+                 __entry->length, __entry->mode, &__entry->buffer)
+);
+
+TRACE_EVENT(fjes_hw_start_debug,
+       TP_PROTO(union fjes_device_command_res *res_buf),
+       TP_ARGS(res_buf),
+       TP_STRUCT__entry(
+               __field(int, length)
+               __field(int, code)
+       ),
+       TP_fast_assign(
+               __entry->length = res_buf->start_trace.length;
+               __entry->code = res_buf->start_trace.code;
+       ),
+       TP_printk("res_buf=[length=%d, code=%d]", __entry->length, __entry->code)
+);
+
+TRACE_EVENT(fjes_hw_start_debug_err,
+       TP_PROTO(char *err),
+       TP_ARGS(err),
+       TP_STRUCT__entry(
+                __string(err, err)
+       ),
+       TP_fast_assign(
+               __assign_str(err, err)
+       ),
+       TP_printk("%s", __get_str(err))
+);
+
+TRACE_EVENT(fjes_hw_stop_debug,
+       TP_PROTO(union fjes_device_command_res *res_buf),
+       TP_ARGS(res_buf),
+       TP_STRUCT__entry(
+               __field(int, length)
+               __field(int, code)
+       ),
+       TP_fast_assign(
+               __entry->length = res_buf->stop_trace.length;
+               __entry->code = res_buf->stop_trace.code;
+       ),
+       TP_printk("res_buf=[length=%d, code=%d]", __entry->length, __entry->code)
+);
+
+TRACE_EVENT(fjes_hw_stop_debug_err,
+       TP_PROTO(char *err),
+       TP_ARGS(err),
+       TP_STRUCT__entry(
+                __string(err, err)
+       ),
+       TP_fast_assign(
+               __assign_str(err, err)
+       ),
+       TP_printk("%s", __get_str(err))
+);
+
+/* tracepoints for fjes_main.c */
+
+TRACE_EVENT(fjes_txrx_stop_req_irq_pre,
+       TP_PROTO(struct fjes_hw *hw, int src_epid,
+                enum ep_partner_status status),
+       TP_ARGS(hw, src_epid, status),
+       TP_STRUCT__entry(
+               __field(int, src_epid)
+               __field(enum ep_partner_status, status)
+               __field(u8, ep_status)
+               __field(unsigned long, txrx_stop_req_bit)
+               __field(u16, rx_status)
+       ),
+       TP_fast_assign(
+               __entry->src_epid = src_epid;
+               __entry->status = status;
+               __entry->ep_status = hw->hw_info.share->ep_status[src_epid];
+               __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit;
+               __entry->rx_status =
+                       hw->ep_shm_info[src_epid].tx.info->v1i.rx_status;
+       ),
+       TP_printk("epid=%d, partner_status=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x",
+                 __entry->src_epid, __entry->status, __entry->ep_status,
+                 __entry->txrx_stop_req_bit, __entry->rx_status)
+);
+
+TRACE_EVENT(fjes_txrx_stop_req_irq_post,
+       TP_PROTO(struct fjes_hw *hw, int src_epid),
+       TP_ARGS(hw, src_epid),
+       TP_STRUCT__entry(
+               __field(int, src_epid)
+               __field(u8, ep_status)
+               __field(unsigned long, txrx_stop_req_bit)
+               __field(u16, rx_status)
+       ),
+       TP_fast_assign(
+               __entry->src_epid = src_epid;
+               __entry->ep_status = hw->hw_info.share->ep_status[src_epid];
+               __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit;
+               __entry->rx_status = hw->ep_shm_info[src_epid].tx.info->v1i.rx_status;
+       ),
+       TP_printk("epid=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x",
+                 __entry->src_epid, __entry->ep_status,
+                 __entry->txrx_stop_req_bit, __entry->rx_status)
+);
+
+TRACE_EVENT(fjes_stop_req_irq_pre,
+       TP_PROTO(struct fjes_hw *hw, int src_epid,
+                enum ep_partner_status status),
+       TP_ARGS(hw, src_epid, status),
+       TP_STRUCT__entry(
+               __field(int, src_epid)
+               __field(enum ep_partner_status, status)
+               __field(u8, ep_status)
+               __field(unsigned long, txrx_stop_req_bit)
+               __field(u16, rx_status)
+       ),
+       TP_fast_assign(
+               __entry->src_epid = src_epid;
+               __entry->status = status;
+               __entry->ep_status = hw->hw_info.share->ep_status[src_epid];
+               __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit;
+               __entry->rx_status =
+                       hw->ep_shm_info[src_epid].tx.info->v1i.rx_status;
+       ),
+       TP_printk("epid=%d, partner_status=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x",
+                 __entry->src_epid, __entry->status, __entry->ep_status,
+                 __entry->txrx_stop_req_bit, __entry->rx_status)
+);
+
+TRACE_EVENT(fjes_stop_req_irq_post,
+       TP_PROTO(struct fjes_hw *hw, int src_epid),
+       TP_ARGS(hw, src_epid),
+       TP_STRUCT__entry(
+               __field(int, src_epid)
+               __field(u8, ep_status)
+               __field(unsigned long, txrx_stop_req_bit)
+               __field(u16, rx_status)
+       ),
+       TP_fast_assign(
+               __entry->src_epid = src_epid;
+               __entry->ep_status = hw->hw_info.share->ep_status[src_epid];
+               __entry->txrx_stop_req_bit = hw->txrx_stop_req_bit;
+               __entry->rx_status =
+                       hw->ep_shm_info[src_epid].tx.info->v1i.rx_status;
+       ),
+       TP_printk("epid=%d, ep_status=%x, txrx_stop_req_bit=%016lx, tx.rx_status=%08x",
+                 __entry->src_epid, __entry->ep_status,
+                 __entry->txrx_stop_req_bit, __entry->rx_status)
+);
+
+#endif /* FJES_TRACE_H_ */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH ../../../drivers/net/fjes
+#define TRACE_INCLUDE_FILE fjes_trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 42edd7b7902f16125f860fa37d3b1e45d2a4c1a2..85a423a664784979ed2cc90d11ae4bb22f6b30cd 100644 (file)
@@ -1057,39 +1057,18 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
        return geneve_xmit_skb(skb, dev, info);
 }
 
-static int __geneve_change_mtu(struct net_device *dev, int new_mtu, bool strict)
+static int geneve_change_mtu(struct net_device *dev, int new_mtu)
 {
-       struct geneve_dev *geneve = netdev_priv(dev);
-       /* The max_mtu calculation does not take account of GENEVE
-        * options, to avoid excluding potentially valid
-        * configurations.
+       /* Only possible if called internally, ndo_change_mtu path's new_mtu
+        * is guaranteed to be between dev->min_mtu and dev->max_mtu.
         */
-       int max_mtu = IP_MAX_MTU - GENEVE_BASE_HLEN - dev->hard_header_len;
-
-       if (geneve->remote.sa.sa_family == AF_INET6)
-               max_mtu -= sizeof(struct ipv6hdr);
-       else
-               max_mtu -= sizeof(struct iphdr);
-
-       if (new_mtu < 68)
-               return -EINVAL;
-
-       if (new_mtu > max_mtu) {
-               if (strict)
-                       return -EINVAL;
-
-               new_mtu = max_mtu;
-       }
+       if (new_mtu > dev->max_mtu)
+               new_mtu = dev->max_mtu;
 
        dev->mtu = new_mtu;
        return 0;
 }
 
-static int geneve_change_mtu(struct net_device *dev, int new_mtu)
-{
-       return __geneve_change_mtu(dev, new_mtu, true);
-}
-
 static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 {
        struct ip_tunnel_info *info = skb_tunnel_info(skb);
@@ -1193,6 +1172,14 @@ static void geneve_setup(struct net_device *dev)
        dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
        dev->hw_features |= NETIF_F_GSO_SOFTWARE;
 
+       /* MTU range: 68 - (something less than 65535) */
+       dev->min_mtu = ETH_MIN_MTU;
+       /* The max_mtu calculation does not take account of GENEVE
+        * options, to avoid excluding potentially valid
+        * configurations. This will be further reduced by IPvX hdr size.
+        */
+       dev->max_mtu = IP_MAX_MTU - GENEVE_BASE_HLEN - dev->hard_header_len;
+
        netif_keep_dst(dev);
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
@@ -1308,10 +1295,13 @@ static int geneve_configure(struct net *net, struct net_device *dev,
 
        /* make enough headroom for basic scenario */
        encap_len = GENEVE_BASE_HLEN + ETH_HLEN;
-       if (remote->sa.sa_family == AF_INET)
+       if (remote->sa.sa_family == AF_INET) {
                encap_len += sizeof(struct iphdr);
-       else
+               dev->max_mtu -= sizeof(struct iphdr);
+       } else {
                encap_len += sizeof(struct ipv6hdr);
+               dev->max_mtu -= sizeof(struct ipv6hdr);
+       }
        dev->needed_headroom = encap_len + ETH_HLEN;
 
        if (metadata) {
@@ -1511,7 +1501,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
        /* openvswitch users expect packet sizes to be unrestricted,
         * so set the largest MTU we can.
         */
-       err = __geneve_change_mtu(dev, IP_MAX_MTU, false);
+       err = geneve_change_mtu(dev, IP_MAX_MTU);
        if (err)
                goto err;
 
index 97e0cbca0a08a15af666fdb17ebc0c87e2a09bda..719d19f35673fb4235df4cd2254347410a5b2d22 100644 (file)
@@ -1094,14 +1094,7 @@ static int gtp_genl_del_pdp(struct sk_buff *skb, struct genl_info *info)
        return 0;
 }
 
-static struct genl_family gtp_genl_family = {
-       .id             = GENL_ID_GENERATE,
-       .name           = "gtp",
-       .version        = 0,
-       .hdrsize        = 0,
-       .maxattr        = GTPA_MAX,
-       .netnsok        = true,
-};
+static struct genl_family gtp_genl_family;
 
 static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
                              u32 type, struct pdp_ctx *pctx)
@@ -1297,6 +1290,17 @@ static const struct genl_ops gtp_genl_ops[] = {
        },
 };
 
+static struct genl_family gtp_genl_family __ro_after_init = {
+       .name           = "gtp",
+       .version        = 0,
+       .hdrsize        = 0,
+       .maxattr        = GTPA_MAX,
+       .netnsok        = true,
+       .module         = THIS_MODULE,
+       .ops            = gtp_genl_ops,
+       .n_ops          = ARRAY_SIZE(gtp_genl_ops),
+};
+
 static int __net_init gtp_net_init(struct net *net)
 {
        struct gtp_net *gn = net_generic(net, gtp_net_id);
@@ -1336,7 +1340,7 @@ static int __init gtp_init(void)
        if (err < 0)
                goto error_out;
 
-       err = genl_register_family_with_ops(&gtp_genl_family, gtp_genl_ops);
+       err = genl_register_family(&gtp_genl_family);
        if (err < 0)
                goto unreg_rtnl_link;
 
index 95c0b45a68fb2654705c00470e53ffb24198d170..f5a9728b89f3d63383bbe2f12ed19c613b7fd8ed 100644 (file)
@@ -68,7 +68,6 @@ static const struct net_device_ops rr_netdev_ops = {
        .ndo_stop               = rr_close,
        .ndo_do_ioctl           = rr_ioctl,
        .ndo_start_xmit         = rr_start_xmit,
-       .ndo_change_mtu         = hippi_change_mtu,
        .ndo_set_mac_address    = hippi_mac_addr,
 };
 
index f4fbcb5aa24a03099e734ce37ebbdc42413bd0e3..3958adade7eb681d78d8baf301f9f74c30a40cce 100644 (file)
@@ -606,8 +606,8 @@ struct nvsp_message {
 } __packed;
 
 
-#define NETVSC_MTU 65536
-#define NETVSC_MTU_MIN 68
+#define NETVSC_MTU 65535
+#define NETVSC_MTU_MIN ETH_MIN_MTU
 
 #define NETVSC_RECEIVE_BUFFER_SIZE             (1024*1024*16)  /* 16MB */
 #define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY      (1024*1024*15)  /* 15MB */
index 720b5fa9e6254463ce0dde094d6b71afd7e7684d..e2bfaac1801dedc698a83657a0f1f5fdcddefca0 100644 (file)
@@ -888,6 +888,13 @@ int netvsc_send(struct hv_device *device,
        if (!net_device)
                return -ENODEV;
 
+       /* We may race with netvsc_connect_vsp()/netvsc_init_buf() and get
+        * here before the negotiation with the host is finished and
+        * send_section_map may not be allocated yet.
+        */
+       if (!net_device->send_section_map)
+               return -EAGAIN;
+
        out_channel = net_device->chn_table[q_idx];
 
        packet->send_buf_index = NETVSC_INVALID_INDEX;
index f6382150b16a13e7071f4640c548b377023a02b3..9522763c8faf4aea389a958f6248cc5f2b2847dc 100644 (file)
@@ -871,19 +871,12 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
        struct netvsc_device *nvdev = ndevctx->nvdev;
        struct hv_device *hdev = ndevctx->device_ctx;
        struct netvsc_device_info device_info;
-       int limit = ETH_DATA_LEN;
        u32 num_chn;
        int ret = 0;
 
        if (ndevctx->start_remove || !nvdev || nvdev->destroy)
                return -ENODEV;
 
-       if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
-               limit = NETVSC_MTU - ETH_HLEN;
-
-       if (mtu < NETVSC_MTU_MIN || mtu > limit)
-               return -EINVAL;
-
        ret = netvsc_close(ndev);
        if (ret)
                goto out;
@@ -1401,6 +1394,13 @@ static int netvsc_probe(struct hv_device *dev,
        netif_set_real_num_tx_queues(net, nvdev->num_chn);
        netif_set_real_num_rx_queues(net, nvdev->num_chn);
 
+       /* MTU range: 68 - 1500 or 65521 */
+       net->min_mtu = NETVSC_MTU_MIN;
+       if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
+               net->max_mtu = NETVSC_MTU - ETH_HLEN;
+       else
+               net->max_mtu = ETH_DATA_LEN;
+
        ret = register_netdev(net);
        if (ret != 0) {
                pr_err("Unable to register netdev.\n");
index f442eb366863e034055c8cf773c9b4b0e287ae87..ab90b22e778c9e85f89146d4094dd903f159438c 100644 (file)
@@ -26,7 +26,7 @@ static struct nf_hook_ops ipvl_nfops[] __read_mostly = {
        },
 };
 
-static struct l3mdev_ops ipvl_l3mdev_ops __read_mostly = {
+static const struct l3mdev_ops ipvl_l3mdev_ops = {
        .l3mdev_l3_rcv = ipvlan_l3_rcv,
 };
 
index d2e61e0029262073b56e3f2cb81e7bf3e00a728e..cc00eb0db5d2d99d2be3c9ad682230db14fad8c3 100644 (file)
@@ -1431,14 +1431,7 @@ static void clear_tx_sa(struct macsec_tx_sa *tx_sa)
        macsec_txsa_put(tx_sa);
 }
 
-static struct genl_family macsec_fam = {
-       .id             = GENL_ID_GENERATE,
-       .name           = MACSEC_GENL_NAME,
-       .hdrsize        = 0,
-       .version        = MACSEC_GENL_VERSION,
-       .maxattr        = MACSEC_ATTR_MAX,
-       .netnsok        = true,
-};
+static struct genl_family macsec_fam;
 
 static struct net_device *get_dev_from_nl(struct net *net,
                                          struct nlattr **attrs)
@@ -2665,6 +2658,17 @@ static const struct genl_ops macsec_genl_ops[] = {
        },
 };
 
+static struct genl_family macsec_fam __ro_after_init = {
+       .name           = MACSEC_GENL_NAME,
+       .hdrsize        = 0,
+       .version        = MACSEC_GENL_VERSION,
+       .maxattr        = MACSEC_ATTR_MAX,
+       .netnsok        = true,
+       .module         = THIS_MODULE,
+       .ops            = macsec_genl_ops,
+       .n_ops          = ARRAY_SIZE(macsec_genl_ops),
+};
+
 static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
                                     struct net_device *dev)
 {
@@ -2980,6 +2984,8 @@ static void macsec_free_netdev(struct net_device *dev)
 static void macsec_setup(struct net_device *dev)
 {
        ether_setup(dev);
+       dev->min_mtu = 0;
+       dev->max_mtu = ETH_MAX_MTU;
        dev->priv_flags |= IFF_NO_QUEUE;
        dev->netdev_ops = &macsec_netdev_ops;
        dev->destructor = macsec_free_netdev;
@@ -3470,7 +3476,7 @@ static int __init macsec_init(void)
        if (err)
                goto notifier;
 
-       err = genl_register_family_with_ops(&macsec_fam, macsec_genl_ops);
+       err = genl_register_family(&macsec_fam);
        if (err)
                goto rtnl;
 
index 3234fcdea31745046cc5a7ac20f2ca676ddcb2e4..a0644158647a86af5930cc4c35a9bca02a2770a8 100644 (file)
@@ -777,7 +777,7 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
 
-       if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu)
+       if (vlan->lowerdev->mtu < new_mtu)
                return -EINVAL;
        dev->mtu = new_mtu;
        return 0;
@@ -1085,6 +1085,8 @@ void macvlan_common_setup(struct net_device *dev)
 {
        ether_setup(dev);
 
+       dev->min_mtu            = 0;
+       dev->max_mtu            = ETH_MAX_MTU;
        dev->priv_flags        &= ~IFF_TX_SKB_SHARING;
        netif_keep_dst(dev);
        dev->priv_flags        |= IFF_UNICAST_FLT;
@@ -1297,6 +1299,10 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
        else if (dev->mtu > lowerdev->mtu)
                return -EINVAL;
 
+       /* MTU range: 68 - lowerdev->max_mtu */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = lowerdev->max_mtu;
+
        if (!tb[IFLA_ADDRESS])
                eth_hw_addr_random(dev);
 
index a9acf7156855546080e850bc07c7a5380ccc1980..36877ba6551646bf1308066026b2f9f9dd12a5d3 100644 (file)
@@ -433,6 +433,9 @@ static int ntb_netdev_probe(struct device *client_dev)
        ndev->netdev_ops = &ntb_netdev_ops;
        ndev->ethtool_ops = &ntb_ethtool_ops;
 
+       ndev->min_mtu = 0;
+       ndev->max_mtu = ETH_MAX_MTU;
+
        dev->qp = ntb_transport_create_queue(ndev, client_dev,
                                             &ntb_netdev_handlers);
        if (!dev->qp) {
index 2651c8d8de2f8ae96ab867756a8a05e0c1e608a7..ff31c10a3485d4e82680b9d25e6e0f4765f68c01 100644 (file)
@@ -15,6 +15,19 @@ if PHYLIB
 config SWPHY
        bool
 
+config LED_TRIGGER_PHY
+       bool "Support LED triggers for tracking link state"
+       depends on LEDS_TRIGGERS
+       ---help---
+         Adds support for a set of LED trigger events per-PHY.  Link
+         state change will trigger the events, for consumption by an
+         LED class driver.  There are triggers for each link speed currently
+         supported by the phy, and are of the form:
+              <mii bus id>:<phy>:<speed>
+
+         Where speed is in the form:
+               <Speed in megabits>Mbps or <Speed in gigabits>Gbps
+
 comment "MDIO bus device drivers"
 
 config MDIO_BCM_IPROC
@@ -277,7 +290,7 @@ config MICROCHIP_PHY
 config MICROSEMI_PHY
        tristate "Microsemi PHYs"
        ---help---
-         Currently supports the VSC8531 and VSC8541 PHYs
+         Currently supports VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
 
 config NATIONAL_PHY
        tristate "National Semiconductor PHYs"
index e58667d111e7f7e08916fd8c6ec2a784b9cee1b1..86d12cd3fbf0912297f64674d5c1309e6339a78c 100644 (file)
@@ -2,6 +2,7 @@
 
 libphy-y                       := phy.o phy_device.o mdio_bus.o mdio_device.o
 libphy-$(CONFIG_SWPHY)         += swphy.o
+libphy-$(CONFIG_LED_TRIGGER_PHY)       += phy_led_triggers.o
 
 obj-$(CONFIG_PHYLIB)           += libphy.o
 
index 09b0b0aa8d6877ad233d72c139aa6cd52bcd2db7..e8ae50e1255e4b1b7912a08db98fecf99caf98c6 100644 (file)
@@ -21,6 +21,8 @@
 #define PHY_ID_AQ1202  0x03a1b445
 #define PHY_ID_AQ2104  0x03a1b460
 #define PHY_ID_AQR105  0x03a1b4a2
+#define PHY_ID_AQR106  0x03a1b4d0
+#define PHY_ID_AQR107  0x03a1b4e0
 #define PHY_ID_AQR405  0x03a1b4b0
 
 #define PHY_AQUANTIA_FEATURES  (SUPPORTED_10000baseT_Full | \
@@ -153,6 +155,30 @@ static struct phy_driver aquantia_driver[] = {
        .ack_interrupt  = aquantia_ack_interrupt,
        .read_status    = aquantia_read_status,
 },
+{
+       .phy_id         = PHY_ID_AQR106,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Aquantia AQR106",
+       .features       = PHY_AQUANTIA_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .aneg_done      = aquantia_aneg_done,
+       .config_aneg    = aquantia_config_aneg,
+       .config_intr    = aquantia_config_intr,
+       .ack_interrupt  = aquantia_ack_interrupt,
+       .read_status    = aquantia_read_status,
+},
+{
+       .phy_id         = PHY_ID_AQR107,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Aquantia AQR107",
+       .features       = PHY_AQUANTIA_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .aneg_done      = aquantia_aneg_done,
+       .config_aneg    = aquantia_config_aneg,
+       .config_intr    = aquantia_config_intr,
+       .ack_interrupt  = aquantia_ack_interrupt,
+       .read_status    = aquantia_read_status,
+},
 {
        .phy_id         = PHY_ID_AQR405,
        .phy_id_mask    = 0xfffffff0,
@@ -173,6 +199,8 @@ static struct mdio_device_id __maybe_unused aquantia_tbl[] = {
        { PHY_ID_AQ1202, 0xfffffff0 },
        { PHY_ID_AQ2104, 0xfffffff0 },
        { PHY_ID_AQR105, 0xfffffff0 },
+       { PHY_ID_AQR106, 0xfffffff0 },
+       { PHY_ID_AQR107, 0xfffffff0 },
        { PHY_ID_AQR405, 0xfffffff0 },
        { }
 };
index a52b560e428b86cd5e782749725875a127a52ea7..c1e52b9dc58d39f02f279b46f400fa811efe3866 100644 (file)
@@ -63,6 +63,7 @@
 #define ATH8030_PHY_ID 0x004dd076
 #define ATH8031_PHY_ID 0x004dd074
 #define ATH8035_PHY_ID 0x004dd072
+#define AT803X_PHY_ID_MASK                     0xffffffef
 
 MODULE_DESCRIPTION("Atheros 803x PHY driver");
 MODULE_AUTHOR("Matus Ujhelyi");
@@ -398,7 +399,7 @@ static struct phy_driver at803x_driver[] = {
        /* ATHEROS 8035 */
        .phy_id                 = ATH8035_PHY_ID,
        .name                   = "Atheros 8035 ethernet",
-       .phy_id_mask            = 0xffffffef,
+       .phy_id_mask            = AT803X_PHY_ID_MASK,
        .probe                  = at803x_probe,
        .config_init            = at803x_config_init,
        .set_wol                = at803x_set_wol,
@@ -415,7 +416,7 @@ static struct phy_driver at803x_driver[] = {
        /* ATHEROS 8030 */
        .phy_id                 = ATH8030_PHY_ID,
        .name                   = "Atheros 8030 ethernet",
-       .phy_id_mask            = 0xffffffef,
+       .phy_id_mask            = AT803X_PHY_ID_MASK,
        .probe                  = at803x_probe,
        .config_init            = at803x_config_init,
        .link_change_notify     = at803x_link_change_notify,
@@ -433,7 +434,7 @@ static struct phy_driver at803x_driver[] = {
        /* ATHEROS 8031 */
        .phy_id                 = ATH8031_PHY_ID,
        .name                   = "Atheros 8031 ethernet",
-       .phy_id_mask            = 0xffffffef,
+       .phy_id_mask            = AT803X_PHY_ID_MASK,
        .probe                  = at803x_probe,
        .config_init            = at803x_config_init,
        .set_wol                = at803x_set_wol,
@@ -452,9 +453,9 @@ static struct phy_driver at803x_driver[] = {
 module_phy_driver(at803x_driver);
 
 static struct mdio_device_id __maybe_unused atheros_tbl[] = {
-       { ATH8030_PHY_ID, 0xffffffef },
-       { ATH8031_PHY_ID, 0xffffffef },
-       { ATH8035_PHY_ID, 0xffffffef },
+       { ATH8030_PHY_ID, AT803X_PHY_ID_MASK },
+       { ATH8031_PHY_ID, AT803X_PHY_ID_MASK },
+       { ATH8035_PHY_ID, AT803X_PHY_ID_MASK },
        { }
 };
 
index 870327efccf78ef0db0361212caf0aa899974625..583ef8a2ec8d3af2179bc3d83de7ac0dc38b481e 100644 (file)
@@ -337,6 +337,41 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
        return ret;
 }
 
+static int bcm54612e_config_aneg(struct phy_device *phydev)
+{
+       int ret;
+
+       /* First, auto-negotiate. */
+       ret = genphy_config_aneg(phydev);
+
+       /* Clear TX internal delay unless requested. */
+       if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
+           (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
+               /* Disable TXD to GTXCLK clock delay (default set) */
+               /* Bit 9 is the only field in shadow register 00011 */
+               bcm_phy_write_shadow(phydev, 0x03, 0);
+       }
+
+       /* Clear RX internal delay unless requested. */
+       if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
+           (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
+               u16 reg;
+
+               /* Errata: reads require filling in the write selector field */
+               bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+                                    MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC);
+               reg = phy_read(phydev, MII_BCM54XX_AUX_CTL);
+               /* Disable RXD to RXC delay (default set) */
+               reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
+               /* Clear shadow selector field */
+               reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
+               bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+                                    MII_BCM54XX_AUXCTL_MISC_WREN | reg);
+       }
+
+       return ret;
+}
+
 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
 {
        int val;
@@ -484,6 +519,18 @@ static struct phy_driver broadcom_drivers[] = {
        .read_status    = genphy_read_status,
        .ack_interrupt  = bcm_phy_ack_intr,
        .config_intr    = bcm_phy_config_intr,
+}, {
+       .phy_id         = PHY_ID_BCM54612E,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Broadcom BCM54612E",
+       .features       = PHY_GBIT_FEATURES |
+                         SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = bcm54xx_config_init,
+       .config_aneg    = bcm54612e_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = bcm_phy_ack_intr,
+       .config_intr    = bcm_phy_config_intr,
 }, {
        .phy_id         = PHY_ID_BCM54616S,
        .phy_id_mask    = 0xfffffff0,
@@ -600,6 +647,7 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
        { PHY_ID_BCM5411, 0xfffffff0 },
        { PHY_ID_BCM5421, 0xfffffff0 },
        { PHY_ID_BCM5461, 0xfffffff0 },
+       { PHY_ID_BCM54612E, 0xfffffff0 },
        { PHY_ID_BCM54616S, 0xfffffff0 },
        { PHY_ID_BCM5464, 0xfffffff0 },
        { PHY_ID_BCM5481, 0xfffffff0 },
index 91177a4a32ad21c1cbea044424659f5604cef7de..1b639242f9e23170e69f7b7669ba82d8d4263fb5 100644 (file)
@@ -33,6 +33,7 @@
 /* Extended Registers */
 #define DP83867_RGMIICTL       0x0032
 #define DP83867_RGMIIDCTL      0x0086
+#define DP83867_IO_MUX_CFG     0x0170
 
 #define DP83867_SW_RESET       BIT(15)
 #define DP83867_SW_RESTART     BIT(14)
 /* RGMIIDCTL bits */
 #define DP83867_RGMII_TX_CLK_DELAY_SHIFT       4
 
+/* IO_MUX_CFG bits */
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL   0x1f
+
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX    0x0
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN    0x1f
+
 struct dp83867_private {
        int rx_id_delay;
        int tx_id_delay;
        int fifo_depth;
+       int io_impedance;
 };
 
 static int dp83867_ack_interrupt(struct phy_device *phydev)
@@ -111,6 +119,14 @@ static int dp83867_of_init(struct phy_device *phydev)
        if (!of_node)
                return -ENODEV;
 
+       dp83867->io_impedance = -EINVAL;
+
+       /* Optional configuration */
+       if (of_property_read_bool(of_node, "ti,max-output-impedance"))
+               dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
+       else if (of_property_read_bool(of_node, "ti,min-output-impedance"))
+               dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
+
        ret = of_property_read_u32(of_node, "ti,rx-internal-delay",
                                   &dp83867->rx_id_delay);
        if (ret)
@@ -184,6 +200,18 @@ static int dp83867_config_init(struct phy_device *phydev)
 
                phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL,
                                       DP83867_DEVADDR, delay);
+
+               if (dp83867->io_impedance >= 0) {
+                       val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
+                                                   DP83867_DEVADDR);
+
+                       val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
+                       val |= dp83867->io_impedance &
+                              DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
+
+                       phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
+                                              DP83867_DEVADDR, val);
+               }
        }
 
        return 0;
index 77a6671d572e38372e3c4c1a22248e4c48099bc9..d0026ab8a22079679729fbe7559e48b3ff1767c6 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/of.h>
-#include <dt-bindings/net/mscc-phy-vsc8531.h>
 #include <linux/netdevice.h>
 
 enum rgmii_rx_clock_delay {
@@ -66,25 +65,33 @@ enum rgmii_rx_clock_delay {
 #define SECURE_ON_PASSWD_LEN_4           0x4000
 
 /* Microsemi PHY ID's */
+#define PHY_ID_VSC8530                   0x00070560
 #define PHY_ID_VSC8531                   0x00070570
+#define PHY_ID_VSC8540                   0x00070760
 #define PHY_ID_VSC8541                   0x00070770
 
-struct edge_rate_table {
-       u16 vddmac;
-       int slowdown[MSCC_SLOWDOWN_MAX];
-};
+#define MSCC_VDDMAC_1500                 1500
+#define MSCC_VDDMAC_1800                 1800
+#define MSCC_VDDMAC_2500                 2500
+#define MSCC_VDDMAC_3300                 3300
 
-struct edge_rate_table edge_table[MSCC_VDDMAC_MAX] = {
-       {3300, { 0, -2, -4,  -7,  -10, -17, -29, -53} },
-       {2500, { 0, -3, -6,  -10, -14, -23, -37, -63} },
-       {1800, { 0, -5, -9,  -16, -23, -35, -52, -76} },
-       {1500, { 0, -6, -14, -21, -29, -42, -58, -77} },
+struct vsc8531_private {
+       int rate_magic;
 };
 
-struct vsc8531_private {
-       u8 edge_slowdown;
+#ifdef CONFIG_OF_MDIO
+struct vsc8531_edge_rate_table {
        u16 vddmac;
+       u8 slowdown[8];
+};
+
+static const struct vsc8531_edge_rate_table edge_table[] = {
+       {MSCC_VDDMAC_3300, { 0, 2,  4,  7, 10, 17, 29, 53} },
+       {MSCC_VDDMAC_2500, { 0, 3,  6, 10, 14, 23, 37, 63} },
+       {MSCC_VDDMAC_1800, { 0, 5,  9, 16, 23, 35, 52, 76} },
+       {MSCC_VDDMAC_1500, { 0, 6, 14, 21, 29, 42, 58, 77} },
 };
+#endif /* CONFIG_OF_MDIO */
 
 static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page)
 {
@@ -205,29 +212,43 @@ out_unlock:
        mutex_unlock(&phydev->lock);
 }
 
-static u8 edge_rate_magic_get(u16 vddmac,
-                             int slowdown)
+#ifdef CONFIG_OF_MDIO
+static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
 {
-       int rc = (MSCC_SLOWDOWN_MAX - 1);
-       u8 vdd;
        u8 sd;
+       u16 vdd;
+       int rc, i, j;
+       struct device *dev = &phydev->mdio.dev;
+       struct device_node *of_node = dev->of_node;
+       u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
 
-       for (vdd = 0; vdd < MSCC_VDDMAC_MAX; vdd++) {
-               if (edge_table[vdd].vddmac == vddmac) {
-                       for (sd = 0; sd < MSCC_SLOWDOWN_MAX; sd++) {
-                               if (edge_table[vdd].slowdown[sd] <= slowdown) {
-                                       rc = (MSCC_SLOWDOWN_MAX - sd - 1);
-                                       break;
-                               }
-                       }
-               }
-       }
+       if (!of_node)
+               return -ENODEV;
 
-       return rc;
+       rc = of_property_read_u16(of_node, "vsc8531,vddmac", &vdd);
+       if (rc != 0)
+               vdd = MSCC_VDDMAC_3300;
+
+       rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown", &sd);
+       if (rc != 0)
+               sd = 0;
+
+       for (i = 0; i < ARRAY_SIZE(edge_table); i++)
+               if (edge_table[i].vddmac == vdd)
+                       for (j = 0; j < sd_array_size; j++)
+                               if (edge_table[i].slowdown[j] == sd)
+                                       return (sd_array_size - j - 1);
+
+       return -EINVAL;
+}
+#else
+static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
+{
+       return 0;
 }
+#endif /* CONFIG_OF_MDIO */
 
-static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev,
-                                     u8 edge_rate)
+static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
 {
        int rc;
        u16 reg_val;
@@ -308,45 +329,10 @@ out_unlock:
        return rc;
 }
 
-#ifdef CONFIG_OF_MDIO
-static int vsc8531_of_init(struct phy_device *phydev)
-{
-       int rc;
-       struct vsc8531_private *vsc8531 = phydev->priv;
-       struct device *dev = &phydev->mdio.dev;
-       struct device_node *of_node = dev->of_node;
-
-       if (!of_node)
-               return -ENODEV;
-
-       rc = of_property_read_u16(of_node, "vsc8531,vddmac",
-                                 &vsc8531->vddmac);
-       if (rc == -EINVAL)
-               vsc8531->vddmac = MSCC_VDDMAC_3300;
-       rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown",
-                                &vsc8531->edge_slowdown);
-       if (rc == -EINVAL)
-               vsc8531->edge_slowdown = 0;
-
-       rc = 0;
-       return rc;
-}
-#else
-static int vsc8531_of_init(struct phy_device *phydev)
-{
-       return 0;
-}
-#endif /* CONFIG_OF_MDIO */
-
 static int vsc85xx_config_init(struct phy_device *phydev)
 {
        int rc;
        struct vsc8531_private *vsc8531 = phydev->priv;
-       u8 edge_rate;
-
-       rc = vsc8531_of_init(phydev);
-       if (rc)
-               return rc;
 
        rc = vsc85xx_default_config(phydev);
        if (rc)
@@ -356,9 +342,7 @@ static int vsc85xx_config_init(struct phy_device *phydev)
        if (rc)
                return rc;
 
-       edge_rate = edge_rate_magic_get(vsc8531->vddmac,
-                                       -(int)vsc8531->edge_slowdown);
-       rc = vsc85xx_edge_rate_cntl_set(phydev, edge_rate);
+       rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic);
        if (rc)
                return rc;
 
@@ -396,19 +380,45 @@ static int vsc85xx_config_intr(struct phy_device *phydev)
 
 static int vsc85xx_probe(struct phy_device *phydev)
 {
+       int rate_magic;
        struct vsc8531_private *vsc8531;
 
+       rate_magic = vsc85xx_edge_rate_magic_get(phydev);
+       if (rate_magic < 0)
+               return rate_magic;
+
        vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
        if (!vsc8531)
                return -ENOMEM;
 
        phydev->priv = vsc8531;
 
+       vsc8531->rate_magic = rate_magic;
+
        return 0;
 }
 
 /* Microsemi VSC85xx PHYs */
 static struct phy_driver vsc85xx_driver[] = {
+{
+       .phy_id         = PHY_ID_VSC8530,
+       .name           = "Microsemi FE VSC8530",
+       .phy_id_mask    = 0xfffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc85xx_config_init,
+       .config_aneg    = &genphy_config_aneg,
+       .aneg_done      = &genphy_aneg_done,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &vsc85xx_ack_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc85xx_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
+},
 {
        .phy_id         = PHY_ID_VSC8531,
        .name           = "Microsemi VSC8531",
@@ -424,9 +434,28 @@ static struct phy_driver vsc85xx_driver[] = {
        .config_intr    = &vsc85xx_config_intr,
        .suspend        = &genphy_suspend,
        .resume         = &genphy_resume,
-       .probe          = &vsc85xx_probe,
-       .set_wol        = &vsc85xx_wol_set,
-       .get_wol        = &vsc85xx_wol_get,
+       .probe          = &vsc85xx_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
+},
+{
+       .phy_id         = PHY_ID_VSC8540,
+       .name           = "Microsemi FE VSC8540 SyncE",
+       .phy_id_mask    = 0xfffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc85xx_config_init,
+       .config_aneg    = &genphy_config_aneg,
+       .aneg_done      = &genphy_aneg_done,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &vsc85xx_ack_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc85xx_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
 },
 {
        .phy_id         = PHY_ID_VSC8541,
@@ -443,9 +472,9 @@ static struct phy_driver vsc85xx_driver[] = {
        .config_intr    = &vsc85xx_config_intr,
        .suspend        = &genphy_suspend,
        .resume         = &genphy_resume,
-       .probe          = &vsc85xx_probe,
-       .set_wol        = &vsc85xx_wol_set,
-       .get_wol        = &vsc85xx_wol_get,
+       .probe          = &vsc85xx_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
 }
 
 };
@@ -453,7 +482,9 @@ static struct phy_driver vsc85xx_driver[] = {
 module_phy_driver(vsc85xx_driver);
 
 static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
+       { PHY_ID_VSC8530, 0xfffffff0, },
        { PHY_ID_VSC8531, 0xfffffff0, },
+       { PHY_ID_VSC8540, 0xfffffff0, },
        { PHY_ID_VSC8541, 0xfffffff0, },
        { }
 };
index f424b867f73e0fb4675c16e565cdeab0af8af0c8..2f94c60d49394ecc743b13660a261979c460c15b 100644 (file)
@@ -260,6 +260,41 @@ static inline unsigned int phy_find_valid(unsigned int idx, u32 features)
        return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
 }
 
+/**
+ * phy_supported_speeds - return all speeds currently supported by a phy device
+ * @phy: The phy device to return supported speeds of.
+ * @speeds: buffer to store supported speeds in.
+ * @size:   size of speeds buffer.
+ *
+ * Description: Returns the number of supported speeds, and fills the speeds
+ * buffer with the supported speeds. If speeds buffer is too small to contain
+ * all currently supported speeds, will return as many speeds as can fit.
+ */
+unsigned int phy_supported_speeds(struct phy_device *phy,
+                                 unsigned int *speeds,
+                                 unsigned int size)
+{
+       unsigned int count = 0;
+       unsigned int idx = 0;
+
+       while (idx < MAX_NUM_SETTINGS && count < size) {
+               idx = phy_find_valid(idx, phy->supported);
+
+               if (!(settings[idx].setting & phy->supported))
+                       break;
+
+               /* Assumes settings are grouped by speed */
+               if ((count == 0) ||
+                   (speeds[count - 1] != settings[idx].speed)) {
+                       speeds[count] = settings[idx].speed;
+                       count++;
+               }
+               idx++;
+       }
+
+       return count;
+}
+
 /**
  * phy_check_valid - check if there is a valid PHY setting which matches
  *                  speed, duplex, and feature mask
@@ -664,7 +699,7 @@ static void phy_error(struct phy_device *phydev)
  * @phy_dat: phy_device pointer
  *
  * Description: When a PHY interrupt occurs, the handler disables
- * interrupts, and schedules a work task to clear the interrupt.
+ * interrupts, and uses phy_change to handle the interrupt.
  */
 static irqreturn_t phy_interrupt(int irq, void *phy_dat)
 {
@@ -673,15 +708,10 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
        if (PHY_HALTED == phydev->state)
                return IRQ_NONE;                /* It can't be ours.  */
 
-       /* The MDIO bus is not allowed to be written in interrupt
-        * context, so we need to disable the irq here.  A work
-        * queue will write the PHY to disable and clear the
-        * interrupt, and then reenable the irq line.
-        */
        disable_irq_nosync(irq);
        atomic_inc(&phydev->irq_disable);
 
-       queue_work(system_power_efficient_wq, &phydev->phy_queue);
+       phy_change(phydev);
 
        return IRQ_HANDLED;
 }
@@ -739,10 +769,9 @@ phy_err:
 int phy_start_interrupts(struct phy_device *phydev)
 {
        atomic_set(&phydev->irq_disable, 0);
-       if (request_irq(phydev->irq, phy_interrupt,
-                               IRQF_SHARED,
-                               "phy_interrupt",
-                               phydev) < 0) {
+       if (request_threaded_irq(phydev->irq, NULL, phy_interrupt,
+                                IRQF_ONESHOT | IRQF_SHARED,
+                                phydev_name(phydev), phydev) < 0) {
                pr_warn("%s: Can't get IRQ %d (PHY)\n",
                        phydev->mdio.bus->name, phydev->irq);
                phydev->irq = PHY_POLL;
@@ -766,12 +795,6 @@ int phy_stop_interrupts(struct phy_device *phydev)
 
        free_irq(phydev->irq, phydev);
 
-       /* Cannot call flush_scheduled_work() here as desired because
-        * of rtnl_lock(), but we do not really care about what would
-        * be done, except from enable_irq(), so cancel any work
-        * possibly pending and take care of the matter below.
-        */
-       cancel_work_sync(&phydev->phy_queue);
        /* If work indeed has been cancelled, disable_irq() will have
         * been left unbalanced from phy_interrupt() and enable_irq()
         * has to be called so that other devices on the line work.
@@ -784,14 +807,11 @@ int phy_stop_interrupts(struct phy_device *phydev)
 EXPORT_SYMBOL(phy_stop_interrupts);
 
 /**
- * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes
- * @work: work_struct that describes the work to be done
+ * phy_change - Called by the phy_interrupt to handle PHY changes
+ * @phydev: phy_device struct that interrupted
  */
-void phy_change(struct work_struct *work)
+void phy_change(struct phy_device *phydev)
 {
-       struct phy_device *phydev =
-               container_of(work, struct phy_device, phy_queue);
-
        if (phy_interrupt_is_valid(phydev)) {
                if (phydev->drv->did_interrupt &&
                    !phydev->drv->did_interrupt(phydev))
@@ -832,6 +852,18 @@ phy_err:
        phy_error(phydev);
 }
 
+/**
+ * phy_change_work - Scheduled by the phy_mac_interrupt to handle PHY changes
+ * @work: work_struct that describes the work to be done
+ */
+void phy_change_work(struct work_struct *work)
+{
+       struct phy_device *phydev =
+               container_of(work, struct phy_device, phy_queue);
+
+       phy_change(phydev);
+}
+
 /**
  * phy_stop - Bring down the PHY link, and stop checking the status
  * @phydev: target phy_device struct
@@ -911,6 +943,12 @@ void phy_start(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_start);
 
+static void phy_adjust_link(struct phy_device *phydev)
+{
+       phydev->adjust_link(phydev->attached_dev);
+       phy_led_trigger_change_speed(phydev);
+}
+
 /**
  * phy_state_machine - Handle the state machine
  * @work: work_struct that describes the work to be done
@@ -953,7 +991,7 @@ void phy_state_machine(struct work_struct *work)
                if (!phydev->link) {
                        phydev->state = PHY_NOLINK;
                        netif_carrier_off(phydev->attached_dev);
-                       phydev->adjust_link(phydev->attached_dev);
+                       phy_adjust_link(phydev);
                        break;
                }
 
@@ -966,7 +1004,7 @@ void phy_state_machine(struct work_struct *work)
                if (err > 0) {
                        phydev->state = PHY_RUNNING;
                        netif_carrier_on(phydev->attached_dev);
-                       phydev->adjust_link(phydev->attached_dev);
+                       phy_adjust_link(phydev);
 
                } else if (0 == phydev->link_timeout--)
                        needs_aneg = true;
@@ -993,7 +1031,7 @@ void phy_state_machine(struct work_struct *work)
                        }
                        phydev->state = PHY_RUNNING;
                        netif_carrier_on(phydev->attached_dev);
-                       phydev->adjust_link(phydev->attached_dev);
+                       phy_adjust_link(phydev);
                }
                break;
        case PHY_FORCING:
@@ -1009,7 +1047,7 @@ void phy_state_machine(struct work_struct *work)
                                needs_aneg = true;
                }
 
-               phydev->adjust_link(phydev->attached_dev);
+               phy_adjust_link(phydev);
                break;
        case PHY_RUNNING:
                /* Only register a CHANGE if we are polling and link changed
@@ -1038,7 +1076,7 @@ void phy_state_machine(struct work_struct *work)
                        netif_carrier_off(phydev->attached_dev);
                }
 
-               phydev->adjust_link(phydev->attached_dev);
+               phy_adjust_link(phydev);
 
                if (phy_interrupt_is_valid(phydev))
                        err = phy_config_interrupt(phydev,
@@ -1048,7 +1086,7 @@ void phy_state_machine(struct work_struct *work)
                if (phydev->link) {
                        phydev->link = 0;
                        netif_carrier_off(phydev->attached_dev);
-                       phydev->adjust_link(phydev->attached_dev);
+                       phy_adjust_link(phydev);
                        do_suspend = true;
                }
                break;
@@ -1072,7 +1110,7 @@ void phy_state_machine(struct work_struct *work)
                                } else  {
                                        phydev->state = PHY_NOLINK;
                                }
-                               phydev->adjust_link(phydev->attached_dev);
+                               phy_adjust_link(phydev);
                        } else {
                                phydev->state = PHY_AN;
                                phydev->link_timeout = PHY_AN_TIMEOUT;
@@ -1088,7 +1126,7 @@ void phy_state_machine(struct work_struct *work)
                        } else  {
                                phydev->state = PHY_NOLINK;
                        }
-                       phydev->adjust_link(phydev->attached_dev);
+                       phy_adjust_link(phydev);
                }
                break;
        }
@@ -1116,6 +1154,15 @@ void phy_state_machine(struct work_struct *work)
                                   PHY_STATE_TIME * HZ);
 }
 
+/**
+ * phy_mac_interrupt - MAC says the link has changed
+ * @phydev: phy_device struct with changed link
+ * @new_link: Link is Up/Down.
+ *
+ * Description: The MAC layer is able indicate there has been a change
+ *   in the PHY link status. Set the new link status, and trigger the
+ *   state machine, work a work queue.
+ */
 void phy_mac_interrupt(struct phy_device *phydev, int new_link)
 {
        phydev->link = new_link;
index e977ba931878e77cb149fd5a66c5618f723500a3..49a1c988d29cb85ebd4a91c403b03c26f2e25817 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/phy.h>
+#include <linux/phy_led_triggers.h>
 #include <linux/mdio.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
@@ -347,7 +348,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
 
        mutex_init(&dev->lock);
        INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
-       INIT_WORK(&dev->phy_queue, phy_change);
+       INIT_WORK(&dev->phy_queue, phy_change_work);
 
        /* Request the appropriate module unconditionally; don't
         * bother trying to do so only if it isn't already loaded,
@@ -916,6 +917,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
        else
                phy_resume(phydev);
 
+       phy_led_triggers_register(phydev);
+
        return err;
 
 error:
@@ -989,6 +992,8 @@ void phy_detach(struct phy_device *phydev)
                }
        }
 
+       phy_led_triggers_unregister(phydev);
+
        /*
         * The phydev might go away on the put_device() below, so avoid
         * a use-after-free bug by reading the underlying bus first.
diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c
new file mode 100644 (file)
index 0000000..cda600a
--- /dev/null
@@ -0,0 +1,136 @@
+/* Copyright (C) 2016 National Instruments Corp.
+ *
+ * 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 Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/leds.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+
+static struct phy_led_trigger *phy_speed_to_led_trigger(struct phy_device *phy,
+                                                       unsigned int speed)
+{
+       unsigned int i;
+
+       for (i = 0; i < phy->phy_num_led_triggers; i++) {
+               if (phy->phy_led_triggers[i].speed == speed)
+                       return &phy->phy_led_triggers[i];
+       }
+       return NULL;
+}
+
+void phy_led_trigger_change_speed(struct phy_device *phy)
+{
+       struct phy_led_trigger *plt;
+
+       if (!phy->link)
+               goto out_change_speed;
+
+       if (phy->speed == 0)
+               return;
+
+       plt = phy_speed_to_led_trigger(phy, phy->speed);
+       if (!plt) {
+               netdev_alert(phy->attached_dev,
+                            "No phy led trigger registered for speed(%d)\n",
+                            phy->speed);
+               goto out_change_speed;
+       }
+
+       if (plt != phy->last_triggered) {
+               led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
+               led_trigger_event(&plt->trigger, LED_FULL);
+               phy->last_triggered = plt;
+       }
+       return;
+
+out_change_speed:
+       if (phy->last_triggered) {
+               led_trigger_event(&phy->last_triggered->trigger,
+                                 LED_OFF);
+               phy->last_triggered = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(phy_led_trigger_change_speed);
+
+static int phy_led_trigger_register(struct phy_device *phy,
+                                   struct phy_led_trigger *plt,
+                                   unsigned int speed)
+{
+       char name_suffix[PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE];
+
+       plt->speed = speed;
+
+       if (speed < SPEED_1000)
+               snprintf(name_suffix, sizeof(name_suffix), "%dMbps", speed);
+       else if (speed == SPEED_2500)
+               snprintf(name_suffix, sizeof(name_suffix), "2.5Gbps");
+       else
+               snprintf(name_suffix, sizeof(name_suffix), "%dGbps",
+                        DIV_ROUND_CLOSEST(speed, 1000));
+
+       snprintf(plt->name, sizeof(plt->name), PHY_ID_FMT ":%s",
+                phy->mdio.bus->id, phy->mdio.addr, name_suffix);
+       plt->trigger.name = plt->name;
+
+       return led_trigger_register(&plt->trigger);
+}
+
+static void phy_led_trigger_unregister(struct phy_led_trigger *plt)
+{
+       led_trigger_unregister(&plt->trigger);
+}
+
+int phy_led_triggers_register(struct phy_device *phy)
+{
+       int i, err;
+       unsigned int speeds[50];
+
+       phy->phy_num_led_triggers = phy_supported_speeds(phy, speeds,
+                                                        ARRAY_SIZE(speeds));
+       if (!phy->phy_num_led_triggers)
+               return 0;
+
+       phy->phy_led_triggers = devm_kzalloc(&phy->mdio.dev,
+                                           sizeof(struct phy_led_trigger) *
+                                                  phy->phy_num_led_triggers,
+                                           GFP_KERNEL);
+       if (!phy->phy_led_triggers)
+               return -ENOMEM;
+
+       for (i = 0; i < phy->phy_num_led_triggers; i++) {
+               err = phy_led_trigger_register(phy, &phy->phy_led_triggers[i],
+                                              speeds[i]);
+               if (err)
+                       goto out_unreg;
+       }
+
+       phy->last_triggered = NULL;
+       phy_led_trigger_change_speed(phy);
+
+       return 0;
+out_unreg:
+       while (i--)
+               phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
+       devm_kfree(&phy->mdio.dev, phy->phy_led_triggers);
+       return err;
+}
+EXPORT_SYMBOL_GPL(phy_led_triggers_register);
+
+void phy_led_triggers_unregister(struct phy_device *phy)
+{
+       int i;
+
+       for (i = 0; i < phy->phy_num_led_triggers; i++)
+               phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
+
+       devm_kfree(&phy->mdio.dev, phy->phy_led_triggers);
+}
+EXPORT_SYMBOL_GPL(phy_led_triggers_unregister);
index 9c4b41a4df7d795c268f9816fdfe45b5ca780e90..3c55ea357f351b9006d35fdfee7d8d6e936a039b 100644 (file)
@@ -270,7 +270,6 @@ static const struct net_device_ops plip_netdev_ops = {
        .ndo_stop                = plip_close,
        .ndo_start_xmit          = plip_tx_packet,
        .ndo_do_ioctl            = plip_ioctl,
-       .ndo_change_mtu          = eth_change_mtu,
        .ndo_set_mac_address     = eth_mac_addr,
        .ndo_validate_addr       = eth_validate_addr,
 };
index a31f4610b4936b698724597d66164c1470cdeac9..300bb1479b3a45bc919d053a799ea058164a0e2b 100644 (file)
@@ -466,17 +466,6 @@ static void rionet_set_msglevel(struct net_device *ndev, u32 value)
        rnet->msg_enable = value;
 }
 
-static int rionet_change_mtu(struct net_device *ndev, int new_mtu)
-{
-       if ((new_mtu < 68) || (new_mtu > RIONET_MAX_MTU)) {
-               printk(KERN_ERR "%s: Invalid MTU size %d\n",
-                      ndev->name, new_mtu);
-               return -EINVAL;
-       }
-       ndev->mtu = new_mtu;
-       return 0;
-}
-
 static const struct ethtool_ops rionet_ethtool_ops = {
        .get_drvinfo = rionet_get_drvinfo,
        .get_msglevel = rionet_get_msglevel,
@@ -488,7 +477,6 @@ static const struct net_device_ops rionet_netdev_ops = {
        .ndo_open               = rionet_open,
        .ndo_stop               = rionet_close,
        .ndo_start_xmit         = rionet_start_xmit,
-       .ndo_change_mtu         = rionet_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 };
@@ -525,6 +513,9 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
 
        ndev->netdev_ops = &rionet_netdev_ops;
        ndev->mtu = RIONET_MAX_MTU;
+       /* MTU range: 68 - 4082 */
+       ndev->min_mtu = ETH_MIN_MTU;
+       ndev->max_mtu = RIONET_MAX_MTU;
        ndev->features = NETIF_F_LLTX;
        SET_NETDEV_DEV(ndev, &mport->dev);
        ndev->ethtool_ops = &rionet_ethtool_ops;
index aad0b59d41e304c6481c0b58e04afd1db2b51918..8b8b532597830e47cc22a4415a6e68c07bc857d5 100644 (file)
@@ -141,7 +141,6 @@ static const struct net_device_ops sb1000_netdev_ops = {
        .ndo_start_xmit         = sb1000_start_xmit,
        .ndo_do_ioctl           = sb1000_dev_ioctl,
        .ndo_stop               = sb1000_close,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 9ed6d1c1ee45f15b2686b7c4102045b3acead55c..7e933d8ff811e1b70b0f4f113983d0d431b0679c 100644 (file)
@@ -561,12 +561,7 @@ static int sl_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct slip *sl = netdev_priv(dev);
 
-       if (new_mtu < 68 || new_mtu > 65534)
-               return -EINVAL;
-
-       if (new_mtu != dev->mtu)
-               return sl_realloc_bufs(sl, new_mtu);
-       return 0;
+       return sl_realloc_bufs(sl, new_mtu);
 }
 
 /* Netdevice get statistics request */
@@ -663,6 +658,10 @@ static void sl_setup(struct net_device *dev)
        dev->addr_len           = 0;
        dev->tx_queue_len       = 10;
 
+       /* MTU range: 68 - 65534 */
+       dev->min_mtu = 68;
+       dev->max_mtu = 65534;
+
        /* New-style flags. */
        dev->flags              = IFF_NOARP|IFF_POINTOPOINT|IFF_MULTICAST;
 }
index a380649bf6b5c2242edac044b497bf15922cffe5..bdc58567d10e7b370b6966c35251b81619f314ce 100644 (file)
@@ -2150,13 +2150,7 @@ static struct rtnl_link_ops team_link_ops __read_mostly = {
  * Generic netlink custom interface
  ***********************************/
 
-static struct genl_family team_nl_family = {
-       .id             = GENL_ID_GENERATE,
-       .name           = TEAM_GENL_NAME,
-       .version        = TEAM_GENL_VERSION,
-       .maxattr        = TEAM_ATTR_MAX,
-       .netnsok        = true,
-};
+static struct genl_family team_nl_family;
 
 static const struct nla_policy team_nl_policy[TEAM_ATTR_MAX + 1] = {
        [TEAM_ATTR_UNSPEC]                      = { .type = NLA_UNSPEC, },
@@ -2746,6 +2740,18 @@ static const struct genl_multicast_group team_nl_mcgrps[] = {
        { .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, },
 };
 
+static struct genl_family team_nl_family __ro_after_init = {
+       .name           = TEAM_GENL_NAME,
+       .version        = TEAM_GENL_VERSION,
+       .maxattr        = TEAM_ATTR_MAX,
+       .netnsok        = true,
+       .module         = THIS_MODULE,
+       .ops            = team_nl_ops,
+       .n_ops          = ARRAY_SIZE(team_nl_ops),
+       .mcgrps         = team_nl_mcgrps,
+       .n_mcgrps       = ARRAY_SIZE(team_nl_mcgrps),
+};
+
 static int team_nl_send_multicast(struct sk_buff *skb,
                                  struct team *team, u32 portid)
 {
@@ -2767,10 +2773,9 @@ static int team_nl_send_event_port_get(struct team *team,
                                          port);
 }
 
-static int team_nl_init(void)
+static int __init team_nl_init(void)
 {
-       return genl_register_family_with_ops_groups(&team_nl_family, team_nl_ops,
-                                                   team_nl_mcgrps);
+       return genl_register_family(&team_nl_family);
 }
 
 static void team_nl_fini(void)
index 8093e39ae263a7bd954682125221189499206b7c..9142db847ee156f8e29dab9856cbcc90021ac541 100644 (file)
@@ -925,18 +925,6 @@ static void tun_net_mclist(struct net_device *dev)
         */
 }
 
-#define MIN_MTU 68
-#define MAX_MTU 65535
-
-static int
-tun_net_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU)
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static netdev_features_t tun_net_fix_features(struct net_device *dev,
        netdev_features_t features)
 {
@@ -1014,7 +1002,6 @@ static const struct net_device_ops tun_netdev_ops = {
        .ndo_open               = tun_net_open,
        .ndo_stop               = tun_net_close,
        .ndo_start_xmit         = tun_net_xmit,
-       .ndo_change_mtu         = tun_net_change_mtu,
        .ndo_fix_features       = tun_net_fix_features,
        .ndo_select_queue       = tun_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1029,7 +1016,6 @@ static const struct net_device_ops tap_netdev_ops = {
        .ndo_open               = tun_net_open,
        .ndo_stop               = tun_net_close,
        .ndo_start_xmit         = tun_net_xmit,
-       .ndo_change_mtu         = tun_net_change_mtu,
        .ndo_fix_features       = tun_net_fix_features,
        .ndo_set_rx_mode        = tun_net_mclist,
        .ndo_set_mac_address    = eth_mac_addr,
@@ -1062,6 +1048,9 @@ static void tun_flow_uninit(struct tun_struct *tun)
        tun_flow_flush(tun);
 }
 
+#define MIN_MTU 68
+#define MAX_MTU 65535
+
 /* Initialize net device. */
 static void tun_net_init(struct net_device *dev)
 {
@@ -1092,6 +1081,9 @@ static void tun_net_init(struct net_device *dev)
 
                break;
        }
+
+       dev->min_mtu = MIN_MTU;
+       dev->max_mtu = MAX_MTU - dev->hard_header_len;
 }
 
 /* Character device part */
@@ -2013,7 +2005,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
        rtnl_lock();
 
        tun = __tun_get(tfile);
-       if (cmd == TUNSETIFF && !tun) {
+       if (cmd == TUNSETIFF) {
+               ret = -EEXIST;
+               if (tun)
+                       goto unlock;
+
                ifr.ifr_name[IFNAMSIZ-1] = '\0';
 
                ret = tun_set_iff(sock_net(&tfile->sk), file, &ifr);
index cce24950a0ab65f795230b5d5fa08d09e69dd139..7363cc5dd1bfd40463ecea4523515f06c8ac8799 100644 (file)
@@ -1026,9 +1026,6 @@ static int ax88178_change_mtu(struct net_device *net, int new_mtu)
 
        netdev_dbg(dev->net, "ax88178_change_mtu() new_mtu=%d\n", new_mtu);
 
-       if (new_mtu <= 0 || ll_mtu > 16384)
-               return -EINVAL;
-
        if ((ll_mtu % dev->maxpacket) == 0)
                return -EDOM;
 
@@ -1081,6 +1078,7 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
 
        dev->net->netdev_ops = &ax88178_netdev_ops;
        dev->net->ethtool_ops = &ax88178_ethtool_ops;
+       dev->net->max_mtu = 16384 - (dev->net->hard_header_len + 4);
 
        /* Blink LEDS so users know driver saw dongle */
        asix_sw_reset(dev, 0, 0);
index e6338c16081a5d66c11ad400e876ca7b6c7bcd40..36c70d6f736322f6204ac414146497cc0421613c 100644 (file)
@@ -907,9 +907,6 @@ static int ax88179_change_mtu(struct net_device *net, int new_mtu)
        struct usbnet *dev = netdev_priv(net);
        u16 tmp16;
 
-       if (new_mtu <= 0 || new_mtu > 4088)
-               return -EINVAL;
-
        net->mtu = new_mtu;
        dev->hard_mtu = net->mtu + net->hard_header_len;
 
@@ -1266,6 +1263,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->netdev_ops = &ax88179_netdev_ops;
        dev->net->ethtool_ops = &ax88179_ethtool_ops;
        dev->net->needed_headroom = 8;
+       dev->net->max_mtu = 4088;
 
        /* Initialize MII structure */
        dev->mii.dev = dev->net;
index d9ca05d3ac8eadb17a0ec12d539c50dde7fb151b..a1f2f6f1e6149840551cd2418299800119ee65a2 100644 (file)
@@ -761,7 +761,6 @@ static const struct net_device_ops catc_netdev_ops = {
 
        .ndo_tx_timeout         = catc_tx_timeout,
        .ndo_set_rx_mode        = catc_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index ff2270ead2e68b8a381ab42f6309d919f8b9ed12..eb52de8205f0d48044bcb6c1302ce7bda779128e 100644 (file)
@@ -276,21 +276,11 @@ static int usbpn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        return -ENOIOCTLCMD;
 }
 
-static int usbpn_set_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
-               return -EINVAL;
-
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static const struct net_device_ops usbpn_ops = {
        .ndo_open       = usbpn_open,
        .ndo_stop       = usbpn_close,
        .ndo_start_xmit = usbpn_xmit,
        .ndo_do_ioctl   = usbpn_ioctl,
-       .ndo_change_mtu = usbpn_set_mtu,
 };
 
 static void usbpn_setup(struct net_device *dev)
@@ -301,6 +291,8 @@ static void usbpn_setup(struct net_device *dev)
        dev->type               = ARPHRD_PHONET;
        dev->flags              = IFF_POINTOPOINT | IFF_NOARP;
        dev->mtu                = PHONET_MAX_MTU;
+       dev->min_mtu            = PHONET_MIN_MTU;
+       dev->max_mtu            = PHONET_MAX_MTU;
        dev->hard_header_len    = 1;
        dev->dev_addr[0]        = PN_MEDIA_USB;
        dev->addr_len           = 1;
index c47ec0a04c8e5f9ff4d77cf8fade7717ca9cdb75..45e5e4332a28085d98d7257ae48c3d87d97dc30a 100644 (file)
@@ -687,6 +687,20 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* ThinkPad USB-C Dock (based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
+/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
 {
        USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM,
@@ -694,6 +708,20 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
+/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
 {
        USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM,
index 877c9516e78174dc41bd1e9d3f4c506d193134a9..7141817946f01f72c3f16b5335b1093a18a4af44 100644 (file)
@@ -740,10 +740,6 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx)
 int cdc_ncm_change_mtu(struct net_device *net, int new_mtu)
 {
        struct usbnet *dev = netdev_priv(net);
-       int maxmtu = cdc_ncm_max_dgram_size(dev) - cdc_ncm_eth_hlen(dev);
-
-       if (new_mtu <= 0 || new_mtu > maxmtu)
-               return -EINVAL;
 
        net->mtu = new_mtu;
        cdc_ncm_set_dgram_size(dev, new_mtu + cdc_ncm_eth_hlen(dev));
@@ -909,6 +905,7 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
 
        /* must handle MTU changes */
        dev->net->netdev_ops = &cdc_ncm_netdev_ops;
+       dev->net->max_mtu = cdc_ncm_max_dgram_size(dev) - cdc_ncm_eth_hlen(dev);
 
        return 0;
 
index 66b34ddbe216dfc3578a81831b733b9463622fa7..338aed5da14d849c17f5e9125f3a1652d0859ac1 100644 (file)
@@ -982,7 +982,6 @@ static const struct net_device_ops kaweth_netdev_ops = {
        .ndo_tx_timeout =               kaweth_tx_timeout,
        .ndo_set_rx_mode =              kaweth_set_rx_mode,
        .ndo_get_stats =                kaweth_netdev_stats,
-       .ndo_change_mtu =               eth_change_mtu,
        .ndo_set_mac_address =          eth_mac_addr,
        .ndo_validate_addr =            eth_validate_addr,
 };
index db558b8b32fe5ba7f9fb71129d41cf806b6c08f4..c4e748e92db40faed62fe7501ad2453daca95668 100644 (file)
@@ -1092,7 +1092,7 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex,
 static int lan78xx_link_reset(struct lan78xx_net *dev)
 {
        struct phy_device *phydev = dev->net->phydev;
-       struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+       struct ethtool_link_ksettings ecmd;
        int ladv, radv, ret;
        u32 buf;
 
@@ -1126,12 +1126,12 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
        } else if (phydev->link && !dev->link_on) {
                dev->link_on = true;
 
-               phy_ethtool_gset(phydev, &ecmd);
+               phy_ethtool_ksettings_get(phydev, &ecmd);
 
                ret = phy_read(phydev, LAN88XX_INT_STS);
 
                if (dev->udev->speed == USB_SPEED_SUPER) {
-                       if (ethtool_cmd_speed(&ecmd) == 1000) {
+                       if (ecmd.base.speed == 1000) {
                                /* disable U2 */
                                ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
                                buf &= ~USB_CFG1_DEV_U2_INIT_EN_;
@@ -1159,9 +1159,10 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
 
                netif_dbg(dev, link, dev->net,
                          "speed: %u duplex: %d anadv: 0x%04x anlpa: 0x%04x",
-                         ethtool_cmd_speed(&ecmd), ecmd.duplex, ladv, radv);
+                         ecmd.base.speed, ecmd.base.duplex, ladv, radv);
 
-               ret = lan78xx_update_flowcontrol(dev, ecmd.duplex, ladv, radv);
+               ret = lan78xx_update_flowcontrol(dev, ecmd.base.duplex, ladv,
+                                                radv);
                phy_mac_interrupt(phydev, 1);
 
                if (!timer_pending(&dev->stat_monitor)) {
@@ -1484,7 +1485,8 @@ static void lan78xx_set_mdix_status(struct net_device *net, __u8 mdix_ctrl)
        dev->mdix_ctrl = mdix_ctrl;
 }
 
-static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
+static int lan78xx_get_link_ksettings(struct net_device *net,
+                                     struct ethtool_link_ksettings *cmd)
 {
        struct lan78xx_net *dev = netdev_priv(net);
        struct phy_device *phydev = net->phydev;
@@ -1495,20 +1497,20 @@ static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
        if (ret < 0)
                return ret;
 
-       ret = phy_ethtool_gset(phydev, cmd);
+       ret = phy_ethtool_ksettings_get(phydev, cmd);
 
        buf = lan78xx_get_mdix_status(net);
 
        buf &= LAN88XX_EXT_MODE_CTRL_MDIX_MASK_;
        if (buf == LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_) {
-               cmd->eth_tp_mdix = ETH_TP_MDI_AUTO;
-               cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
+               cmd->base.eth_tp_mdix = ETH_TP_MDI_AUTO;
+               cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
        } else if (buf == LAN88XX_EXT_MODE_CTRL_MDI_) {
-               cmd->eth_tp_mdix = ETH_TP_MDI;
-               cmd->eth_tp_mdix_ctrl = ETH_TP_MDI;
+               cmd->base.eth_tp_mdix = ETH_TP_MDI;
+               cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI;
        } else if (buf == LAN88XX_EXT_MODE_CTRL_MDI_X_) {
-               cmd->eth_tp_mdix = ETH_TP_MDI_X;
-               cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_X;
+               cmd->base.eth_tp_mdix = ETH_TP_MDI_X;
+               cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_X;
        }
 
        usb_autopm_put_interface(dev->intf);
@@ -1516,7 +1518,8 @@ static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
        return ret;
 }
 
-static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
+static int lan78xx_set_link_ksettings(struct net_device *net,
+                                     const struct ethtool_link_ksettings *cmd)
 {
        struct lan78xx_net *dev = netdev_priv(net);
        struct phy_device *phydev = net->phydev;
@@ -1527,14 +1530,13 @@ static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
        if (ret < 0)
                return ret;
 
-       if (dev->mdix_ctrl != cmd->eth_tp_mdix_ctrl) {
-               lan78xx_set_mdix_status(net, cmd->eth_tp_mdix_ctrl);
-       }
+       if (dev->mdix_ctrl != cmd->base.eth_tp_mdix_ctrl)
+               lan78xx_set_mdix_status(net, cmd->base.eth_tp_mdix_ctrl);
 
        /* change speed & duplex */
-       ret = phy_ethtool_sset(phydev, cmd);
+       ret = phy_ethtool_ksettings_set(phydev, cmd);
 
-       if (!cmd->autoneg) {
+       if (!cmd->base.autoneg) {
                /* force link down */
                temp = phy_read(phydev, MII_BMCR);
                phy_write(phydev, MII_BMCR, temp | BMCR_LOOPBACK);
@@ -1552,9 +1554,9 @@ static void lan78xx_get_pause(struct net_device *net,
 {
        struct lan78xx_net *dev = netdev_priv(net);
        struct phy_device *phydev = net->phydev;
-       struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+       struct ethtool_link_ksettings ecmd;
 
-       phy_ethtool_gset(phydev, &ecmd);
+       phy_ethtool_ksettings_get(phydev, &ecmd);
 
        pause->autoneg = dev->fc_autoneg;
 
@@ -1570,12 +1572,12 @@ static int lan78xx_set_pause(struct net_device *net,
 {
        struct lan78xx_net *dev = netdev_priv(net);
        struct phy_device *phydev = net->phydev;
-       struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+       struct ethtool_link_ksettings ecmd;
        int ret;
 
-       phy_ethtool_gset(phydev, &ecmd);
+       phy_ethtool_ksettings_get(phydev, &ecmd);
 
-       if (pause->autoneg && !ecmd.autoneg) {
+       if (pause->autoneg && !ecmd.base.autoneg) {
                ret = -EINVAL;
                goto exit;
        }
@@ -1587,13 +1589,21 @@ static int lan78xx_set_pause(struct net_device *net,
        if (pause->tx_pause)
                dev->fc_request_control |= FLOW_CTRL_TX;
 
-       if (ecmd.autoneg) {
+       if (ecmd.base.autoneg) {
                u32 mii_adv;
+               u32 advertising;
+
+               ethtool_convert_link_mode_to_legacy_u32(
+                       &advertising, ecmd.link_modes.advertising);
 
-               ecmd.advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
+               advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
                mii_adv = (u32)mii_advertise_flowctrl(dev->fc_request_control);
-               ecmd.advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
-               phy_ethtool_sset(phydev, &ecmd);
+               advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
+
+               ethtool_convert_legacy_u32_to_link_mode(
+                       ecmd.link_modes.advertising, advertising);
+
+               phy_ethtool_ksettings_set(phydev, &ecmd);
        }
 
        dev->fc_autoneg = pause->autoneg;
@@ -1609,8 +1619,6 @@ static const struct ethtool_ops lan78xx_ethtool_ops = {
        .get_drvinfo    = lan78xx_get_drvinfo,
        .get_msglevel   = lan78xx_get_msglevel,
        .set_msglevel   = lan78xx_set_msglevel,
-       .get_settings   = lan78xx_get_settings,
-       .set_settings   = lan78xx_set_settings,
        .get_eeprom_len = lan78xx_ethtool_get_eeprom_len,
        .get_eeprom     = lan78xx_ethtool_get_eeprom,
        .set_eeprom     = lan78xx_ethtool_set_eeprom,
@@ -1623,6 +1631,8 @@ static const struct ethtool_ops lan78xx_ethtool_ops = {
        .set_eee        = lan78xx_set_eee,
        .get_pauseparam = lan78xx_get_pause,
        .set_pauseparam = lan78xx_set_pause,
+       .get_link_ksettings = lan78xx_get_link_ksettings,
+       .set_link_ksettings = lan78xx_set_link_ksettings,
 };
 
 static int lan78xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
@@ -1970,11 +1980,6 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)
        int old_rx_urb_size = dev->rx_urb_size;
        int ret;
 
-       if (new_mtu > MAX_SINGLE_PACKET_SIZE)
-               return -EINVAL;
-
-       if (new_mtu <= 0)
-               return -EINVAL;
        /* no second zero-length packet read wanted after mtu-sized packets */
        if ((ll_mtu % dev->maxpacket) == 0)
                return -EDOM;
@@ -3378,6 +3383,9 @@ static int lan78xx_probe(struct usb_interface *intf,
        if (netdev->mtu > (dev->hard_mtu - netdev->hard_header_len))
                netdev->mtu = dev->hard_mtu - netdev->hard_header_len;
 
+       /* MTU range: 68 - 9000 */
+       netdev->max_mtu = MAX_SINGLE_PACKET_SIZE;
+
        dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0;
        dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1;
        dev->ep_intr = (intf->cur_altsetting)->endpoint + 2;
index 1434e5dd5f9cd2c859ed7a54e4fb2267c8420654..399f7ee57aead0db2b7a5de51d245020bc21b4b8 100644 (file)
@@ -1273,7 +1273,6 @@ static const struct net_device_ops pegasus_netdev_ops = {
        .ndo_set_rx_mode =              pegasus_set_multicast,
        .ndo_get_stats =                pegasus_netdev_stats,
        .ndo_tx_timeout =               pegasus_tx_timeout,
-       .ndo_change_mtu =               eth_change_mtu,
        .ndo_set_mac_address =          eth_mac_addr,
        .ndo_validate_addr =            eth_validate_addr,
 };
index 44d439f50961d676694107017073ca1323543f99..4213c28eeb43e45787621c5b10eef3893635b113 100644 (file)
@@ -4113,14 +4113,12 @@ static int rtl8152_change_mtu(struct net_device *dev, int new_mtu)
        switch (tp->version) {
        case RTL_VER_01:
        case RTL_VER_02:
-               return eth_change_mtu(dev, new_mtu);
+               dev->mtu = new_mtu;
+               return 0;
        default:
                break;
        }
 
-       if (new_mtu < 68 || new_mtu > RTL8153_MAX_MTU)
-               return -EINVAL;
-
        ret = usb_autopm_get_interface(tp->intf);
        if (ret < 0)
                return ret;
@@ -4310,6 +4308,18 @@ static int rtl8152_probe(struct usb_interface *intf,
        netdev->ethtool_ops = &ops;
        netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
 
+       /* MTU range: 68 - 1500 or 9194 */
+       netdev->min_mtu = ETH_MIN_MTU;
+       switch (tp->version) {
+       case RTL_VER_01:
+       case RTL_VER_02:
+               netdev->max_mtu = ETH_DATA_LEN;
+               break;
+       default:
+               netdev->max_mtu = RTL8153_MAX_MTU;
+               break;
+       }
+
        tp->mii.dev = netdev;
        tp->mii.mdio_read = read_mii_word;
        tp->mii.mdio_write = write_mii_word;
@@ -4410,8 +4420,12 @@ static struct usb_device_id rtl8152_table[] = {
        {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)},
        {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
        {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
-       {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7205)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x304f)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3062)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3069)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7205)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x720c)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7214)},
        {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA,  0x09ff)},
        {}
 };
index 7c72bfac89d08df2f6c873ffe0a11e51364e9547..93a1bda1c1e5e1161b2a4f44519e5fe625cf51bd 100644 (file)
@@ -847,7 +847,6 @@ static const struct net_device_ops rtl8150_netdev_ops = {
        .ndo_set_rx_mode        = rtl8150_set_multicast,
        .ndo_set_mac_address    = rtl8150_set_mac_address,
 
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index a251588762ec6aa4053ec8af337e714411ec877c..12071f1582df2c9b4e867e432f972659d3f78dc4 100644 (file)
@@ -165,7 +165,6 @@ struct lsi_umts {
 
 /* Forward definitions */
 static void sierra_sync_timer(unsigned long syncdata);
-static int sierra_net_change_mtu(struct net_device *net, int new_mtu);
 
 /* Our own net device operations structure */
 static const struct net_device_ops sierra_net_device_ops = {
@@ -173,7 +172,7 @@ static const struct net_device_ops sierra_net_device_ops = {
        .ndo_stop               = usbnet_stop,
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
-       .ndo_change_mtu         = sierra_net_change_mtu,
+       .ndo_change_mtu         = usbnet_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -622,15 +621,6 @@ static const struct ethtool_ops sierra_net_ethtool_ops = {
        .nway_reset = usbnet_nway_reset,
 };
 
-/* MTU can not be more than 1500 bytes, enforce it. */
-static int sierra_net_change_mtu(struct net_device *net, int new_mtu)
-{
-       if (new_mtu > SIERRA_NET_MAX_SUPPORTED_MTU)
-               return -EINVAL;
-
-       return usbnet_change_mtu(net, new_mtu);
-}
-
 static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
 {
        int result = 0;
@@ -720,6 +710,7 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
 
        dev->net->hard_header_len += SIERRA_NET_HIP_EXT_HDR_LEN;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+       dev->net->max_mtu = SIERRA_NET_MAX_SUPPORTED_MTU;
 
        /* Set up the netdev */
        dev->net->flags |= IFF_NOARP;
index 9af9799935dbbd4baed06eb03402803e0ce8d9c8..0b17b40d7a4fa2653caf21406c4a6b3b45d868b0 100644 (file)
@@ -925,9 +925,6 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
        struct usbnet *dev = netdev_priv(netdev);
        int ret;
 
-       if (new_mtu > MAX_SINGLE_PACKET_SIZE)
-               return -EINVAL;
-
        ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN);
        if (ret < 0) {
                netdev_warn(dev->net, "Failed to set mac rx frame length\n");
@@ -1448,6 +1445,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->flags |= IFF_MULTICAST;
        dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+       dev->net->max_mtu = MAX_SINGLE_PACKET_SIZE;
        return 0;
 }
 
index d5071e364d40e1dba629a887d67a07c4ff66825c..3de65ea6531a8add927c0a2d7c74e8923c0f3274 100644 (file)
@@ -384,8 +384,6 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
        int             old_hard_mtu = dev->hard_mtu;
        int             old_rx_urb_size = dev->rx_urb_size;
 
-       if (new_mtu <= 0)
-               return -EINVAL;
        // no second zero-length packet read wanted after mtu-sized packets
        if ((ll_mtu % dev->maxpacket) == 0)
                return -EDOM;
@@ -1669,6 +1667,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
         * bind() should set rx_urb_size in that case.
         */
        dev->hard_mtu = net->mtu + net->hard_header_len;
+       net->min_mtu = 0;
+       net->max_mtu = ETH_MAX_MTU;
 
        net->netdev_ops = &usbnet_netdev_ops;
        net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
index fbc853e645318537e41eee115e17961607e394ff..0520952aa096efd4131526ae53cde4bf94786d42 100644 (file)
@@ -23,9 +23,6 @@
 #define DRV_NAME       "veth"
 #define DRV_VERSION    "1.0"
 
-#define MIN_MTU 68             /* Min L3 MTU */
-#define MAX_MTU 65535          /* Max L3 MTU (arbitrary) */
-
 struct pcpu_vstats {
        u64                     packets;
        u64                     bytes;
@@ -216,17 +213,9 @@ static int veth_close(struct net_device *dev)
        return 0;
 }
 
-static int is_valid_veth_mtu(int new_mtu)
+static int is_valid_veth_mtu(int mtu)
 {
-       return new_mtu >= MIN_MTU && new_mtu <= MAX_MTU;
-}
-
-static int veth_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if (!is_valid_veth_mtu(new_mtu))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
+       return mtu >= ETH_MIN_MTU && mtu <= ETH_MAX_MTU;
 }
 
 static int veth_dev_init(struct net_device *dev)
@@ -300,7 +289,6 @@ static const struct net_device_ops veth_netdev_ops = {
        .ndo_open            = veth_open,
        .ndo_stop            = veth_close,
        .ndo_start_xmit      = veth_xmit,
-       .ndo_change_mtu      = veth_change_mtu,
        .ndo_get_stats64     = veth_get_stats64,
        .ndo_set_rx_mode     = veth_set_multicast_list,
        .ndo_set_mac_address = eth_mac_addr,
@@ -337,6 +325,7 @@ static void veth_setup(struct net_device *dev)
                               NETIF_F_HW_VLAN_CTAG_RX |
                               NETIF_F_HW_VLAN_STAG_RX);
        dev->destructor = veth_dev_free;
+       dev->max_mtu = ETH_MAX_MTU;
 
        dev->hw_features = VETH_FEATURES;
        dev->hw_enc_features = VETH_FEATURES;
index fad84f3f41099dce6fb62399b0df9ac6be857318..2cafd12a10752e1e02c28c5ee0a8594ac76833a0 100644 (file)
@@ -1419,17 +1419,6 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
        .set_settings = virtnet_set_settings,
 };
 
-#define MIN_MTU 68
-#define MAX_MTU 65535
-
-static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu < MIN_MTU || new_mtu > MAX_MTU)
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static const struct net_device_ops virtnet_netdev = {
        .ndo_open            = virtnet_open,
        .ndo_stop            = virtnet_close,
@@ -1437,7 +1426,6 @@ static const struct net_device_ops virtnet_netdev = {
        .ndo_validate_addr   = eth_validate_addr,
        .ndo_set_mac_address = virtnet_set_mac_address,
        .ndo_set_rx_mode     = virtnet_set_rx_mode,
-       .ndo_change_mtu      = virtnet_change_mtu,
        .ndo_get_stats64     = virtnet_stats,
        .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
@@ -1748,6 +1736,9 @@ static bool virtnet_validate_features(struct virtio_device *vdev)
        return true;
 }
 
+#define MIN_MTU ETH_MIN_MTU
+#define MAX_MTU ETH_MAX_MTU
+
 static int virtnet_probe(struct virtio_device *vdev)
 {
        int i, err;
@@ -1821,6 +1812,10 @@ static int virtnet_probe(struct virtio_device *vdev)
 
        dev->vlan_features = dev->features;
 
+       /* MTU range: 68 - 65535 */
+       dev->min_mtu = MIN_MTU;
+       dev->max_mtu = MAX_MTU;
+
        /* Configuration may specify what MAC to use.  Otherwise random. */
        if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC))
                virtio_cread_bytes(vdev,
@@ -1875,8 +1870,12 @@ static int virtnet_probe(struct virtio_device *vdev)
                mtu = virtio_cread16(vdev,
                                     offsetof(struct virtio_net_config,
                                              mtu));
-               if (virtnet_change_mtu(dev, mtu))
+               if (mtu < dev->min_mtu) {
                        __virtio_clear_bit(vdev, VIRTIO_NET_F_MTU);
+               } else {
+                       dev->mtu = mtu;
+                       dev->max_mtu = mtu;
+               }
        }
 
        if (vi->any_header_sg)
index ef83ae3b0a44a4c854c02a5a66e048203ee7ce8e..e34b1297c96af96e6a9d6a6841c4bbc24e74254e 100644 (file)
@@ -2972,9 +2972,6 @@ vmxnet3_change_mtu(struct net_device *netdev, int new_mtu)
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
        int err = 0;
 
-       if (new_mtu < VMXNET3_MIN_MTU || new_mtu > VMXNET3_MAX_MTU)
-               return -EINVAL;
-
        netdev->mtu = new_mtu;
 
        /*
@@ -3431,6 +3428,10 @@ vmxnet3_probe_device(struct pci_dev *pdev,
        vmxnet3_set_ethtool_ops(netdev);
        netdev->watchdog_timeo = 5 * HZ;
 
+       /* MTU range: 60 - 9000 */
+       netdev->min_mtu = VMXNET3_MIN_MTU;
+       netdev->max_mtu = VMXNET3_MAX_MTU;
+
        INIT_WORK(&adapter->work, vmxnet3_reset_work);
        set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
 
index f3c2fa3ab0d54197c6e2f3ad27dcf6db7ef84257..cb5cc7c031609fe9d38d571189136fdf298aeca2 100644 (file)
@@ -2388,43 +2388,31 @@ static void vxlan_set_multicast_list(struct net_device *dev)
 {
 }
 
-static int __vxlan_change_mtu(struct net_device *dev,
-                             struct net_device *lowerdev,
-                             struct vxlan_rdst *dst, int new_mtu, bool strict)
+static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
 {
-       int max_mtu = IP_MAX_MTU;
-
-       if (lowerdev)
-               max_mtu = lowerdev->mtu;
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct vxlan_rdst *dst = &vxlan->default_dst;
+       struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
+                                                        dst->remote_ifindex);
+       bool use_ipv6 = false;
 
        if (dst->remote_ip.sa.sa_family == AF_INET6)
-               max_mtu -= VXLAN6_HEADROOM;
-       else
-               max_mtu -= VXLAN_HEADROOM;
-
-       if (new_mtu < 68)
-               return -EINVAL;
+               use_ipv6 = true;
 
-       if (new_mtu > max_mtu) {
-               if (strict)
+       /* This check is different than dev->max_mtu, because it looks at
+        * the lowerdev->mtu, rather than the static dev->max_mtu
+        */
+       if (lowerdev) {
+               int max_mtu = lowerdev->mtu -
+                             (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+               if (new_mtu > max_mtu)
                        return -EINVAL;
-
-               new_mtu = max_mtu;
        }
 
        dev->mtu = new_mtu;
        return 0;
 }
 
-static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
-{
-       struct vxlan_dev *vxlan = netdev_priv(dev);
-       struct vxlan_rdst *dst = &vxlan->default_dst;
-       struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
-                                                        dst->remote_ifindex);
-       return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true);
-}
-
 static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
@@ -2815,6 +2803,10 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
                vxlan_ether_setup(dev);
        }
 
+       /* MTU range: 68 - 65535 */
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = ETH_MAX_MTU;
+
        vxlan->net = src_net;
 
        dst->remote_vni = conf->vni;
@@ -2858,7 +2850,8 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
 #endif
 
                if (!conf->mtu)
-                       dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+                       dev->mtu = lowerdev->mtu -
+                                  (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
 
                needed_headroom = lowerdev->hard_header_len;
        } else if (vxlan_addr_multicast(&dst->remote_ip)) {
@@ -2867,9 +2860,20 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
        }
 
        if (conf->mtu) {
-               err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false);
-               if (err)
-                       return err;
+               int max_mtu = ETH_MAX_MTU;
+
+               if (lowerdev)
+                       max_mtu = lowerdev->mtu;
+
+               max_mtu -= (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+
+               if (conf->mtu < dev->min_mtu || conf->mtu > dev->max_mtu)
+                       return -EINVAL;
+
+               dev->mtu = conf->mtu;
+
+               if (conf->mtu > max_mtu)
+                       dev->mtu = max_mtu;
        }
 
        if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
index 09a50751763b1990f1b778ef62051c06743675c2..2371e078afbbd57ac696467df456c6e55393baaf 100644 (file)
@@ -302,7 +302,6 @@ static void c101_destroy_card(card_t *card)
 static const struct net_device_ops c101_ops = {
        .ndo_open       = c101_open,
        .ndo_stop       = c101_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = c101_ioctl,
 };
index b87fe0a01c69ff3bb53b609632f5016eb8806073..087eb266601fc81f4b62ee95008a7b2ece8353a4 100644 (file)
@@ -432,7 +432,6 @@ module_exit(cosa_exit);
 static const struct net_device_ops cosa_ops = {
        .ndo_open       = cosa_net_open,
        .ndo_stop       = cosa_net_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = cosa_net_ioctl,
        .ndo_tx_timeout = cosa_net_timeout,
index 6292259804634e0c6251e23dd8eb7213f16211fb..7351e5440ed78b74aa383de3d26ae74add0a4499 100644 (file)
@@ -887,7 +887,6 @@ static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz)
 static const struct net_device_ops dscc4_ops = {
        .ndo_open       = dscc4_open,
        .ndo_stop       = dscc4_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = dscc4_ioctl,
        .ndo_tx_timeout = dscc4_tx_timeout,
index 3c9cbf908ec73cd95a75d59a289eef5e68e5f414..03696d35ee9cce109812a8215c4e3b7d118764e5 100644 (file)
@@ -2394,7 +2394,6 @@ fst_init_card(struct fst_card_info *card)
 static const struct net_device_ops fst_ops = {
        .ndo_open       = fst_open,
        .ndo_stop       = fst_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = fst_ioctl,
        .ndo_tx_timeout = fst_tx_timeout,
index 65647533b4014844f1c0b0e7d5ab25b71e0b94ed..e38ce4da3efbf8af30c89556e8a896e1c5314bea 100644 (file)
@@ -992,7 +992,6 @@ static const struct dev_pm_ops uhdlc_pm_ops = {
 static const struct net_device_ops uhdlc_ops = {
        .ndo_open       = uhdlc_open,
        .ndo_stop       = uhdlc_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = uhdlc_ioctl,
 };
index 9bd4aa8083ce787cc93ed5cfe416175b8f2b7d24..7221a53b8b14444fc497a0b3eb5a86f8ece733a9 100644 (file)
@@ -46,14 +46,6 @@ static const char* version = "HDLC support module revision 1.22";
 
 static struct hdlc_proto *first_proto;
 
-int hdlc_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
                    struct packet_type *p, struct net_device *orig_dev)
 {
@@ -237,6 +229,8 @@ static void hdlc_setup_dev(struct net_device *dev)
        dev->flags               = IFF_POINTOPOINT | IFF_NOARP;
        dev->priv_flags          = IFF_WAN_HDLC;
        dev->mtu                 = HDLC_MAX_MTU;
+       dev->min_mtu             = 68;
+       dev->max_mtu             = HDLC_MAX_MTU;
        dev->type                = ARPHRD_RAWHDLC;
        dev->hard_header_len     = 16;
        dev->addr_len            = 0;
@@ -353,7 +347,6 @@ MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
 MODULE_DESCRIPTION("HDLC support module");
 MODULE_LICENSE("GPL v2");
 
-EXPORT_SYMBOL(hdlc_change_mtu);
 EXPORT_SYMBOL(hdlc_start_xmit);
 EXPORT_SYMBOL(hdlc_open);
 EXPORT_SYMBOL(hdlc_close);
index b6e0cfb095d35c716fbdc22c99a4907ca75b33c1..eb915281197efc98a0fae96cc9dcdd2691a21ee3 100644 (file)
@@ -1053,7 +1053,6 @@ static void pvc_setup(struct net_device *dev)
 static const struct net_device_ops pvc_ops = {
        .ndo_open       = pvc_open,
        .ndo_stop       = pvc_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = pvc_xmit,
        .ndo_do_ioctl   = pvc_ioctl,
 };
@@ -1096,6 +1095,8 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
        }
        dev->netdev_ops = &pvc_ops;
        dev->mtu = HDLC_MAX_MTU;
+       dev->min_mtu = 68;
+       dev->max_mtu = HDLC_MAX_MTU;
        dev->priv_flags |= IFF_NO_QUEUE;
        dev->ml_priv = pvc;
 
index 3d741663fd677a42eb2a3823e54412cf8afe7ee0..dd6bb3364ad2330ed662abbaaa192d9d24967f3d 100644 (file)
@@ -180,7 +180,6 @@ static int hostess_attach(struct net_device *dev, unsigned short encoding,
 static const struct net_device_ops hostess_ops = {
        .ndo_open       = hostess_open,
        .ndo_stop       = hostess_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = hostess_ioctl,
 };
index e7bbdb7af53ac7dcbdd21d12705613054efe8626..6a505c26a3e74416c0461b677871a81e2b543041 100644 (file)
@@ -1321,7 +1321,6 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 static const struct net_device_ops hss_hdlc_ops = {
        .ndo_open       = hss_hdlc_open,
        .ndo_stop       = hss_hdlc_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = hss_hdlc_ioctl,
 };
index 299140c04556979b9fc75b2a43211b325c81243a..001b7796740dc3b6a78214cc42fb42978140ab44 100644 (file)
@@ -808,7 +808,6 @@ static int lmc_attach(struct net_device *dev, unsigned short encoding,
 static const struct net_device_ops lmc_ops = {
        .ndo_open       = lmc_open,
        .ndo_stop       = lmc_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = lmc_ioctl,
        .ndo_tx_timeout = lmc_driver_timeout,
index 315bf09d6a2026aea0068eee58b893ef1431fcae..c8f4517db3a0be3dbc82bc382b7941e2f8418158 100644 (file)
@@ -330,7 +330,6 @@ static void n2_destroy_card(card_t *card)
 static const struct net_device_ops n2_ops = {
        .ndo_open       = n2_open,
        .ndo_stop       = n2_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = n2_ioctl,
 };
index db363856e0b52aff1a4f2f6d9ac4416ccd7d031b..e1dd1ec18d64c0a4eb6d16bd5c85d0dec485ee36 100644 (file)
@@ -291,7 +291,6 @@ static void pc300_pci_remove_one(struct pci_dev *pdev)
 static const struct net_device_ops pc300_ops = {
        .ndo_open       = pc300_open,
        .ndo_stop       = pc300_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = pc300_ioctl,
 };
index e8455621390e2abbb4d19f4e7b9a1a1950bcc810..4e437c599e9a5b9384dca958e4efa9395739e471 100644 (file)
@@ -270,7 +270,6 @@ static void pci200_pci_remove_one(struct pci_dev *pdev)
 static const struct net_device_ops pci200_ops = {
        .ndo_open       = pci200_open,
        .ndo_stop       = pci200_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = pci200_ioctl,
 };
index 3a421ca8a4d082de104c12b92949998413de4e50..3f83be98d46925e83adf6d2a97e28e8ab4eb34dd 100644 (file)
@@ -211,7 +211,6 @@ static const struct net_device_ops sbni_netdev_ops = {
        .ndo_start_xmit         = sbni_start_xmit,
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_do_ioctl           = sbni_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 27860b4f59081a46f71ad4f5baa2f7605ef8e17c..fbb5aa2c4d8faf415c2463440f3adbfd5b0721c2 100644 (file)
@@ -174,7 +174,6 @@ static int sealevel_attach(struct net_device *dev, unsigned short encoding,
 static const struct net_device_ops sealevel_ops = {
        .ndo_open       = sealevel_open,
        .ndo_stop       = sealevel_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = sealevel_ioctl,
 };
index a20d688d259570467d83585962815f42be5bd38d..0c7317520ed396a2a2448a21b62e08cd1debdfc4 100644 (file)
@@ -551,7 +551,6 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)
 static const struct net_device_ops wanxl_ops = {
        .ndo_open       = wanxl_open,
        .ndo_stop       = wanxl_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = wanxl_ioctl,
        .ndo_get_stats  = wanxl_get_stats,
index 1bc5e93d2a342181503e85e2f2729d6e983dd31f..878b05d06fc7abc64450d8a46ef842d3375a8f0f 100644 (file)
@@ -124,9 +124,6 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
        unsigned char *xbuff, *rbuff;
        int len;
 
-       if (newmtu > 65534)
-               return -EINVAL;
-
        len = 2 * newmtu;
        xbuff = kmalloc(len + 4, GFP_ATOMIC);
        rbuff = kmalloc(len + 4, GFP_ATOMIC);
@@ -751,6 +748,8 @@ static void x25_asy_setup(struct net_device *dev)
         */
 
        dev->mtu                = SL_MTU;
+       dev->min_mtu            = 0;
+       dev->max_mtu            = 65534;
        dev->netdev_ops         = &x25_asy_netdev_ops;
        dev->watchdog_timeo     = HZ*20;
        dev->hard_header_len    = 0;
index bb74f4b9a02fb5dd3fe1ff1ad0ec112430b46d99..7f64e74d746b790e70900ef831b63438942632c2 100644 (file)
@@ -394,25 +394,6 @@ drop:
 }
 
 
-static
-int i2400m_change_mtu(struct net_device *net_dev, int new_mtu)
-{
-       int result;
-       struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
-       struct device *dev = i2400m_dev(i2400m);
-
-       if (new_mtu >= I2400M_MAX_MTU) {
-               dev_err(dev, "Cannot change MTU to %d (max is %d)\n",
-                       new_mtu, I2400M_MAX_MTU);
-               result = -EINVAL;
-       } else {
-               net_dev->mtu = new_mtu;
-               result = 0;
-       }
-       return result;
-}
-
-
 static
 void i2400m_tx_timeout(struct net_device *net_dev)
 {
@@ -590,7 +571,6 @@ static const struct net_device_ops i2400m_netdev_ops = {
        .ndo_stop = i2400m_stop,
        .ndo_start_xmit = i2400m_hard_start_xmit,
        .ndo_tx_timeout = i2400m_tx_timeout,
-       .ndo_change_mtu = i2400m_change_mtu,
 };
 
 static void i2400m_get_drvinfo(struct net_device *net_dev,
@@ -621,6 +601,8 @@ void i2400m_netdev_setup(struct net_device *net_dev)
        d_fnstart(3, NULL, "(net_dev %p)\n", net_dev);
        ether_setup(net_dev);
        net_dev->mtu = I2400M_MAX_MTU;
+       net_dev->min_mtu = 0;
+       net_dev->max_mtu = I2400M_MAX_MTU;
        net_dev->tx_queue_len = I2400M_TX_QLEN;
        net_dev->features =
                  NETIF_F_VLAN_CHALLENGED
index 8c8edaf1bba612ca3592fbab24077a2ec8b3f1e0..8f5a3f4a43f2d0d215ea116f89417cf21b5c9d51 100644 (file)
@@ -17,6 +17,19 @@ menuconfig WLAN
 
 if WLAN
 
+config WIRELESS_WDS
+       bool "mac80211-based legacy WDS support" if EXPERT
+       help
+         This option enables the deprecated WDS support, the newer
+         mac80211-based 4-addr AP/client support supersedes it with
+         a much better feature set (HT, VHT, ...)
+
+         We plan to remove this option and code, so if you find
+         that you have to enable it, please let us know on the
+         linux-wireless@vger.kernel.org mailing list, so we can
+         help you migrate to 4-addr AP/client (or, if it's really
+         necessary, give up on our plan of removing it).
+
 source "drivers/net/wireless/admtek/Kconfig"
 source "drivers/net/wireless/ath/Kconfig"
 source "drivers/net/wireless/atmel/Kconfig"
index 76297d69f1ed4303ec6595f3ad59ef29ee3137b6..e322b6df0ebcec2a49dbcd843c6dec82c166b24e 100644 (file)
@@ -7881,6 +7881,7 @@ int ath10k_mac_register(struct ath10k *ar)
        ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF);
        ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
        ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
+       ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
 
        if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
                ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
index cfa3fe82ade36086c344cd3453c779733ad0a085..368d9b3138231f7ab4f915dc5459cfdb606d3a31 100644 (file)
@@ -734,9 +734,11 @@ static const struct ieee80211_iface_limit if_limits[] = {
                                 BIT(NL80211_IFTYPE_P2P_GO) },
 };
 
+#ifdef CONFIG_WIRELESS_WDS
 static const struct ieee80211_iface_limit wds_limits[] = {
        { .max = 2048,  .types = BIT(NL80211_IFTYPE_WDS) },
 };
+#endif
 
 #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
 
@@ -774,6 +776,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
                                        BIT(NL80211_CHAN_WIDTH_40),
 #endif
        },
+#ifdef CONFIG_WIRELESS_WDS
        {
                .limits = wds_limits,
                .n_limits = ARRAY_SIZE(wds_limits),
@@ -781,6 +784,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
                .num_different_channels = 1,
                .beacon_int_infra_match = true,
        },
+#endif
 };
 
 #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
@@ -851,7 +855,9 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                        BIT(NL80211_IFTYPE_STATION) |
                        BIT(NL80211_IFTYPE_ADHOC) |
                        BIT(NL80211_IFTYPE_MESH_POINT) |
+#ifdef CONFIG_WIRELESS_WDS
                        BIT(NL80211_IFTYPE_WDS) |
+#endif
                        BIT(NL80211_IFTYPE_OCB);
 
                if (ath9k_is_chanctx_enabled())
index 61de5e9f8ef0745d882aec0f2b329c2f7e2bab8c..d18372cdc8cab60752d995bd8dea71cbcb8753c7 100644 (file)
@@ -41,21 +41,6 @@ static int wil_stop(struct net_device *ndev)
        return wil_down(wil);
 }
 
-static int wil_change_mtu(struct net_device *ndev, int new_mtu)
-{
-       struct wil6210_priv *wil = ndev_to_wil(ndev);
-
-       if (new_mtu < 68 || new_mtu > mtu_max) {
-               wil_err(wil, "invalid MTU %d\n", new_mtu);
-               return -EINVAL;
-       }
-
-       wil_dbg_misc(wil, "change MTU %d -> %d\n", ndev->mtu, new_mtu);
-       ndev->mtu = new_mtu;
-
-       return 0;
-}
-
 static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
 {
        struct wil6210_priv *wil = ndev_to_wil(ndev);
@@ -69,7 +54,6 @@ static const struct net_device_ops wil_netdev_ops = {
        .ndo_start_xmit         = wil_start_xmit,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = wil_change_mtu,
        .ndo_do_ioctl           = wil_do_ioctl,
 };
 
@@ -126,6 +110,7 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
 static void wil_dev_setup(struct net_device *dev)
 {
        ether_setup(dev);
+       dev->max_mtu = mtu_max;
        dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT;
 }
 
index bf2e9a083c0c31be65dc3f5c33e5a71f0015b1d3..eb92d5ab7a27bf3a9e32bfcd319151d8ac78a294 100644 (file)
@@ -1295,14 +1295,6 @@ static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev)
        return &priv->wstats;
 }
 
-static int atmel_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 68) || (new_mtu > 2312))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static int atmel_set_mac_address(struct net_device *dev, void *p)
 {
        struct sockaddr *addr = p;
@@ -1506,7 +1498,6 @@ static const struct file_operations atmel_proc_fops = {
 static const struct net_device_ops atmel_netdev_ops = {
        .ndo_open               = atmel_open,
        .ndo_stop               = atmel_close,
-       .ndo_change_mtu         = atmel_change_mtu,
        .ndo_set_mac_address    = atmel_set_mac_address,
        .ndo_start_xmit         = start_tx,
        .ndo_do_ioctl           = atmel_ioctl,
@@ -1600,6 +1591,10 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
        dev->irq = irq;
        dev->base_addr = port;
 
+       /* MTU range: 68 - 2312 */
+       dev->min_mtu = 68;
+       dev->max_mtu = MAX_WIRELESS_BODY - ETH_FCS_LEN;
+
        SET_NETDEV_DEV(dev, sys_dev);
 
        if ((rc = request_irq(dev->irq, service_interrupt, IRQF_SHARED, dev->name, dev))) {
index 6e5d9095b1956c1d792725591fe79a75fe676f38..52f3541ecbcfe40f3289bbba681503d974900625 100644 (file)
@@ -5591,7 +5591,9 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
                BIT(NL80211_IFTYPE_AP) |
                BIT(NL80211_IFTYPE_MESH_POINT) |
                BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_WIRELESS_WDS
                BIT(NL80211_IFTYPE_WDS) |
+#endif
                BIT(NL80211_IFTYPE_ADHOC);
 
        hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
index 83770d2ea057875ddd75ffb312e9b2f3d28e5e9f..e97ab2b916630e1259ebbb7641f2365363d47f67 100644 (file)
@@ -3838,7 +3838,9 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_AP) |
                BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_WIRELESS_WDS
                BIT(NL80211_IFTYPE_WDS) |
+#endif
                BIT(NL80211_IFTYPE_ADHOC);
        hw->queues = 1; /* FIXME: hardware has more queues */
        hw->max_rates = 2;
index b777e1b2f87aeb06d6c1b527b1b92aee744dd2e1..2295336355dfde23587694ab0ce0a6846f136938 100644 (file)
@@ -414,23 +414,24 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
                                     struct brcmf_cfg80211_vif *vif,
                                     enum nl80211_iftype new_type)
 {
-       int iftype_num[NUM_NL80211_IFTYPES];
        struct brcmf_cfg80211_vif *pos;
        bool check_combos = false;
        int ret = 0;
+       struct iface_combination_params params = {
+               .num_different_channels = 1,
+       };
 
-       memset(&iftype_num[0], 0, sizeof(iftype_num));
        list_for_each_entry(pos, &cfg->vif_list, list)
                if (pos == vif) {
-                       iftype_num[new_type]++;
+                       params.iftype_num[new_type]++;
                } else {
                        /* concurrent interfaces so need check combinations */
                        check_combos = true;
-                       iftype_num[pos->wdev.iftype]++;
+                       params.iftype_num[pos->wdev.iftype]++;
                }
 
        if (check_combos)
-               ret = cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+               ret = cfg80211_check_combinations(cfg->wiphy, &params);
 
        return ret;
 }
@@ -438,15 +439,16 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
 static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
                                  enum nl80211_iftype new_type)
 {
-       int iftype_num[NUM_NL80211_IFTYPES];
        struct brcmf_cfg80211_vif *pos;
+       struct iface_combination_params params = {
+               .num_different_channels = 1,
+       };
 
-       memset(&iftype_num[0], 0, sizeof(iftype_num));
        list_for_each_entry(pos, &cfg->vif_list, list)
-               iftype_num[pos->wdev.iftype]++;
+               params.iftype_num[pos->wdev.iftype]++;
 
-       iftype_num[new_type]++;
-       return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+       params.iftype_num[new_type]++;
+       return cfg80211_check_combinations(cfg->wiphy, &params);
 }
 
 static void convert_key_from_CPU(struct brcmf_wsec_key *key,
index 69b826d229c5b7462e157de2b93ec8bbd4de1f2a..4b040451a9b8049265e4a460c314c893f924ab8d 100644 (file)
@@ -2329,14 +2329,6 @@ static int airo_set_mac_address(struct net_device *dev, void *p)
        return 0;
 }
 
-static int airo_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 68) || (new_mtu > 2400))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static LIST_HEAD(airo_devices);
 
 static void add_airo_dev(struct airo_info *ai)
@@ -2656,7 +2648,6 @@ static const struct net_device_ops airo11_netdev_ops = {
        .ndo_get_stats          = airo_get_stats,
        .ndo_set_mac_address    = airo_set_mac_address,
        .ndo_do_ioctl           = airo_ioctl,
-       .ndo_change_mtu         = airo_change_mtu,
 };
 
 static void wifi_setup(struct net_device *dev)
@@ -2668,6 +2659,8 @@ static void wifi_setup(struct net_device *dev)
        dev->type               = ARPHRD_IEEE80211;
        dev->hard_header_len    = ETH_HLEN;
        dev->mtu                = AIRO_DEF_MTU;
+       dev->min_mtu            = 68;
+       dev->max_mtu            = MIC_MSGLEN_MAX;
        dev->addr_len           = ETH_ALEN;
        dev->tx_queue_len       = 100; 
 
@@ -2754,7 +2747,6 @@ static const struct net_device_ops airo_netdev_ops = {
        .ndo_set_rx_mode        = airo_set_multicast_list,
        .ndo_set_mac_address    = airo_set_mac_address,
        .ndo_do_ioctl           = airo_ioctl,
-       .ndo_change_mtu         = airo_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
@@ -2766,7 +2758,6 @@ static const struct net_device_ops mpi_netdev_ops = {
        .ndo_set_rx_mode        = airo_set_multicast_list,
        .ndo_set_mac_address    = airo_set_mac_address,
        .ndo_do_ioctl           = airo_ioctl,
-       .ndo_change_mtu         = airo_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
@@ -2822,6 +2813,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        dev->irq = irq;
        dev->base_addr = port;
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+       dev->max_mtu = MIC_MSGLEN_MAX;
 
        SET_NETDEV_DEV(dev, dmdev);
 
index bfa542c8d6f1a2b4f98ac2c419326ceb3ac7a17d..64176090b196562008bfd72257b3b980202bf737 100644 (file)
@@ -6035,7 +6035,6 @@ static const struct net_device_ops ipw2100_netdev_ops = {
        .ndo_open               = ipw2100_open,
        .ndo_stop               = ipw2100_close,
        .ndo_start_xmit         = libipw_xmit,
-       .ndo_change_mtu         = libipw_change_mtu,
        .ndo_tx_timeout         = ipw2100_tx_timeout,
        .ndo_set_mac_address    = ipw2100_set_address,
        .ndo_validate_addr      = eth_validate_addr,
@@ -6071,6 +6070,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
        dev->wireless_data = &priv->wireless_data;
        dev->watchdog_timeo = 3 * HZ;
        dev->irq = 0;
+       dev->min_mtu = 68;
+       dev->max_mtu = LIBIPW_DATA_LEN;
 
        /* NOTE: We don't use the wireless_handlers hook
         * in dev as the system will start throwing WX requests
index bfd68612a535d6a8ec39307492131521e489c677..ef9af8a29cad5172c24871a7cb2746a57ccf8cbb 100644 (file)
@@ -11561,7 +11561,6 @@ static const struct net_device_ops ipw_prom_netdev_ops = {
        .ndo_open               = ipw_prom_open,
        .ndo_stop               = ipw_prom_stop,
        .ndo_start_xmit         = ipw_prom_hard_start_xmit,
-       .ndo_change_mtu         = libipw_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -11587,6 +11586,9 @@ static int ipw_prom_alloc(struct ipw_priv *priv)
        priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
        priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops;
 
+       priv->prom_net_dev->min_mtu = 68;
+       priv->prom_net_dev->max_mtu = LIBIPW_DATA_LEN;
+
        priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR;
        SET_NETDEV_DEV(priv->prom_net_dev, &priv->pci_dev->dev);
 
@@ -11619,7 +11621,6 @@ static const struct net_device_ops ipw_netdev_ops = {
        .ndo_set_rx_mode        = ipw_net_set_multicast_list,
        .ndo_set_mac_address    = ipw_net_set_mac_address,
        .ndo_start_xmit         = libipw_xmit,
-       .ndo_change_mtu         = libipw_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
@@ -11729,6 +11730,9 @@ static int ipw_pci_probe(struct pci_dev *pdev,
        net_dev->wireless_handlers = &ipw_wx_handler_def;
        net_dev->ethtool_ops = &ipw_ethtool_ops;
 
+       net_dev->min_mtu = 68;
+       net_dev->max_mtu = LIBIPW_DATA_LEN;
+
        err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group);
        if (err) {
                IPW_ERROR("failed to create sysfs device attributes\n");
index b0571618c2edf2a9b7478aee36c61c4cef915020..b51355134e0480dad28de34ff3540645fe3dc6a2 100644 (file)
@@ -948,7 +948,6 @@ static inline int libipw_is_cck_rate(u8 rate)
 /* libipw.c */
 void free_libipw(struct net_device *dev, int monitor);
 struct net_device *alloc_libipw(int sizeof_priv, int monitor);
-int libipw_change_mtu(struct net_device *dev, int new_mtu);
 
 void libipw_networks_age(struct libipw_device *ieee, unsigned long age_secs);
 
index 60f28740f6afed42ab9e01c1077ae2130646ac69..2332075565f2eba6ec53891ee302759e75293497 100644 (file)
@@ -118,15 +118,6 @@ static void libipw_networks_initialize(struct libipw_device *ieee)
                              &ieee->network_free_list);
 }
 
-int libipw_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-EXPORT_SYMBOL(libipw_change_mtu);
-
 struct net_device *alloc_libipw(int sizeof_priv, int monitor)
 {
        struct libipw_device *ieee;
index 80d4228ba7543ee024bd95b72956595772509d27..1a16b8cb366eb837fd6d081d79c5d9774627726d 100644 (file)
@@ -765,16 +765,6 @@ static void hostap_set_multicast_list(struct net_device *dev)
 }
 
 
-static int prism2_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu < PRISM2_MIN_MTU || new_mtu > PRISM2_MAX_MTU)
-               return -EINVAL;
-
-       dev->mtu = new_mtu;
-       return 0;
-}
-
-
 static void prism2_tx_timeout(struct net_device *dev)
 {
        struct hostap_interface *iface;
@@ -813,7 +803,6 @@ static const struct net_device_ops hostap_netdev_ops = {
        .ndo_do_ioctl           = hostap_ioctl,
        .ndo_set_mac_address    = prism2_set_mac_address,
        .ndo_set_rx_mode        = hostap_set_multicast_list,
-       .ndo_change_mtu         = prism2_change_mtu,
        .ndo_tx_timeout         = prism2_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -826,7 +815,6 @@ static const struct net_device_ops hostap_mgmt_netdev_ops = {
        .ndo_do_ioctl           = hostap_ioctl,
        .ndo_set_mac_address    = prism2_set_mac_address,
        .ndo_set_rx_mode        = hostap_set_multicast_list,
-       .ndo_change_mtu         = prism2_change_mtu,
        .ndo_tx_timeout         = prism2_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -839,7 +827,6 @@ static const struct net_device_ops hostap_master_ops = {
        .ndo_do_ioctl           = hostap_ioctl,
        .ndo_set_mac_address    = prism2_set_mac_address,
        .ndo_set_rx_mode        = hostap_set_multicast_list,
-       .ndo_change_mtu         = prism2_change_mtu,
        .ndo_tx_timeout         = prism2_tx_timeout,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -851,6 +838,8 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
 
        iface = netdev_priv(dev);
        ether_setup(dev);
+       dev->min_mtu = PRISM2_MIN_MTU;
+       dev->max_mtu = PRISM2_MAX_MTU;
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 
        /* kernel callbacks */
index 7afe2004e93064f8954a5dcd8940f06b4f86dab5..9d96b7c928f7655e4a79e4b13717ce0a23357259 100644 (file)
@@ -322,9 +322,6 @@ int orinoco_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct orinoco_private *priv = ndev_priv(dev);
 
-       if ((new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU))
-               return -EINVAL;
-
        /* MTU + encapsulation + header length */
        if ((new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) >
             (priv->nicbuf_size - ETH_HLEN))
@@ -2288,6 +2285,9 @@ int orinoco_if_add(struct orinoco_private *priv,
        dev->base_addr = base_addr;
        dev->irq = irq;
 
+       dev->min_mtu = ORINOCO_MIN_MTU;
+       dev->max_mtu = ORINOCO_MAX_MTU;
+
        SET_NETDEV_DEV(dev, priv->dev);
        ret = register_netdev(dev);
        if (ret)
index 84a42012aeae096806eb0900561f12803707d448..325176d4d796a6041488b0e2cd7fdffe3b2c4a08 100644 (file)
@@ -808,7 +808,6 @@ static const struct net_device_ops islpci_netdev_ops = {
        .ndo_start_xmit         = islpci_eth_transmit,
        .ndo_tx_timeout         = islpci_eth_tx_timeout,
        .ndo_set_mac_address    = prism54_set_mac_address,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 431f13b4faf690c885fbd459b257de5d103406a8..8f366cc097e6f9bd353be3f9729cacaf9452469c 100644 (file)
@@ -587,15 +587,8 @@ struct hwsim_radiotap_ack_hdr {
        __le16 rt_chbitmask;
 } __packed;
 
-/* MAC80211_HWSIM netlinf family */
-static struct genl_family hwsim_genl_family = {
-       .id = GENL_ID_GENERATE,
-       .hdrsize = 0,
-       .name = "MAC80211_HWSIM",
-       .version = 1,
-       .maxattr = HWSIM_ATTR_MAX,
-       .netnsok = true,
-};
+/* MAC80211_HWSIM netlink family */
+static struct genl_family hwsim_genl_family;
 
 enum hwsim_multicast_groups {
        HWSIM_MCGRP_CONFIG,
@@ -2256,35 +2249,51 @@ static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw,
        WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN);
 }
 
+#define HWSIM_COMMON_OPS                                       \
+       .tx = mac80211_hwsim_tx,                                \
+       .start = mac80211_hwsim_start,                          \
+       .stop = mac80211_hwsim_stop,                            \
+       .add_interface = mac80211_hwsim_add_interface,          \
+       .change_interface = mac80211_hwsim_change_interface,    \
+       .remove_interface = mac80211_hwsim_remove_interface,    \
+       .config = mac80211_hwsim_config,                        \
+       .configure_filter = mac80211_hwsim_configure_filter,    \
+       .bss_info_changed = mac80211_hwsim_bss_info_changed,    \
+       .sta_add = mac80211_hwsim_sta_add,                      \
+       .sta_remove = mac80211_hwsim_sta_remove,                \
+       .sta_notify = mac80211_hwsim_sta_notify,                \
+       .set_tim = mac80211_hwsim_set_tim,                      \
+       .conf_tx = mac80211_hwsim_conf_tx,                      \
+       .get_survey = mac80211_hwsim_get_survey,                \
+       CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)      \
+       .ampdu_action = mac80211_hwsim_ampdu_action,            \
+       .flush = mac80211_hwsim_flush,                          \
+       .get_tsf = mac80211_hwsim_get_tsf,                      \
+       .set_tsf = mac80211_hwsim_set_tsf,                      \
+       .get_et_sset_count = mac80211_hwsim_get_et_sset_count,  \
+       .get_et_stats = mac80211_hwsim_get_et_stats,            \
+       .get_et_strings = mac80211_hwsim_get_et_strings,
+
 static const struct ieee80211_ops mac80211_hwsim_ops = {
-       .tx = mac80211_hwsim_tx,
-       .start = mac80211_hwsim_start,
-       .stop = mac80211_hwsim_stop,
-       .add_interface = mac80211_hwsim_add_interface,
-       .change_interface = mac80211_hwsim_change_interface,
-       .remove_interface = mac80211_hwsim_remove_interface,
-       .config = mac80211_hwsim_config,
-       .configure_filter = mac80211_hwsim_configure_filter,
-       .bss_info_changed = mac80211_hwsim_bss_info_changed,
-       .sta_add = mac80211_hwsim_sta_add,
-       .sta_remove = mac80211_hwsim_sta_remove,
-       .sta_notify = mac80211_hwsim_sta_notify,
-       .set_tim = mac80211_hwsim_set_tim,
-       .conf_tx = mac80211_hwsim_conf_tx,
-       .get_survey = mac80211_hwsim_get_survey,
-       CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
-       .ampdu_action = mac80211_hwsim_ampdu_action,
+       HWSIM_COMMON_OPS
        .sw_scan_start = mac80211_hwsim_sw_scan,
        .sw_scan_complete = mac80211_hwsim_sw_scan_complete,
-       .flush = mac80211_hwsim_flush,
-       .get_tsf = mac80211_hwsim_get_tsf,
-       .set_tsf = mac80211_hwsim_set_tsf,
-       .get_et_sset_count = mac80211_hwsim_get_et_sset_count,
-       .get_et_stats = mac80211_hwsim_get_et_stats,
-       .get_et_strings = mac80211_hwsim_get_et_strings,
 };
 
-static struct ieee80211_ops mac80211_hwsim_mchan_ops;
+static const struct ieee80211_ops mac80211_hwsim_mchan_ops = {
+       HWSIM_COMMON_OPS
+       .hw_scan = mac80211_hwsim_hw_scan,
+       .cancel_hw_scan = mac80211_hwsim_cancel_hw_scan,
+       .sw_scan_start = NULL,
+       .sw_scan_complete = NULL,
+       .remain_on_channel = mac80211_hwsim_roc,
+       .cancel_remain_on_channel = mac80211_hwsim_croc,
+       .add_chanctx = mac80211_hwsim_add_chanctx,
+       .remove_chanctx = mac80211_hwsim_remove_chanctx,
+       .change_chanctx = mac80211_hwsim_change_chanctx,
+       .assign_vif_chanctx = mac80211_hwsim_assign_vif_chanctx,
+       .unassign_vif_chanctx = mac80211_hwsim_unassign_vif_chanctx,
+};
 
 struct hwsim_new_radio_params {
        unsigned int channels;
@@ -2791,7 +2800,6 @@ static void mac80211_hwsim_free(void)
 
 static const struct net_device_ops hwsim_netdev_ops = {
        .ndo_start_xmit         = hwsim_mon_xmit,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -3236,6 +3244,18 @@ static const struct genl_ops hwsim_ops[] = {
        },
 };
 
+static struct genl_family hwsim_genl_family __ro_after_init = {
+       .name = "MAC80211_HWSIM",
+       .version = 1,
+       .maxattr = HWSIM_ATTR_MAX,
+       .netnsok = true,
+       .module = THIS_MODULE,
+       .ops = hwsim_ops,
+       .n_ops = ARRAY_SIZE(hwsim_ops),
+       .mcgrps = hwsim_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
+};
+
 static void destroy_radio(struct work_struct *work)
 {
        struct mac80211_hwsim_data *data =
@@ -3283,15 +3303,13 @@ static struct notifier_block hwsim_netlink_notifier = {
        .notifier_call = mac80211_hwsim_netlink_notify,
 };
 
-static int hwsim_init_netlink(void)
+static int __init hwsim_init_netlink(void)
 {
        int rc;
 
        printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
 
-       rc = genl_register_family_with_ops_groups(&hwsim_genl_family,
-                                                 hwsim_ops,
-                                                 hwsim_mcgrps);
+       rc = genl_register_family(&hwsim_genl_family);
        if (rc)
                goto failure;
 
@@ -3360,21 +3378,6 @@ static int __init init_mac80211_hwsim(void)
        if (channels < 1)
                return -EINVAL;
 
-       mac80211_hwsim_mchan_ops = mac80211_hwsim_ops;
-       mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan;
-       mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan;
-       mac80211_hwsim_mchan_ops.sw_scan_start = NULL;
-       mac80211_hwsim_mchan_ops.sw_scan_complete = NULL;
-       mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc;
-       mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc;
-       mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx;
-       mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx;
-       mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx;
-       mac80211_hwsim_mchan_ops.assign_vif_chanctx =
-               mac80211_hwsim_assign_vif_chanctx;
-       mac80211_hwsim_mchan_ops.unassign_vif_chanctx =
-               mac80211_hwsim_unassign_vif_chanctx;
-
        spin_lock_init(&hwsim_radio_lock);
 
        err = register_pernet_device(&hwsim_net_ops);
index 8541cbed786da3b09d5ac08e12cf5b8be4b2cdd5..e3500203715cf6d1f42a7243460ad1878ca10c1d 100644 (file)
@@ -945,7 +945,6 @@ static const struct net_device_ops lbs_netdev_ops = {
        .ndo_start_xmit         = lbs_hard_start_xmit,
        .ndo_set_mac_address    = lbs_set_mac_address,
        .ndo_set_rx_mode        = lbs_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 4e0c5653054bbdc9d313872760c2994f681fd191..236f790e097a4b06412a1a742aa3809cb8d4e52b 100644 (file)
@@ -1362,11 +1362,13 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
        if (rt2x00dev->bcn->limit > 0)
                rt2x00dev->hw->wiphy->interface_modes |=
                    BIT(NL80211_IFTYPE_ADHOC) |
-                   BIT(NL80211_IFTYPE_AP) |
 #ifdef CONFIG_MAC80211_MESH
                    BIT(NL80211_IFTYPE_MESH_POINT) |
 #endif
-                   BIT(NL80211_IFTYPE_WDS);
+#ifdef CONFIG_WIRELESS_WDS
+                   BIT(NL80211_IFTYPE_WDS) |
+#endif
+                   BIT(NL80211_IFTYPE_AP);
 
        rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
 
index 0881ba8535f4e11bec61d029dc58f29a7f0c4500..4fdc7223c894b29671b03403856ffa0c5fb85a97 100644 (file)
@@ -272,7 +272,6 @@ static const struct net_device_ops ray_netdev_ops = {
        .ndo_set_config         = ray_dev_config,
        .ndo_get_stats          = ray_get_stats,
        .ndo_set_rx_mode        = set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 471521a0db7b6634e0f2c36ef8a168116c336f4f..9f39c6cf98fb74fefd27ea16a3775fdb5adf110e 100644 (file)
@@ -6086,6 +6086,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
        ieee80211_hw_set(wl->hw, SUPPORTS_DYNAMIC_PS);
        ieee80211_hw_set(wl->hw, SIGNAL_DBM);
        ieee80211_hw_set(wl->hw, SUPPORTS_PS);
+       ieee80211_hw_set(wl->hw, SUPPORTS_TX_FRAG);
 
        wl->hw->wiphy->cipher_suites = cipher_suites;
        wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
index 932f3f81e8cf3f3cb6b6a51e0e4904ecfc7c23fc..d9d29ab8818460e1c33db89720a45bb0ed9dc50b 100644 (file)
@@ -1853,7 +1853,6 @@ static const struct net_device_ops wl3501_netdev_ops = {
        .ndo_stop               = wl3501_close,
        .ndo_start_xmit         = wl3501_hard_start_xmit,
        .ndo_tx_timeout         = wl3501_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index dea049b2556f337ed1f1504cef7e834882035707..de7ff395977a31820913eb1d43aa2509d979c136 100644 (file)
@@ -1724,7 +1724,6 @@ static const struct net_device_ops zd1201_netdev_ops = {
        .ndo_tx_timeout         = zd1201_tx_timeout,
        .ndo_set_rx_mode        = zd1201_set_multicast,
        .ndo_set_mac_address    = zd1201_set_mac_address,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
index 74dc2bf714280c935d0ba16511a87a863323b19a..e30ffd29b7e913f2514c4c925979ffd474190acc 100644 (file)
@@ -302,7 +302,7 @@ static int xenvif_close(struct net_device *dev)
 static int xenvif_change_mtu(struct net_device *dev, int mtu)
 {
        struct xenvif *vif = netdev_priv(dev);
-       int max = vif->can_sg ? 65535 - VLAN_ETH_HLEN : ETH_DATA_LEN;
+       int max = vif->can_sg ? ETH_MAX_MTU - VLAN_ETH_HLEN : ETH_DATA_LEN;
 
        if (mtu > max)
                return -EINVAL;
@@ -471,6 +471,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 
        dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
 
+       dev->min_mtu = 0;
+       dev->max_mtu = ETH_MAX_MTU - VLAN_ETH_HLEN;
+
        /*
         * Initialise a dummy MAC address. We choose the numerically
         * largest non-broadcast address to prevent the address getting
index e17879dd5d5a18e3efcfe0d64a4fb992d2967b96..7d616b003e894f50a6337caa7aa841decda87f39 100644 (file)
@@ -1329,6 +1329,8 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
        netdev->features |= netdev->hw_features;
 
        netdev->ethtool_ops = &xennet_ethtool_ops;
+       netdev->min_mtu = 0;
+       netdev->max_mtu = XEN_NETIF_MAX_TX_SIZE;
        SET_NETDEV_DEV(netdev, &dev->dev);
 
        np->netdev = netdev;
index ad17fc5883f61f61bc509f6d95754c881fca1c24..ac65f12bcd43c9dca411940ecabbf315e1b8585f 100644 (file)
@@ -1032,9 +1032,6 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu)
        struct ctcm_priv *priv;
        int max_bufsize;
 
-       if (new_mtu < 576 || new_mtu > 65527)
-               return -EINVAL;
-
        priv = dev->ml_priv;
        max_bufsize = priv->channel[CTCM_READ]->max_bufsize;
 
@@ -1123,6 +1120,8 @@ void static ctcm_dev_setup(struct net_device *dev)
        dev->type = ARPHRD_SLIP;
        dev->tx_queue_len = 100;
        dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+       dev->min_mtu = 576;
+       dev->max_mtu = 65527;
 }
 
 /*
index 251db0a02e73c81c275594d0b72b091ced13137b..211b31d9f157dfeb16441d6852b85b319083e095 100644 (file)
@@ -1888,7 +1888,7 @@ lcs_stop_device(struct net_device *dev)
        rc = lcs_stopcard(card);
        if (rc)
                dev_err(&card->dev->dev,
-                       " Shutting down the LCS device failed\n ");
+                       " Shutting down the LCS device failed\n");
        return rc;
 }
 
index b0e8ffdf864b049c1d72797c039b91a6e29d373e..2981024a24387aeb001357834805ba886ad3531e 100644 (file)
@@ -302,8 +302,7 @@ static char *netiucv_printuser(struct iucv_connection *conn)
        if (memcmp(conn->userdata, iucvMagic_ebcdic, 16)) {
                tmp_uid[8] = '\0';
                tmp_udat[16] = '\0';
-               memcpy(tmp_uid, conn->userid, 8);
-               memcpy(tmp_uid, netiucv_printname(tmp_uid, 8), 8);
+               memcpy(tmp_uid, netiucv_printname(conn->userid, 8), 8);
                memcpy(tmp_udat, conn->userdata, 16);
                EBCASC(tmp_udat, 16);
                memcpy(tmp_udat, netiucv_printname(tmp_udat, 16), 16);
@@ -1429,27 +1428,6 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
        return &priv->stats;
 }
 
-/**
- * netiucv_change_mtu
- * @dev: Pointer to interface struct.
- * @new_mtu: The new MTU to use for this interface.
- *
- * Sets MTU of an interface.
- *
- * Returns 0 on success, -EINVAL if MTU is out of valid range.
- *         (valid range is 576 .. NETIUCV_MTU_MAX).
- */
-static int netiucv_change_mtu(struct net_device * dev, int new_mtu)
-{
-       IUCV_DBF_TEXT(trace, 3, __func__);
-       if (new_mtu < 576 || new_mtu > NETIUCV_MTU_MAX) {
-               IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n");
-               return -EINVAL;
-       }
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 /*
  * attributes in sysfs
  */
@@ -1564,21 +1542,21 @@ static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
 {
        struct netiucv_priv *priv = dev_get_drvdata(dev);
        struct net_device *ndev = priv->conn->netdev;
-       char         *e;
-       int          bs1;
+       unsigned int bs1;
+       int rc;
 
        IUCV_DBF_TEXT(trace, 3, __func__);
        if (count >= 39)
                return -EINVAL;
 
-       bs1 = simple_strtoul(buf, &e, 0);
+       rc = kstrtouint(buf, 0, &bs1);
 
-       if (e && (!isspace(*e))) {
-               IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %02x\n",
-                       *e);
+       if (rc == -EINVAL) {
+               IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %s\n",
+                       buf);
                return -EINVAL;
        }
-       if (bs1 > NETIUCV_BUFSIZE_MAX) {
+       if ((rc == -ERANGE) || (bs1 > NETIUCV_BUFSIZE_MAX)) {
                IUCV_DBF_TEXT_(setup, 2,
                        "buffer_write: buffer size %d too large\n",
                        bs1);
@@ -1987,12 +1965,13 @@ static const struct net_device_ops netiucv_netdev_ops = {
        .ndo_stop               = netiucv_close,
        .ndo_get_stats          = netiucv_stats,
        .ndo_start_xmit         = netiucv_tx,
-       .ndo_change_mtu         = netiucv_change_mtu,
 };
 
 static void netiucv_setup_netdevice(struct net_device *dev)
 {
        dev->mtu                 = NETIUCV_MTU_DEFAULT;
+       dev->min_mtu             = 576;
+       dev->max_mtu             = NETIUCV_MTU_MAX;
        dev->destructor          = netiucv_free_netdevice;
        dev->hard_header_len     = NETIUCV_HDRLEN;
        dev->addr_len            = 0;
index 20cf29613043a7f87a29c444ff2be88d87ae3a53..e33558313834dc5e118d478fb5595452f2f6c9ed 100644 (file)
@@ -4202,10 +4202,6 @@ int qeth_change_mtu(struct net_device *dev, int new_mtu)
        sprintf(dbf_text, "%8x", new_mtu);
        QETH_CARD_TEXT(card, 4, dbf_text);
 
-       if (new_mtu < 64)
-               return -EINVAL;
-       if (new_mtu > 65535)
-               return -EINVAL;
        if ((!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) &&
            (!qeth_mtu_is_valid(card, new_mtu)))
                return -EINVAL;
index bb27058fa9f089bdb61a7f4727148b2d8a9bdeed..9c921c2833f16ea29113bd6cc017d9d2ae01b72d 100644 (file)
@@ -1107,6 +1107,8 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
        card->dev->ml_priv = card;
        card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
        card->dev->mtu = card->info.initial_mtu;
+       card->dev->min_mtu = 64;
+       card->dev->max_mtu = ETH_MAX_MTU;
        card->dev->netdev_ops = &qeth_l2_netdev_ops;
        card->dev->ethtool_ops =
                (card->info.type != QETH_CARD_TYPE_OSN) ?
index 272d9e7419be31f5f19297839f04f8fce88f1eac..ac37d050e765bad4e96a72336c41a9ae18236313 100644 (file)
@@ -3140,6 +3140,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
        card->dev->ml_priv = card;
        card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
        card->dev->mtu = card->info.initial_mtu;
+       card->dev->min_mtu = 64;
+       card->dev->max_mtu = ETH_MAX_MTU;
        card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
        card->dev->features |=  NETIF_F_HW_VLAN_CTAG_TX |
                                NETIF_F_HW_VLAN_CTAG_RX |
index 68a5c347fae9a578fdcacbf6c618a0c15f4f6bb6..845affa112f711d8df861d3dd36299377a6ff34a 100644 (file)
@@ -1368,13 +1368,8 @@ static struct genl_multicast_group pmcraid_mcgrps[] = {
        { .name = "events", /* not really used - see ID discussion below */ },
 };
 
-static struct genl_family pmcraid_event_family = {
-       /*
-        * Due to prior multicast group abuse (the code having assumed that
-        * the family ID can be used as a multicast group ID) we need to
-        * statically allocate a family (and thus group) ID.
-        */
-       .id = GENL_ID_PMCRAID,
+static struct genl_family pmcraid_event_family __ro_after_init = {
+       .module = THIS_MODULE,
        .name = "pmcraid",
        .version = 1,
        .maxattr = PMCRAID_AEN_ATTR_MAX,
@@ -1389,7 +1384,7 @@ static struct genl_family pmcraid_event_family = {
  *     0 if the pmcraid_event_family is successfully registered
  *     with netlink generic, non-zero otherwise
  */
-static int pmcraid_netlink_init(void)
+static int __init pmcraid_netlink_init(void)
 {
        int result;
 
index d02e3e31ed293dbe97fbe5327ec670d8fc91ecc9..8130dfe897451268adcea02c420d3aa61c9809aa 100644 (file)
@@ -259,17 +259,6 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu)
 #endif
        int mtu_overhead = ETH_HLEN + ETH_FCS_LEN + vlan_bytes;
 
-       /*
-        * Limit the MTU to make sure the ethernet packets are between
-        * 64 bytes and 65535 bytes.
-        */
-       if ((new_mtu + mtu_overhead < VLAN_ETH_ZLEN) ||
-           (new_mtu + mtu_overhead > OCTEON_MAX_MTU)) {
-               pr_err("MTU must be between %d and %d.\n",
-                      VLAN_ETH_ZLEN - mtu_overhead,
-                      OCTEON_MAX_MTU - mtu_overhead);
-               return -EINVAL;
-       }
        dev->mtu = new_mtu;
 
        if ((interface < 2) &&
@@ -457,7 +446,7 @@ int cvm_oct_common_init(struct net_device *dev)
        dev->ethtool_ops = &cvm_oct_ethtool_ops;
 
        cvm_oct_set_mac_filter(dev);
-       dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);
+       dev_set_mtu(dev, dev->mtu);
 
        /*
         * Zero out stats for port so we won't mistakenly show
@@ -685,6 +674,11 @@ static int cvm_oct_probe(struct platform_device *pdev)
        int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
        int qos;
        struct device_node *pip;
+       int mtu_overhead = ETH_HLEN + ETH_FCS_LEN;
+
+#if IS_ENABLED(CONFIG_VLAN_8021Q)
+       mtu_overhead += VLAN_HLEN;
+#endif
 
        octeon_mdiobus_force_mod_depencency();
 
@@ -783,6 +777,8 @@ static int cvm_oct_probe(struct platform_device *pdev)
                        strcpy(dev->name, "pow%d");
                        for (qos = 0; qos < 16; qos++)
                                skb_queue_head_init(&priv->tx_free_list[qos]);
+                       dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead;
+                       dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead;
 
                        if (register_netdev(dev) < 0) {
                                pr_err("Failed to register ethernet device for POW\n");
@@ -836,6 +832,8 @@ static int cvm_oct_probe(struct platform_device *pdev)
                        for (qos = 0; qos < cvmx_pko_get_num_queues(port);
                             qos++)
                                cvmx_fau_atomic_write32(priv->fau + qos * 4, 0);
+                       dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead;
+                       dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead;
 
                        switch (priv->imode) {
                        /* These types don't support ports to IPD/PKO */
index d976e5e18d50ef7a469e437585da074d7f3b3af0..c9c9821cfc32c662f579eb77358c34ad963d0882 100644 (file)
@@ -145,7 +145,6 @@ static netdev_tx_t mon_xmit(struct sk_buff *skb, struct net_device *dev)
 
 static const struct net_device_ops mon_netdev_ops = {
        .ndo_start_xmit         = mon_xmit,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
index 4c30eea45f89df5792217aa4594b17bd54773e13..5f53fbd565efafb4379b901cef8cefc3066972e5 100644 (file)
@@ -2545,7 +2545,6 @@ static const struct net_device_ops rtl8192_netdev_ops = {
        .ndo_set_rx_mode = _rtl92e_set_multicast,
        .ndo_set_mac_address = _rtl92e_set_mac_adr,
        .ndo_validate_addr = eth_validate_addr,
-       .ndo_change_mtu = eth_change_mtu,
        .ndo_start_xmit = rtllib_xmit,
 };
 
index 457eeb5f5239d502c8407c692d9a0ef2df90bf48..fdb03dccb449031b07231c24ade33fc933b6d77c 100644 (file)
@@ -4930,7 +4930,6 @@ static const struct net_device_ops rtl8192_netdev_ops = {
        .ndo_set_rx_mode        = r8192_set_multicast,
        .ndo_set_mac_address    = r8192_set_mac_adr,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_start_xmit         = ieee80211_xmit,
 };
 
index 062307ad7fed679d40bc3aee4a45b7af4f8f1904..2802b900f8eea39394488b4cd56d6321beab2825 100644 (file)
@@ -2880,7 +2880,6 @@ static const struct net_device_ops slic_netdev_ops = {
        .ndo_get_stats          = slic_get_stats,
        .ndo_set_rx_mode        = slic_mcast_set_list,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_change_mtu         = eth_change_mtu,
 };
 
 static u32 slic_card_locate(struct adapter *adapter)
index cba4433bcd51963d4f50db940dbcf6e31e5ada07..9081b3f8779c122180fb98c4e3906b0774be7095 100644 (file)
@@ -113,12 +113,10 @@ enum net_types {
 
 };
 
-#define                ETH_HEADER_SIZE 14      /* size of ethernet header */
-
 #define                ETH_MIN_DATA_SIZE 46    /* minimum eth data size */
-#define                ETH_MIN_PACKET_SIZE (ETH_HEADER_SIZE + ETH_MIN_DATA_SIZE)
+#define                ETH_MIN_PACKET_SIZE (ETH_HLEN + ETH_MIN_DATA_SIZE)
 
-#define                ETH_MAX_MTU 16384       /* maximum data size */
+#define                VISOR_ETH_MAX_MTU 16384 /* maximum data size */
 
 #ifndef MAX_MACADDR_LEN
 #define MAX_MACADDR_LEN 6      /* number of bytes in MAC address */
@@ -288,7 +286,7 @@ struct net_pkt_xmt {
        int len;        /* full length of data in the packet */
        int num_frags;  /* number of fragments in frags containing data */
        struct phys_info frags[MAX_PHYS_INFO];  /* physical page information */
-       char ethhdr[ETH_HEADER_SIZE];   /* the ethernet header  */
+       char ethhdr[ETH_HLEN];  /* the ethernet header  */
        struct {
                /* these are needed for csum at uisnic end */
                u8 valid;       /* 1 = struct is valid - else ignore */
@@ -323,7 +321,7 @@ struct net_pkt_xmtdone {
  */
 #define RCVPOST_BUF_SIZE 4032
 #define MAX_NET_RCV_CHAIN \
-       ((ETH_MAX_MTU + ETH_HEADER_SIZE + RCVPOST_BUF_SIZE - 1) \
+       ((VISOR_ETH_MAX_MTU + ETH_HLEN + RCVPOST_BUF_SIZE - 1) \
        / RCVPOST_BUF_SIZE)
 
 struct net_pkt_rcvpost {
index 136700756485ffb4dc372ede3c8a8ddee870e895..f8a584bf4a77b909b7a3b0f195cdfb9950f4e845 100644 (file)
@@ -791,7 +791,7 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
         * pointing to
         */
        firstfraglen = skb->len - skb->data_len;
-       if (firstfraglen < ETH_HEADER_SIZE) {
+       if (firstfraglen < ETH_HLEN) {
                spin_unlock_irqrestore(&devdata->priv_lock, flags);
                devdata->busy_cnt++;
                dev_err(&netdev->dev,
@@ -864,7 +864,7 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
        /* copy ethernet header from first frag into ocmdrsp
         * - everything else will be pass in frags & DMA'ed
         */
-       memcpy(cmdrsp->net.xmt.ethhdr, skb->data, ETH_HEADER_SIZE);
+       memcpy(cmdrsp->net.xmt.ethhdr, skb->data, ETH_HLEN);
        /* copy frags info - from skb->data we need to only provide access
         * beyond eth header
         */
index 825a63a7c0e319c582c97b5182b501ff5f821054..4762d38a720e720337389e9054b556163514f5ce 100644 (file)
@@ -669,18 +669,6 @@ static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr)
        return result;
 }
 
-static int wlan_change_mtu(struct net_device *dev, int new_mtu)
-{
-       /* 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap)
-          and another 8 for wep. */
-       if ((new_mtu < 68) || (new_mtu > (2312 - 20 - 8)))
-               return -EINVAL;
-
-       dev->mtu = new_mtu;
-
-       return 0;
-}
-
 static const struct net_device_ops p80211_netdev_ops = {
        .ndo_init = p80211knetdev_init,
        .ndo_open = p80211knetdev_open,
@@ -690,7 +678,6 @@ static const struct net_device_ops p80211_netdev_ops = {
        .ndo_do_ioctl = p80211knetdev_do_ioctl,
        .ndo_set_mac_address = p80211knetdev_set_mac_address,
        .ndo_tx_timeout = p80211knetdev_tx_timeout,
-       .ndo_change_mtu = wlan_change_mtu,
        .ndo_validate_addr = eth_validate_addr,
 };
 
@@ -756,6 +743,11 @@ int wlan_setup(struct wlandevice *wlandev, struct device *physdev)
                wdev->wiphy = wiphy;
                wdev->iftype = NL80211_IFTYPE_STATION;
                netdev->ieee80211_ptr = wdev;
+               netdev->min_mtu = 68;
+               /* 2312 is max 802.11 payload, 20 is overhead,
+                * (ether + llc + snap) and another 8 for wep.
+                */
+               netdev->max_mtu = (2312 - 20 - 8);
 
                netif_stop_queue(netdev);
                netif_carrier_off(netdev);
index 47562509b4892b07b85cb304a3190804c658d6e9..2b3c8564ace8154548349c6a71872f0b1aceeadb 100644 (file)
@@ -147,8 +147,8 @@ static const struct genl_multicast_group tcmu_mcgrps[] = {
 };
 
 /* Our generic netlink family */
-static struct genl_family tcmu_genl_family = {
-       .id = GENL_ID_GENERATE,
+static struct genl_family tcmu_genl_family __ro_after_init = {
+       .module = THIS_MODULE,
        .hdrsize = 0,
        .name = "TCM-USER",
        .version = 1,
index 226b0b4aced6a2e9fd348086259fc517e3f674ee..911fd964c742485847fde04b83254135abcead53 100644 (file)
@@ -2163,8 +2163,8 @@ static const struct genl_multicast_group thermal_event_mcgrps[] = {
        { .name = THERMAL_GENL_MCAST_GROUP_NAME, },
 };
 
-static struct genl_family thermal_event_genl_family = {
-       .id = GENL_ID_GENERATE,
+static struct genl_family thermal_event_genl_family __ro_after_init = {
+       .module = THIS_MODULE,
        .name = THERMAL_GENL_FAMILY_NAME,
        .version = THERMAL_GENL_VERSION,
        .maxattr = THERMAL_GENL_ATTR_MAX,
@@ -2235,7 +2235,7 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz,
 }
 EXPORT_SYMBOL_GPL(thermal_generate_netlink_event);
 
-static int genetlink_init(void)
+static int __init genetlink_init(void)
 {
        return genl_register_family(&thermal_event_genl_family);
 }
index 54cab59e20edf9e34220354c4c2e870f3c35d027..f3932baed07dc3162ceef88f6c1f831ade5d4cfb 100644 (file)
@@ -2711,15 +2711,6 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
        return;
 }
 
-static int gsm_change_mtu(struct net_device *net, int new_mtu)
-{
-       struct gsm_mux_net *mux_net = netdev_priv(net);
-       if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu))
-               return -EINVAL;
-       net->mtu = new_mtu;
-       return 0;
-}
-
 static void gsm_mux_net_init(struct net_device *net)
 {
        static const struct net_device_ops gsm_netdev_ops = {
@@ -2728,7 +2719,6 @@ static void gsm_mux_net_init(struct net_device *net)
                .ndo_start_xmit         = gsm_mux_net_start_xmit,
                .ndo_tx_timeout         = gsm_mux_net_tx_timeout,
                .ndo_get_stats          = gsm_mux_net_get_stats,
-               .ndo_change_mtu         = gsm_change_mtu,
        };
 
        net->netdev_ops = &gsm_netdev_ops;
@@ -2787,6 +2777,8 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)
                return -ENOMEM;
        }
        net->mtu = dlci->gsm->mtu;
+       net->min_mtu = 8;
+       net->max_mtu = dlci->gsm->mtu;
        mux_net = netdev_priv(net);
        mux_net->dlci = dlci;
        kref_init(&mux_net->ref);
index c13e27ecb0b7f441379dd6cec89ed084892fa057..415885c56435c0450149277b1e66f959f0def47e 100644 (file)
@@ -7973,7 +7973,6 @@ static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
 static const struct net_device_ops hdlcdev_ops = {
        .ndo_open       = hdlcdev_open,
        .ndo_stop       = hdlcdev_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = hdlcdev_ioctl,
        .ndo_tx_timeout = hdlcdev_tx_timeout,
index 7aca2d4670e4a3aaf3636acc5f8dd1c3f288bfd3..8267bcf2405ed5734af331a3437b8b8986303a1f 100644 (file)
@@ -1768,7 +1768,6 @@ static void hdlcdev_rx(struct slgt_info *info, char *buf, int size)
 static const struct net_device_ops hdlcdev_ops = {
        .ndo_open       = hdlcdev_open,
        .ndo_stop       = hdlcdev_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = hdlcdev_ioctl,
        .ndo_tx_timeout = hdlcdev_tx_timeout,
index dec156586de1bdfcf9ed1439523a884267ff02df..d66620f7eaa3f1e94adcdf6310d730eed57d3d05 100644 (file)
@@ -1887,7 +1887,6 @@ static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size)
 static const struct net_device_ops hdlcdev_ops = {
        .ndo_open       = hdlcdev_open,
        .ndo_stop       = hdlcdev_close,
-       .ndo_change_mtu = hdlc_change_mtu,
        .ndo_start_xmit = hdlc_start_xmit,
        .ndo_do_ioctl   = hdlcdev_ioctl,
        .ndo_tx_timeout = hdlcdev_tx_timeout,
index 0473d619d5bf64d23154527ee597cc62706ada7c..b4058f0000e4878efae4a475f834d06f16679fdd 100644 (file)
@@ -261,19 +261,10 @@ out:
        return NETDEV_TX_OK;
 }
 
-static int pn_net_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static const struct net_device_ops pn_netdev_ops = {
        .ndo_open       = pn_net_open,
        .ndo_stop       = pn_net_close,
        .ndo_start_xmit = pn_net_xmit,
-       .ndo_change_mtu = pn_net_mtu,
 };
 
 static void pn_net_setup(struct net_device *dev)
@@ -282,6 +273,8 @@ static void pn_net_setup(struct net_device *dev)
        dev->type               = ARPHRD_PHONET;
        dev->flags              = IFF_POINTOPOINT | IFF_NOARP;
        dev->mtu                = PHONET_DEV_MTU;
+       dev->min_mtu            = PHONET_MIN_MTU;
+       dev->max_mtu            = PHONET_MAX_MTU;
        dev->hard_header_len    = 1;
        dev->dev_addr[0]        = PN_MEDIA_USB;
        dev->addr_len           = 1;
index fe1811650dbc3d9fb0fc6a983486cbae3b653475..686067dd8d2c0a5f4a06f22564dc7dbded82136d 100644 (file)
@@ -142,15 +142,6 @@ static inline int qlen(struct usb_gadget *gadget, unsigned qmult)
 
 /* NETWORK DRIVER HOOKUP (to the layer above this driver) */
 
-static int ueth_change_mtu(struct net_device *net, int new_mtu)
-{
-       if (new_mtu <= ETH_HLEN || new_mtu > GETHER_MAX_ETH_FRAME_LEN)
-               return -ERANGE;
-       net->mtu = new_mtu;
-
-       return 0;
-}
-
 static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
 {
        struct eth_dev *dev = netdev_priv(net);
@@ -737,7 +728,6 @@ static const struct net_device_ops eth_netdev_ops = {
        .ndo_open               = eth_open,
        .ndo_stop               = eth_stop,
        .ndo_start_xmit         = eth_start_xmit,
-       .ndo_change_mtu         = ueth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -800,6 +790,10 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
 
        net->ethtool_ops = &ops;
 
+       /* MTU range: 14 - 15412 */
+       net->min_mtu = ETH_HLEN;
+       net->max_mtu = GETHER_MAX_ETH_FRAME_LEN;
+
        dev->gadget = g;
        SET_NETDEV_DEV(net, &g->dev);
        SET_NETDEV_DEVTYPE(net, &gadget_type);
index 1e6e227134d7b5dae4fa3fc43feafeb994bfa708..0643ae44f3427ddc1088cccb6a0a710039cdc6e1 100644 (file)
 static uint32_t dlm_nl_seqnum;
 static uint32_t listener_nlportid;
 
-static struct genl_family family = {
-       .id             = GENL_ID_GENERATE,
-       .name           = DLM_GENL_NAME,
-       .version        = DLM_GENL_VERSION,
-};
+static struct genl_family family;
 
 static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size)
 {
@@ -76,9 +72,17 @@ static struct genl_ops dlm_nl_ops[] = {
        },
 };
 
+static struct genl_family family __ro_after_init = {
+       .name           = DLM_GENL_NAME,
+       .version        = DLM_GENL_VERSION,
+       .ops            = dlm_nl_ops,
+       .n_ops          = ARRAY_SIZE(dlm_nl_ops),
+       .module         = THIS_MODULE,
+};
+
 int __init dlm_netlink_init(void)
 {
-       return genl_register_family_with_ops(&family, dlm_nl_ops);
+       return genl_register_family(&family);
 }
 
 void dlm_netlink_exit(void)
index 8b252673d4540b519e4a46096869ff039246e614..e99b1a72d9a7348abd9d59a37d661ec335bfe73b 100644 (file)
@@ -12,14 +12,8 @@ static const struct genl_multicast_group quota_mcgrps[] = {
 };
 
 /* Netlink family structure for quota */
-static struct genl_family quota_genl_family = {
-       /*
-        * Needed due to multicast group ID abuse - old code assumed
-        * the family ID was also a valid multicast group ID (which
-        * isn't true) and userspace might thus rely on it. Assign a
-        * static ID for this group to make dealing with that easier.
-        */
-       .id = GENL_ID_VFS_DQUOT,
+static struct genl_family quota_genl_family __ro_after_init = {
+       .module = THIS_MODULE,
        .hdrsize = 0,
        .name = "VFS_DQUOT",
        .version = 1,
diff --git a/include/dt-bindings/net/mscc-phy-vsc8531.h b/include/dt-bindings/net/mscc-phy-vsc8531.h
deleted file mode 100644 (file)
index 2383dd2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Device Tree constants for Microsemi VSC8531 PHY
- *
- * Author: Nagaraju Lakkaraju
- *
- * License: Dual MIT/GPL
- * Copyright (c) 2016 Microsemi Corporation
- */
-
-#ifndef _DT_BINDINGS_MSCC_VSC8531_H
-#define _DT_BINDINGS_MSCC_VSC8531_H
-
-/* MAC interface Edge rate control VDDMAC in milli Volts */
-#define MSCC_VDDMAC_3300                3300
-#define MSCC_VDDMAC_2500                2500
-#define MSCC_VDDMAC_1800                1800
-#define MSCC_VDDMAC_1500                1500
-#define MSCC_VDDMAC_MAX                         4
-#define MSCC_SLOWDOWN_MAX               8
-
-#endif
index c201017b573079961e4ca156ca7ebccda225b0ca..edcd96ded8aafaaef9d37dcdb39df124cb1eb6c7 100644 (file)
@@ -319,6 +319,7 @@ extern const struct bpf_func_proto bpf_map_delete_elem_proto;
 
 extern const struct bpf_func_proto bpf_get_prandom_u32_proto;
 extern const struct bpf_func_proto bpf_get_smp_processor_id_proto;
+extern const struct bpf_func_proto bpf_get_numa_node_id_proto;
 extern const struct bpf_func_proto bpf_tail_call_proto;
 extern const struct bpf_func_proto bpf_ktime_get_ns_proto;
 extern const struct bpf_func_proto bpf_get_current_pid_tgid_proto;
index 7035b997aaa57d7955f4d06501804cd09d8ed675..ac5b393ee6b276084d06796004ad15c78839fc3c 100644 (file)
@@ -23,13 +23,13 @@ struct bpf_reg_state {
         * result in a bad access.
         */
        u64 min_value, max_value;
+       u32 id;
        union {
                /* valid when type == CONST_IMM | PTR_TO_STACK | UNKNOWN_VALUE */
                s64 imm;
 
                /* valid when type == PTR_TO_PACKET* */
                struct {
-                       u32 id;
                        u16 off;
                        u16 range;
                };
index e3354b74286ccca4cefc7cbf46d28a2e880d6deb..60def78c4e1221ea75756fd34c07a66abf9fbc16 100644 (file)
@@ -18,6 +18,7 @@
 #define PHY_ID_BCM5421                 0x002060e0
 #define PHY_ID_BCM5464                 0x002060b0
 #define PHY_ID_BCM5461                 0x002060c0
+#define PHY_ID_BCM54612E               0x03625e60
 #define PHY_ID_BCM54616S               0x03625d10
 #define PHY_ID_BCM57780                        0x03625d90
 
 #define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA      0x0800
 
 #define MII_BCM54XX_AUXCTL_MISC_WREN   0x8000
+#define MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW   0x0100
 #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX    0x0200
 #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC     0x7000
 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC        0x0007
 
-#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL      0x0000
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MASK        0x0007
 
 /*
  * Broadcom LED source encodings.  These are used in BCM5461, BCM5481,
index c934d3a96b5e7da7fd7966ddcb34682454100206..2896f93808ae3a8ed962cf1958e72ff2e5f8da3a 100644 (file)
@@ -67,7 +67,7 @@
  *     genl_magic_func.h
  *             generates an entry in the static genl_ops array,
  *             and static register/unregister functions to
- *             genl_register_family_with_ops().
+ *             genl_register_family().
  *
  *     flags and handler:
  *             GENL_op_init( .doit = x, .dumpit = y, .flags = something)
index 9a79f0106da1a66ea0f7f647468fc3fd5c351108..32c22cfb238b79f0955206b5a6d19a509259d8ea 100644 (file)
@@ -26,7 +26,6 @@
 
 #ifdef __KERNEL__
 __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev);
-int fddi_change_mtu(struct net_device *dev, int new_mtu);
 struct net_device *alloc_fddidev(int sizeof_priv);
 #endif
 
index 667c31101b8b91f0b1d17a99a08edd9cf8d29d63..377257d8f7e3557fe1f98eae3a5f906eb68bac44 100644 (file)
@@ -259,16 +259,7 @@ static struct genl_ops ZZZ_genl_ops[] __read_mostly = {
  *                                                                     {{{2
  */
 #define ZZZ_genl_family                CONCAT_(GENL_MAGIC_FAMILY, _genl_family)
-static struct genl_family ZZZ_genl_family __read_mostly = {
-       .id = GENL_ID_GENERATE,
-       .name = __stringify(GENL_MAGIC_FAMILY),
-       .version = GENL_MAGIC_VERSION,
-#ifdef GENL_MAGIC_FAMILY_HDRSZ
-       .hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ),
-#endif
-       .maxattr = ARRAY_SIZE(drbd_tla_nl_policy)-1,
-};
-
+static struct genl_family ZZZ_genl_family;
 /*
  * Magic: define multicast groups
  * Magic: define multicast group registration helper
@@ -302,11 +293,23 @@ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \
 #undef GENL_mc_group
 #define GENL_mc_group(group)
 
+static struct genl_family ZZZ_genl_family __ro_after_init = {
+       .name = __stringify(GENL_MAGIC_FAMILY),
+       .version = GENL_MAGIC_VERSION,
+#ifdef GENL_MAGIC_FAMILY_HDRSZ
+       .hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ),
+#endif
+       .maxattr = ARRAY_SIZE(drbd_tla_nl_policy)-1,
+       .ops = ZZZ_genl_ops,
+       .n_ops = ARRAY_SIZE(ZZZ_genl_ops),
+       .mcgrps = ZZZ_genl_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(ZZZ_genl_mcgrps),
+       .module = THIS_MODULE,
+};
+
 int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
 {
-       return genl_register_family_with_ops_groups(&ZZZ_genl_family,   \
-                                                   ZZZ_genl_ops,       \
-                                                   ZZZ_genl_mcgrps);
+       return genl_register_family(&ZZZ_genl_family);
 }
 
 void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void)
index e31bcd4c7859e5d01405868090246f4f94a984a2..97585d9679f3de7f2dff7f46aa2cb377a63c219e 100644 (file)
@@ -93,8 +93,6 @@ static __inline__ void debug_frame(const struct sk_buff *skb)
 int hdlc_open(struct net_device *dev);
 /* Must be called by hardware driver when HDLC device is being closed */
 void hdlc_close(struct net_device *dev);
-/* May be used by hardware driver */
-int hdlc_change_mtu(struct net_device *dev, int new_mtu);
 /* Must be pointed to by hw driver's dev->netdev_ops->ndo_start_xmit */
 netdev_tx_t hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
index 8ec23fb0b412290c767ab444b564029911ba7786..402f99e328d4e3bbfaf3452b997985fa52fb48af 100644 (file)
@@ -32,7 +32,6 @@ struct hippi_cb {
 };
 
 __be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev);
-int hippi_change_mtu(struct net_device *dev, int new_mtu);
 int hippi_mac_addr(struct net_device *dev, void *p);
 int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p);
 struct net_device *alloc_hippi_dev(int sizeof_priv);
index a80516fd65c8c12f658346be54fee320b5c513b7..fe849329511a7b4e46ddb6d61441b8675131eb1b 100644 (file)
@@ -1576,6 +1576,9 @@ struct ieee80211_vht_operation {
 #define WLAN_AUTH_SHARED_KEY 1
 #define WLAN_AUTH_FT 2
 #define WLAN_AUTH_SAE 3
+#define WLAN_AUTH_FILS_SK 4
+#define WLAN_AUTH_FILS_SK_PFS 5
+#define WLAN_AUTH_FILS_PK 6
 #define WLAN_AUTH_LEAP 128
 
 #define WLAN_AUTH_CHALLENGE_LEN 128
@@ -1960,6 +1963,26 @@ enum ieee80211_eid {
 
        WLAN_EID_VENDOR_SPECIFIC = 221,
        WLAN_EID_QOS_PARAMETER = 222,
+       WLAN_EID_CAG_NUMBER = 237,
+       WLAN_EID_AP_CSN = 239,
+       WLAN_EID_FILS_INDICATION = 240,
+       WLAN_EID_DILS = 241,
+       WLAN_EID_FRAGMENT = 242,
+       WLAN_EID_EXTENSION = 255
+};
+
+/* Element ID Extensions for Element ID 255 */
+enum ieee80211_eid_ext {
+       WLAN_EID_EXT_ASSOC_DELAY_INFO = 1,
+       WLAN_EID_EXT_FILS_REQ_PARAMS = 2,
+       WLAN_EID_EXT_FILS_KEY_CONFIRM = 3,
+       WLAN_EID_EXT_FILS_SESSION = 4,
+       WLAN_EID_EXT_FILS_HLP_CONTAINER = 5,
+       WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN = 6,
+       WLAN_EID_EXT_KEY_DELIVERY = 7,
+       WLAN_EID_EXT_FILS_WRAPPED_DATA = 8,
+       WLAN_EID_EXT_FILS_PUBLIC_KEY = 12,
+       WLAN_EID_EXT_FILS_NONCE = 13,
 };
 
 /* Action category code */
@@ -2073,6 +2096,9 @@ enum ieee80211_key_len {
 #define IEEE80211_GCMP_MIC_LEN         16
 #define IEEE80211_GCMP_PN_LEN          6
 
+#define FILS_NONCE_LEN                 16
+#define FILS_MAX_KEK_LEN               64
+
 /* Public action codes */
 enum ieee80211_pub_actioncode {
        WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
index 91ee3643ccc8df3f8d244b6dd5f47526ea688274..20ce8df115ac4ce92903ab0f8b5b51fb2e983d1e 100644 (file)
@@ -1456,7 +1456,6 @@ enum netdev_priv_flags {
  *     @ptype_specific: Device-specific, protocol-specific packet handlers
  *
  *     @adj_list:      Directly linked devices, like slaves for bonding
- *     @all_adj_list:  All linked devices, *including* neighbours
  *     @features:      Currently active device features
  *     @hw_features:   User-changeable features
  *
@@ -1506,6 +1505,8 @@ enum netdev_priv_flags {
  *     @if_port:       Selectable AUI, TP, ...
  *     @dma:           DMA channel
  *     @mtu:           Interface MTU value
+ *     @min_mtu:       Interface Minimum MTU value
+ *     @max_mtu:       Interface Maximum MTU value
  *     @type:          Interface hardware type
  *     @hard_header_len: Maximum hardware header length.
  *
@@ -1673,11 +1674,6 @@ struct net_device {
                struct list_head lower;
        } adj_list;
 
-       struct {
-               struct list_head upper;
-               struct list_head lower;
-       } all_adj_list;
-
        netdev_features_t       features;
        netdev_features_t       hw_features;
        netdev_features_t       wanted_features;
@@ -1726,6 +1722,8 @@ struct net_device {
        unsigned char           dma;
 
        unsigned int            mtu;
+       unsigned int            min_mtu;
+       unsigned int            max_mtu;
        unsigned short          type;
        unsigned short          hard_header_len;
 
@@ -2686,71 +2684,6 @@ static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb,
        remcsum_unadjust((__sum16 *)ptr, grc->delta);
 }
 
-struct skb_csum_offl_spec {
-       __u16           ipv4_okay:1,
-                       ipv6_okay:1,
-                       encap_okay:1,
-                       ip_options_okay:1,
-                       ext_hdrs_okay:1,
-                       tcp_okay:1,
-                       udp_okay:1,
-                       sctp_okay:1,
-                       vlan_okay:1,
-                       no_encapped_ipv6:1,
-                       no_not_encapped:1;
-};
-
-bool __skb_csum_offload_chk(struct sk_buff *skb,
-                           const struct skb_csum_offl_spec *spec,
-                           bool *csum_encapped,
-                           bool csum_help);
-
-static inline bool skb_csum_offload_chk(struct sk_buff *skb,
-                                       const struct skb_csum_offl_spec *spec,
-                                       bool *csum_encapped,
-                                       bool csum_help)
-{
-       if (skb->ip_summed != CHECKSUM_PARTIAL)
-               return false;
-
-       return __skb_csum_offload_chk(skb, spec, csum_encapped, csum_help);
-}
-
-static inline bool skb_csum_offload_chk_help(struct sk_buff *skb,
-                                            const struct skb_csum_offl_spec *spec)
-{
-       bool csum_encapped;
-
-       return skb_csum_offload_chk(skb, spec, &csum_encapped, true);
-}
-
-static inline bool skb_csum_off_chk_help_cmn(struct sk_buff *skb)
-{
-       static const struct skb_csum_offl_spec csum_offl_spec = {
-               .ipv4_okay = 1,
-               .ip_options_okay = 1,
-               .ipv6_okay = 1,
-               .vlan_okay = 1,
-               .tcp_okay = 1,
-               .udp_okay = 1,
-       };
-
-       return skb_csum_offload_chk_help(skb, &csum_offl_spec);
-}
-
-static inline bool skb_csum_off_chk_help_cmn_v4_only(struct sk_buff *skb)
-{
-       static const struct skb_csum_offl_spec csum_offl_spec = {
-               .ipv4_okay = 1,
-               .ip_options_okay = 1,
-               .tcp_okay = 1,
-               .udp_okay = 1,
-               .vlan_okay = 1,
-       };
-
-       return skb_csum_offload_chk_help(skb, &csum_offl_spec);
-}
-
 static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
                                  unsigned short type,
                                  const void *daddr, const void *saddr,
@@ -3869,12 +3802,13 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
             updev; \
             updev = netdev_upper_get_next_dev_rcu(dev, &(iter)))
 
-/* iterate through upper list, must be called under RCU read lock */
-#define netdev_for_each_all_upper_dev_rcu(dev, updev, iter) \
-       for (iter = &(dev)->all_adj_list.upper, \
-            updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)); \
-            updev; \
-            updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)))
+int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
+                                 int (*fn)(struct net_device *upper_dev,
+                                           void *data),
+                                 void *data);
+
+bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
+                                 struct net_device *upper_dev);
 
 void *netdev_lower_get_next_private(struct net_device *dev,
                                    struct list_head **iter);
@@ -3907,17 +3841,14 @@ struct net_device *netdev_all_lower_get_next(struct net_device *dev,
 struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
                                                 struct list_head **iter);
 
-#define netdev_for_each_all_lower_dev(dev, ldev, iter) \
-       for (iter = (dev)->all_adj_list.lower.next, \
-            ldev = netdev_all_lower_get_next(dev, &(iter)); \
-            ldev; \
-            ldev = netdev_all_lower_get_next(dev, &(iter)))
-
-#define netdev_for_each_all_lower_dev_rcu(dev, ldev, iter) \
-       for (iter = &(dev)->all_adj_list.lower, \
-            ldev = netdev_all_lower_get_next_rcu(dev, &(iter)); \
-            ldev; \
-            ldev = netdev_all_lower_get_next_rcu(dev, &(iter)))
+int netdev_walk_all_lower_dev(struct net_device *dev,
+                             int (*fn)(struct net_device *lower_dev,
+                                       void *data),
+                             void *data);
+int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
+                                 int (*fn)(struct net_device *lower_dev,
+                                           void *data),
+                                 void *data);
 
 void *netdev_adjacent_get_private(struct list_head *adj_list);
 void *netdev_lower_get_first_private_rcu(struct net_device *dev);
@@ -3994,19 +3925,6 @@ static inline bool can_checksum_protocol(netdev_features_t features,
        }
 }
 
-/* Map an ethertype into IP protocol if possible */
-static inline int eproto_to_ipproto(int eproto)
-{
-       switch (eproto) {
-       case htons(ETH_P_IP):
-               return IPPROTO_IP;
-       case htons(ETH_P_IPV6):
-               return IPPROTO_IPV6;
-       default:
-               return -1;
-       }
-}
-
 #ifdef CONFIG_BUG
 void netdev_rx_csum_fault(struct net_device *dev);
 #else
index e25f1830fbcfbcfc34f76fc4f16c882109b736c6..e7e1fd3825646090ee3e4eeaae13d3f43d3cf2f2 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/mod_devicetable.h>
+#include <linux/phy_led_triggers.h>
 
 #include <linux/atomic.h>
 
@@ -84,6 +85,21 @@ typedef enum {
        PHY_INTERFACE_MODE_MAX,
 } phy_interface_t;
 
+/**
+ * phy_supported_speeds - return all speeds currently supported by a phy device
+ * @phy: The phy device to return supported speeds of.
+ * @speeds: buffer to store supported speeds in.
+ * @size: size of speeds buffer.
+ *
+ * Description: Returns the number of supported speeds, and
+ * fills the speeds * buffer with the supported speeds. If speeds buffer is
+ * too small to contain * all currently supported speeds, will return as
+ * many speeds as can fit.
+ */
+unsigned int phy_supported_speeds(struct phy_device *phy,
+                                     unsigned int *speeds,
+                                     unsigned int size);
+
 /**
  * It maps 'enum phy_interface_t' found in include/linux/phy.h
  * into the device tree binding of 'phy-mode', so that Ethernet
@@ -343,7 +359,7 @@ struct phy_c45_device_ids {
  * giving up on the current attempt at acquiring a link
  * irq: IRQ number of the PHY's interrupt (-1 if none)
  * phy_timer: The timer for handling the state machine
- * phy_queue: A work_queue for the interrupt
+ * phy_queue: A work_queue for the phy_mac_interrupt
  * attached_dev: The attached enet driver's device instance ptr
  * adjust_link: Callback for the enet controller to respond to
  * changes in the link state.
@@ -405,6 +421,12 @@ struct phy_device {
 
        int link_timeout;
 
+#ifdef CONFIG_LED_TRIGGER_PHY
+       struct phy_led_trigger *phy_led_triggers;
+       unsigned int phy_num_led_triggers;
+       struct phy_led_trigger *last_triggered;
+#endif
+
        /*
         * Interrupt number for this PHY
         * -1 means no interrupt
@@ -802,7 +824,8 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner);
 int phy_drivers_register(struct phy_driver *new_driver, int n,
                         struct module *owner);
 void phy_state_machine(struct work_struct *work);
-void phy_change(struct work_struct *work);
+void phy_change(struct phy_device *phydev);
+void phy_change_work(struct work_struct *work);
 void phy_mac_interrupt(struct phy_device *phydev, int new_link);
 void phy_start_machine(struct phy_device *phydev);
 void phy_stop_machine(struct phy_device *phydev);
diff --git a/include/linux/phy_led_triggers.h b/include/linux/phy_led_triggers.h
new file mode 100644 (file)
index 0000000..a2daea0
--- /dev/null
@@ -0,0 +1,51 @@
+/* Copyright (C) 2016 National Instruments Corp.
+ *
+ * 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 Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __PHY_LED_TRIGGERS
+#define __PHY_LED_TRIGGERS
+
+struct phy_device;
+
+#ifdef CONFIG_LED_TRIGGER_PHY
+
+#include <linux/leds.h>
+
+#define PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE      10
+#define PHY_MII_BUS_ID_SIZE    (20 - 3)
+
+#define PHY_LINK_LED_TRIGGER_NAME_SIZE (PHY_MII_BUS_ID_SIZE + \
+                                      FIELD_SIZEOF(struct mdio_device, addr)+\
+                                      PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE)
+
+struct phy_led_trigger {
+       struct led_trigger trigger;
+       char name[PHY_LINK_LED_TRIGGER_NAME_SIZE];
+       unsigned int speed;
+};
+
+
+extern int phy_led_triggers_register(struct phy_device *phy);
+extern void phy_led_triggers_unregister(struct phy_device *phy);
+extern void phy_led_trigger_change_speed(struct phy_device *phy);
+
+#else
+
+static inline int phy_led_triggers_register(struct phy_device *phy)
+{
+       return 0;
+}
+static inline void phy_led_triggers_unregister(struct phy_device *phy) { }
+static inline void phy_led_trigger_change_speed(struct phy_device *phy) { }
+
+#endif
+
+#endif
index 33c24ebc9b7f7be724eb02b40ff23a4ab54558e3..15130805d792dd7918bf8e04dca33fa84cd238d7 100644 (file)
@@ -23,6 +23,7 @@ struct qed_dev_eth_info {
 
        u8      port_mac[ETH_ALEN];
        u8      num_vlan_filters;
+       u16     num_mac_filters;
 
        /* Legacy VF - this affects the datapath, so qede has to know */
        bool is_legacy;
@@ -129,7 +130,7 @@ struct qed_tunn_params {
 
 struct qed_eth_cb_ops {
        struct qed_common_cb_ops common;
-       void (*force_mac) (void *dev, u8 *mac);
+       void (*force_mac) (void *dev, u8 *mac, bool forced);
 };
 
 #ifdef CONFIG_DCB
index 32810f279f8e4f097d678fb3bb587254f42d7a00..cc6e23eaac91b1930d059b82b3bc6924653f80c2 100644 (file)
@@ -1087,7 +1087,7 @@ __skb_set_sw_hash(struct sk_buff *skb, __u32 hash, bool is_l4)
 }
 
 void __skb_get_hash(struct sk_buff *skb);
-u32 __skb_get_hash_symmetric(struct sk_buff *skb);
+u32 __skb_get_hash_symmetric(const struct sk_buff *skb);
 u32 skb_get_poff(const struct sk_buff *skb);
 u32 __skb_get_poff(const struct sk_buff *skb, void *data,
                   const struct flow_keys *keys, int hlen);
index e302c447e057a98b0ba47b5bc73acd816b9dc7f7..129bc674dcf5df4ed3b2e184391fda0ada071618 100644 (file)
@@ -39,6 +39,7 @@ struct smc91x_platdata {
        unsigned long flags;
        unsigned char leda;
        unsigned char ledb;
+       bool pxa_u16_align4;    /* PXA buggy u16 writes on 4*n+2 addresses */
 };
 
 #endif /* __SMC91X_H__ */
index 14b51d739c3b39d5d9b8f0b934d3926841cdce69..2019310cf135d2f22727bd6554a76b3c8929fc87 100644 (file)
@@ -771,6 +771,30 @@ struct cfg80211_csa_settings {
        u8 count;
 };
 
+/**
+ * struct iface_combination_params - input parameters for interface combinations
+ *
+ * Used to pass interface combination parameters
+ *
+ * @num_different_channels: the number of different channels we want
+ *     to use for verification
+ * @radar_detect: a bitmap where each bit corresponds to a channel
+ *     width where radar detection is needed, as in the definition of
+ *     &struct ieee80211_iface_combination.@radar_detect_widths
+ * @iftype_num: array with the number of interfaces of each interface
+ *     type.  The index is the interface type as specified in &enum
+ *     nl80211_iftype.
+ * @new_beacon_int: set this to the beacon interval of a new interface
+ *     that's not operating yet, if such is to be checked as part of
+ *     the verification
+ */
+struct iface_combination_params {
+       int num_different_channels;
+       u8 radar_detect;
+       int iftype_num[NUM_NL80211_IFTYPES];
+       u32 new_beacon_int;
+};
+
 /**
  * enum station_parameters_apply_mask - station parameter values to apply
  * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
@@ -1761,9 +1785,11 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
  * @key_len: length of WEP key for shared key authentication
  * @key_idx: index of WEP key for shared key authentication
  * @key: WEP key for shared key authentication
- * @sae_data: Non-IE data to use with SAE or %NULL. This starts with
- *     Authentication transaction sequence number field.
- * @sae_data_len: Length of sae_data buffer in octets
+ * @auth_data: Fields and elements in Authentication frames. This contains
+ *     the authentication frame body (non-IE and IE data), excluding the
+ *     Authentication algorithm number, i.e., starting at the Authentication
+ *     transaction sequence number field.
+ * @auth_data_len: Length of auth_data buffer in octets
  */
 struct cfg80211_auth_request {
        struct cfg80211_bss *bss;
@@ -1772,8 +1798,8 @@ struct cfg80211_auth_request {
        enum nl80211_auth_type auth_type;
        const u8 *key;
        u8 key_len, key_idx;
-       const u8 *sae_data;
-       size_t sae_data_len;
+       const u8 *auth_data;
+       size_t auth_data_len;
 };
 
 /**
@@ -1814,6 +1840,12 @@ enum cfg80211_assoc_req_flags {
  * @ht_capa_mask:  The bits of ht_capa which are to be used.
  * @vht_capa: VHT capability override
  * @vht_capa_mask: VHT capability mask indicating which fields to use
+ * @fils_kek: FILS KEK for protecting (Re)Association Request/Response frame or
+ *     %NULL if FILS is not used.
+ * @fils_kek_len: Length of fils_kek in octets
+ * @fils_nonces: FILS nonces (part of AAD) for protecting (Re)Association
+ *     Request/Response frame or %NULL if FILS is not used. This field starts
+ *     with 16 octets of STA Nonce followed by 16 octets of AP Nonce.
  */
 struct cfg80211_assoc_request {
        struct cfg80211_bss *bss;
@@ -1825,6 +1857,9 @@ struct cfg80211_assoc_request {
        struct ieee80211_ht_cap ht_capa;
        struct ieee80211_ht_cap ht_capa_mask;
        struct ieee80211_vht_cap vht_capa, vht_capa_mask;
+       const u8 *fils_kek;
+       size_t fils_kek_len;
+       const u8 *fils_nonces;
 };
 
 /**
@@ -2015,6 +2050,18 @@ struct cfg80211_connect_params {
        const u8 *prev_bssid;
 };
 
+/**
+ * enum cfg80211_connect_params_changed - Connection parameters being updated
+ *
+ * This enum provides information of all connect parameters that
+ * have to be updated as part of update_connect_params() call.
+ *
+ * @UPDATE_ASSOC_IES: Indicates whether association request IEs are updated
+ */
+enum cfg80211_connect_params_changed {
+       UPDATE_ASSOC_IES                = BIT(0),
+};
+
 /**
  * enum wiphy_params_flags - set_wiphy_params bitfield values
  * @WIPHY_PARAM_RETRY_SHORT: wiphy->retry_short has changed
@@ -2536,9 +2583,18 @@ struct cfg80211_nan_func {
  *     cases, the result of roaming is indicated with a call to
  *     cfg80211_roamed() or cfg80211_roamed_bss().
  *     (invoked with the wireless_dev mutex held)
- * @disconnect: Disconnect from the BSS/ESS. Once done, call
- *     cfg80211_disconnected().
+ * @update_connect_params: Update the connect parameters while connected to a
+ *     BSS. The updated parameters can be used by driver/firmware for
+ *     subsequent BSS selection (roaming) decisions and to form the
+ *     Authentication/(Re)Association Request frames. This call does not
+ *     request an immediate disassociation or reassociation with the current
+ *     BSS, i.e., this impacts only subsequent (re)associations. The bits in
+ *     changed are defined in &enum cfg80211_connect_params_changed.
  *     (invoked with the wireless_dev mutex held)
+ * @disconnect: Disconnect from the BSS/ESS or stop connection attempts if
+ *      connection is in progress. Once done, call cfg80211_disconnected() in
+ *      case connection was already established (invoked with the
+ *      wireless_dev mutex held), otherwise call cfg80211_connect_timeout().
  *
  * @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
  *     cfg80211_ibss_joined(), also call that function when changing BSSID due
@@ -2706,6 +2762,8 @@ struct cfg80211_nan_func {
  * @nan_change_conf: changes NAN configuration. The changed parameters must
  *     be specified in @changes (using &enum cfg80211_nan_conf_changes);
  *     All other parameters must be ignored.
+ *
+ * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
  */
 struct cfg80211_ops {
        int     (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2820,6 +2878,10 @@ struct cfg80211_ops {
 
        int     (*connect)(struct wiphy *wiphy, struct net_device *dev,
                           struct cfg80211_connect_params *sme);
+       int     (*update_connect_params)(struct wiphy *wiphy,
+                                        struct net_device *dev,
+                                        struct cfg80211_connect_params *sme,
+                                        u32 changed);
        int     (*disconnect)(struct wiphy *wiphy, struct net_device *dev,
                              u16 reason_code);
 
@@ -2982,6 +3044,10 @@ struct cfg80211_ops {
                                   struct wireless_dev *wdev,
                                   struct cfg80211_nan_conf *conf,
                                   u32 changes);
+
+       int     (*set_multicast_to_unicast)(struct wiphy *wiphy,
+                                           struct net_device *dev,
+                                           const bool enabled);
 };
 
 /*
@@ -3080,6 +3146,12 @@ struct ieee80211_iface_limit {
  *     only in special cases.
  * @radar_detect_widths: bitmap of channel widths supported for radar detection
  * @radar_detect_regions: bitmap of regions supported for radar detection
+ * @beacon_int_min_gcd: This interface combination supports different
+ *     beacon intervals.
+ *     = 0 - all beacon intervals for different interface must be same.
+ *     > 0 - any beacon interval for the interface part of this combination AND
+ *           *GCD* of all beacon intervals from beaconing interfaces of this
+ *           combination must be greater or equal to this value.
  *
  * With this structure the driver can describe which interface
  * combinations it supports concurrently.
@@ -3145,6 +3217,7 @@ struct ieee80211_iface_combination {
        bool beacon_int_infra_match;
        u8 radar_detect_widths;
        u8 radar_detect_regions;
+       u32 beacon_int_min_gcd;
 };
 
 struct ieee80211_txrx_stypes {
@@ -3752,8 +3825,8 @@ struct cfg80211_cached_keys;
  * @beacon_interval: beacon interval used on this device for transmitting
  *     beacons, 0 when not valid
  * @address: The address for this device, valid only if @netdev is %NULL
- * @p2p_started: true if this is a P2P Device that has been started
- * @nan_started: true if this is a NAN interface that has been started
+ * @is_running: true if this is a non-netdev device that has been started, e.g.
+ *     the P2P Device.
  * @cac_started: true if DFS channel availability check has been started
  * @cac_start_time: timestamp (jiffies) when the dfs state was entered.
  * @cac_time_ms: CAC time in ms
@@ -3785,7 +3858,7 @@ struct wireless_dev {
 
        struct mutex mtx;
 
-       bool use_4addr, p2p_started, nan_started;
+       bool use_4addr, is_running;
 
        u8 address[ETH_ALEN] __aligned(sizeof(u16));
 
@@ -3842,6 +3915,13 @@ static inline u8 *wdev_address(struct wireless_dev *wdev)
        return wdev->address;
 }
 
+static inline bool wdev_running(struct wireless_dev *wdev)
+{
+       if (wdev->netdev)
+               return netif_running(wdev->netdev);
+       return wdev->is_running;
+}
+
 /**
  * wdev_priv - return wiphy priv from wireless_dev
  *
@@ -4162,6 +4242,27 @@ static inline const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
        return cfg80211_find_ie_match(eid, ies, len, NULL, 0, 0);
 }
 
+/**
+ * cfg80211_find_ext_ie - find information element with EID Extension in data
+ *
+ * @ext_eid: element ID Extension
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * Return: %NULL if the extended element ID could not be found or if
+ * the element is invalid (claims to be longer than the given
+ * data), or a pointer to the first byte of the requested
+ * element, that is the byte containing the element ID.
+ *
+ * Note: There are no checks on the element length other than
+ * having to fit into the given data.
+ */
+static inline const u8 *cfg80211_find_ext_ie(u8 ext_eid, const u8 *ies, int len)
+{
+       return cfg80211_find_ie_match(WLAN_EID_EXTENSION, ies, len,
+                                     &ext_eid, 1, 2);
+}
+
 /**
  * cfg80211_find_vendor_ie - find vendor specific information element in data
  *
@@ -4562,7 +4663,8 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
  *     moves to cfg80211 in this call
  * @buf: authentication frame (header + body)
  * @len: length of the frame data
- * @uapsd_queues: bitmap of ACs configured to uapsd. -1 if n/a.
+ * @uapsd_queues: bitmap of queues configured for uapsd. Same format
+ *     as the AC bitmap in the QoS info field
  *
  * After being asked to associate via cfg80211_ops::assoc() the driver must
  * call either this function or cfg80211_auth_timeout().
@@ -5598,36 +5700,20 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy);
  * cfg80211_check_combinations - check interface combinations
  *
  * @wiphy: the wiphy
- * @num_different_channels: the number of different channels we want
- *     to use for verification
- * @radar_detect: a bitmap where each bit corresponds to a channel
- *     width where radar detection is needed, as in the definition of
- *     &struct ieee80211_iface_combination.@radar_detect_widths
- * @iftype_num: array with the numbers of interfaces of each interface
- *     type.  The index is the interface type as specified in &enum
- *     nl80211_iftype.
+ * @params: the interface combinations parameter
  *
  * This function can be called by the driver to check whether a
  * combination of interfaces and their types are allowed according to
  * the interface combinations.
  */
 int cfg80211_check_combinations(struct wiphy *wiphy,
-                               const int num_different_channels,
-                               const u8 radar_detect,
-                               const int iftype_num[NUM_NL80211_IFTYPES]);
+                               struct iface_combination_params *params);
 
 /**
  * cfg80211_iter_combinations - iterate over matching combinations
  *
  * @wiphy: the wiphy
- * @num_different_channels: the number of different channels we want
- *     to use for verification
- * @radar_detect: a bitmap where each bit corresponds to a channel
- *     width where radar detection is needed, as in the definition of
- *     &struct ieee80211_iface_combination.@radar_detect_widths
- * @iftype_num: array with the numbers of interfaces of each interface
- *     type.  The index is the interface type as specified in &enum
- *     nl80211_iftype.
+ * @params: the interface combinations parameter
  * @iter: function to call for each matching combination
  * @data: pointer to pass to iter function
  *
@@ -5636,9 +5722,7 @@ int cfg80211_check_combinations(struct wiphy *wiphy,
  * purposes.
  */
 int cfg80211_iter_combinations(struct wiphy *wiphy,
-                              const int num_different_channels,
-                              const u8 radar_detect,
-                              const int iftype_num[NUM_NL80211_IFTYPES],
+                              struct iface_combination_params *params,
                               void (*iter)(const struct ieee80211_iface_combination *c,
                                            void *data),
                               void *data);
index 8d4608ce8716360924ae68a24ffb25c0171187fc..3ec87bacc0f55e7c7e87d870ab9d0970bc2571b8 100644 (file)
@@ -20,7 +20,7 @@ struct genl_info;
 
 /**
  * struct genl_family - generic netlink family
- * @id: protocol family idenfitier
+ * @id: protocol family identifier (private)
  * @hdrsize: length of user specific header in bytes
  * @name: name of family
  * @version: protocol version
@@ -39,16 +39,16 @@ struct genl_info;
  *     Note that unbind() will not be called symmetrically if the
  *     generic netlink family is removed while there are still open
  *     sockets.
- * @attrbuf: buffer to store parsed attributes
- * @family_list: family list
- * @mcgrps: multicast groups used by this family (private)
- * @n_mcgrps: number of multicast groups (private)
+ * @attrbuf: buffer to store parsed attributes (private)
+ * @mcgrps: multicast groups used by this family
+ * @n_mcgrps: number of multicast groups
  * @mcgrp_offset: starting number of multicast group IDs in this family
- * @ops: the operations supported by this family (private)
- * @n_ops: number of operations supported by this family (private)
+ *     (private)
+ * @ops: the operations supported by this family
+ * @n_ops: number of operations supported by this family
  */
 struct genl_family {
-       unsigned int            id;
+       unsigned int            id;             /* private */
        unsigned int            hdrsize;
        char                    name[GENL_NAMSIZ];
        unsigned int            version;
@@ -64,15 +64,16 @@ struct genl_family {
        int                     (*mcast_bind)(struct net *net, int group);
        void                    (*mcast_unbind)(struct net *net, int group);
        struct nlattr **        attrbuf;        /* private */
-       const struct genl_ops * ops;            /* private */
-       const struct genl_multicast_group *mcgrps; /* private */
-       unsigned int            n_ops;          /* private */
-       unsigned int            n_mcgrps;       /* private */
+       const struct genl_ops * ops;
+       const struct genl_multicast_group *mcgrps;
+       unsigned int            n_ops;
+       unsigned int            n_mcgrps;
        unsigned int            mcgrp_offset;   /* private */
-       struct list_head        family_list;    /* private */
        struct module           *module;
 };
 
+struct nlattr **genl_family_attrbuf(const struct genl_family *family);
+
 /**
  * struct genl_info - receiving information
  * @snd_seq: sending sequence number
@@ -130,64 +131,13 @@ struct genl_ops {
        u8                      flags;
 };
 
-int __genl_register_family(struct genl_family *family);
-
-static inline int genl_register_family(struct genl_family *family)
-{
-       family->module = THIS_MODULE;
-       return __genl_register_family(family);
-}
-
-/**
- * genl_register_family_with_ops - register a generic netlink family with ops
- * @family: generic netlink family
- * @ops: operations to be registered
- * @n_ops: number of elements to register
- *
- * Registers the specified family and operations from the specified table.
- * Only one family may be registered with the same family name or identifier.
- *
- * The family id may equal GENL_ID_GENERATE causing an unique id to
- * be automatically generated and assigned.
- *
- * Either a doit or dumpit callback must be specified for every registered
- * operation or the function will fail. Only one operation structure per
- * command identifier may be registered.
- *
- * See include/net/genetlink.h for more documenation on the operations
- * structure.
- *
- * Return 0 on success or a negative error code.
- */
-static inline int
-_genl_register_family_with_ops_grps(struct genl_family *family,
-                                   const struct genl_ops *ops, size_t n_ops,
-                                   const struct genl_multicast_group *mcgrps,
-                                   size_t n_mcgrps)
-{
-       family->module = THIS_MODULE;
-       family->ops = ops;
-       family->n_ops = n_ops;
-       family->mcgrps = mcgrps;
-       family->n_mcgrps = n_mcgrps;
-       return __genl_register_family(family);
-}
-
-#define genl_register_family_with_ops(family, ops)                     \
-       _genl_register_family_with_ops_grps((family),                   \
-                                           (ops), ARRAY_SIZE(ops),     \
-                                           NULL, 0)
-#define genl_register_family_with_ops_groups(family, ops, grps)        \
-       _genl_register_family_with_ops_grps((family),                   \
-                                           (ops), ARRAY_SIZE(ops),     \
-                                           (grps), ARRAY_SIZE(grps))
-
-int genl_unregister_family(struct genl_family *family);
-void genl_notify(struct genl_family *family, struct sk_buff *skb,
+int genl_register_family(struct genl_family *family);
+int genl_unregister_family(const struct genl_family *family);
+void genl_notify(const struct genl_family *family, struct sk_buff *skb,
                 struct genl_info *info, u32 group, gfp_t flags);
 
 void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
-                 struct genl_family *family, int flags, u8 cmd);
+                 const struct genl_family *family, int flags, u8 cmd);
 
 /**
  * genlmsg_nlhdr - Obtain netlink header from user specified header
@@ -196,8 +146,8 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
  *
  * Returns pointer to netlink header.
  */
-static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr,
-                                            struct genl_family *family)
+static inline struct nlmsghdr *
+genlmsg_nlhdr(void *user_hdr, const struct genl_family *family)
 {
        return (struct nlmsghdr *)((char *)user_hdr -
                                   family->hdrsize -
@@ -233,7 +183,7 @@ static inline int genlmsg_parse(const struct nlmsghdr *nlh,
  */
 static inline void genl_dump_check_consistent(struct netlink_callback *cb,
                                              void *user_hdr,
-                                             struct genl_family *family)
+                                             const struct genl_family *family)
 {
        nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family));
 }
@@ -250,7 +200,7 @@ static inline void genl_dump_check_consistent(struct netlink_callback *cb,
  */
 static inline void *genlmsg_put_reply(struct sk_buff *skb,
                                      struct genl_info *info,
-                                     struct genl_family *family,
+                                     const struct genl_family *family,
                                      int flags, u8 cmd)
 {
        return genlmsg_put(skb, info->snd_portid, info->snd_seq, family,
@@ -287,7 +237,7 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
  * @group: offset of multicast group in groups array
  * @flags: allocation flags
  */
-static inline int genlmsg_multicast_netns(struct genl_family *family,
+static inline int genlmsg_multicast_netns(const struct genl_family *family,
                                          struct net *net, struct sk_buff *skb,
                                          u32 portid, unsigned int group, gfp_t flags)
 {
@@ -305,7 +255,7 @@ static inline int genlmsg_multicast_netns(struct genl_family *family,
  * @group: offset of multicast group in groups array
  * @flags: allocation flags
  */
-static inline int genlmsg_multicast(struct genl_family *family,
+static inline int genlmsg_multicast(const struct genl_family *family,
                                    struct sk_buff *skb, u32 portid,
                                    unsigned int group, gfp_t flags)
 {
@@ -323,7 +273,7 @@ static inline int genlmsg_multicast(struct genl_family *family,
  *
  * This function must hold the RTNL or rcu_read_lock().
  */
-int genlmsg_multicast_allns(struct genl_family *family,
+int genlmsg_multicast_allns(const struct genl_family *family,
                            struct sk_buff *skb, u32 portid,
                            unsigned int group, gfp_t flags);
 
@@ -407,8 +357,9 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
  * This function returns the number of broadcast listeners that have set the
  * NETLINK_RECV_NO_ENOBUFS socket option.
  */
-static inline int genl_set_err(struct genl_family *family, struct net *net,
-                              u32 portid, u32 group, int code)
+static inline int genl_set_err(const struct genl_family *family,
+                              struct net *net, u32 portid,
+                              u32 group, int code)
 {
        if (WARN_ON_ONCE(group >= family->n_mcgrps))
                return -EINVAL;
@@ -416,7 +367,7 @@ static inline int genl_set_err(struct genl_family *family, struct net *net,
        return netlink_set_err(net->genl_sock, portid, group, code);
 }
 
-static inline int genl_has_listeners(struct genl_family *family,
+static inline int genl_has_listeners(const struct genl_family *family,
                                     struct net *net, unsigned int group)
 {
        if (WARN_ON_ONCE(group >= family->n_mcgrps))
index ba07b9d8ed638bd5d467b82c4fff2cbec4836c32..d0e7e3f8e67ae208de3195f4af9cd740972dee0b 100644 (file)
@@ -333,9 +333,9 @@ enum ieee80211_radiotap_type {
 #define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS                   0x0003
 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK                 0x00F0
 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU           0x0000
-#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU              0x0010
+#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ         0x0010
 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU              0x0020
-#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ         0x0030
+#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU              0x0030
 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN              0x00F0
 
 #define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT                        0x00
index 197a30d221e92b839e2e96fa37f4a796514ea461..146054ceea8e0566f79739b1ed115dea53423258 100644 (file)
@@ -289,11 +289,6 @@ static inline int inet_csk_reqsk_queue_len(const struct sock *sk)
        return reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue);
 }
 
-static inline int inet_csk_reqsk_queue_young(const struct sock *sk)
-{
-       return reqsk_queue_len_young(&inet_csk(sk)->icsk_accept_queue);
-}
-
 static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
 {
        return inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog;
index ea3f80f58fd6d57f01d4cd9d7cbe659e7a123150..82e76fe1c1f747a633ed1c92258a40451ec16e63 100644 (file)
@@ -24,11 +24,11 @@ enum {
 struct lwtunnel_state {
        __u16           type;
        __u16           flags;
+       __u16           headroom;
        atomic_t        refcnt;
        int             (*orig_output)(struct net *net, struct sock *sk, struct sk_buff *skb);
        int             (*orig_input)(struct sk_buff *);
-       int             len;
-       __u16           headroom;
+       struct          rcu_head rcu;
        __u8            data[0];
 };
 
@@ -36,6 +36,7 @@ struct lwtunnel_encap_ops {
        int (*build_state)(struct net_device *dev, struct nlattr *encap,
                           unsigned int family, const void *cfg,
                           struct lwtunnel_state **ts);
+       void (*destroy_state)(struct lwtunnel_state *lws);
        int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
        int (*input)(struct sk_buff *skb);
        int (*fill_encap)(struct sk_buff *skb,
@@ -46,10 +47,7 @@ struct lwtunnel_encap_ops {
 };
 
 #ifdef CONFIG_LWTUNNEL
-static inline void lwtstate_free(struct lwtunnel_state *lws)
-{
-       kfree(lws);
-}
+void lwtstate_free(struct lwtunnel_state *lws);
 
 static inline struct lwtunnel_state *
 lwtstate_get(struct lwtunnel_state *lws)
index e2dba93e374fda7f93c5dda34d28df8211e9eacc..5345d358a510ce63d5c13fd48cfd7f9284405768 100644 (file)
@@ -1442,7 +1442,7 @@ enum ieee80211_vif_flags {
 struct ieee80211_vif {
        enum nl80211_iftype type;
        struct ieee80211_bss_conf bss_conf;
-       u8 addr[ETH_ALEN];
+       u8 addr[ETH_ALEN] __aligned(2);
        bool p2p;
        bool csa_active;
        bool mu_mimo_owner;
@@ -1749,7 +1749,8 @@ struct ieee80211_sta_rates {
  * @drv_priv: data area for driver use, will always be aligned to
  *     sizeof(void \*), size is determined in hw information.
  * @uapsd_queues: bitmap of queues configured for uapsd. Only valid
- *     if wme is supported.
+ *     if wme is supported. The bits order is like in
+ *     IEEE80211_WMM_IE_STA_QOSINFO_AC_*.
  * @max_sp: max Service Period. Only valid if wme is supported.
  * @bandwidth: current bandwidth the station can receive with
  * @rx_nss: in HT/VHT, the maximum number of spatial streams the
@@ -2029,6 +2030,10 @@ struct ieee80211_txq {
  *     drivers, mac80211 packet loss mechanism will not be triggered and driver
  *     is completely depending on firmware event for station kickout.
  *
+ * @IEEE80211_HW_SUPPORTS_TX_FRAG: Hardware does fragmentation by itself.
+ *     The stack will not do fragmentation.
+ *     The callback for @set_frag_threshold should be set as well.
+ *
  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
  */
 enum ieee80211_hw_flags {
@@ -2070,6 +2075,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_TX_AMSDU,
        IEEE80211_HW_TX_FRAG_LIST,
        IEEE80211_HW_REPORTS_LOW_ACK,
+       IEEE80211_HW_SUPPORTS_TX_FRAG,
 
        /* keep last, obviously */
        NUM_IEEE80211_HW_FLAGS
@@ -3098,8 +3104,9 @@ enum ieee80211_reconfig_type {
  *     The callback must be atomic.
  *
  * @set_frag_threshold: Configuration of fragmentation threshold. Assign this
- *     if the device does fragmentation by itself; if this callback is
- *     implemented then the stack will not do fragmentation.
+ *     if the device does fragmentation by itself. Note that to prevent the
+ *     stack from doing fragmentation IEEE80211_HW_SUPPORTS_TX_FRAG
+ *     should be set as well.
  *     The callback can sleep.
  *
  * @set_rts_threshold: Configuration of RTS threshold (if device needs it)
@@ -4092,6 +4099,10 @@ void ieee80211_sta_pspoll(struct ieee80211_sta *sta);
  * This must be used in conjunction with ieee80211_sta_ps_transition()
  * and possibly ieee80211_sta_pspoll(); calls to all three must be
  * serialized.
+ * %IEEE80211_NUM_TIDS can be passed as the tid if the tid is unknown.
+ * In this case, mac80211 will not check that this tid maps to an AC
+ * that is trigger enabled and assume that the caller did the proper
+ * checks.
  */
 void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *sta, u8 tid);
 
index 254a0fc018006a773f31f41bc07e89e5b81528c2..a34f53acb6d62b8339ceb7da703823dd10dafc7c 100644 (file)
@@ -1190,6 +1190,16 @@ static inline struct in6_addr nla_get_in6_addr(const struct nlattr *nla)
        return tmp;
 }
 
+/**
+ * nla_memdup - duplicate attribute memory (kmemdup)
+ * @src: netlink attribute to duplicate from
+ * @gfp: GFP mask
+ */
+static inline void *nla_memdup(const struct nlattr *src, gfp_t gfp)
+{
+       return kmemdup(nla_data(src), nla_len(src), gfp);
+}
+
 /**
  * nla_nest_start - Start a new level of nested attributes
  * @skb: socket buffer to add attributes to
index 3e789008394d32f0faba9e170b1fa5f09dbbe7f4..57c33dd22ec4dcb3955f3a6297631f9fab7e7237 100644 (file)
 
 extern struct proto raw_prot;
 
+extern struct raw_hashinfo raw_v4_hashinfo;
+struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
+                            unsigned short num, __be32 raddr,
+                            __be32 laddr, int dif);
+
+int raw_abort(struct sock *sk, int err);
 void raw_icmp_error(struct sk_buff *, int, u32);
 int raw_local_deliver(struct sk_buff *, int);
 
index 87783dea0791c616a9bac5a164e4421dc3ef2363..cbe4e9de1894674ea194239fd21d6f85435d5078 100644 (file)
@@ -3,6 +3,13 @@
 
 #include <net/protocol.h>
 
+extern struct raw_hashinfo raw_v6_hashinfo;
+struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
+                            unsigned short num, const struct in6_addr *loc_addr,
+                            const struct in6_addr *rmt_addr, int dif);
+
+int raw_abort(struct sock *sk, int err);
+
 void raw6_icmp_error(struct sk_buff *, int nexthdr,
                u8 type, u8 code, int inner_offset, __be32);
 bool raw6_local_deliver(struct sk_buff *, int);
index 11c3bf262a850315dcb938d6e95a7a4a638b7afe..bd4a3ded7c871b0f08fcbc222b8f04292fed900c 100644 (file)
@@ -530,7 +530,6 @@ struct sctp_datamsg {
        /* Did the messenge fail to send? */
        int send_error;
        u8 send_failed:1,
-          can_abandon:1,   /* can chunks from this message can be abandoned. */
           can_delay;       /* should this message be Nagle delayed */
 };
 
@@ -641,7 +640,6 @@ struct sctp_chunk {
 #define SCTP_NEED_FRTX 0x1
 #define SCTP_DONT_FRTX 0x2
        __u16   rtt_in_progress:1,      /* This chunk used for RTT calc? */
-               resent:1,               /* Has this chunk ever been resent. */
                has_tsn:1,              /* Does this chunk have a TSN yet? */
                has_ssn:1,              /* Does this chunk have a SSN yet? */
                singleton:1,            /* Only chunk in the packet? */
@@ -656,6 +654,7 @@ struct sctp_chunk {
                fast_retransmit:2;      /* Is this chunk fast retransmitted? */
 };
 
+#define sctp_chunk_retransmitted(chunk)        (chunk->sent_count > 1)
 void sctp_chunk_hold(struct sctp_chunk *);
 void sctp_chunk_put(struct sctp_chunk *);
 int sctp_user_addto_chunk(struct sctp_chunk *chunk, int len,
index 73c6b008f1b768e6ca51a00532723c3739bb02bf..f13ac87a8015cb18c5d3fe5fdcf2d6a0592428f4 100644 (file)
@@ -1276,7 +1276,9 @@ static inline struct inode *SOCK_INODE(struct socket *socket)
 /*
  * Functions for memory accounting
  */
+int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind);
 int __sk_mem_schedule(struct sock *sk, int size, int kind);
+void __sk_mem_reduce_allocated(struct sock *sk, int amount);
 void __sk_mem_reclaim(struct sock *sk, int amount);
 
 #define SK_MEM_QUANTUM ((int)PAGE_SIZE)
@@ -1952,6 +1954,8 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer,
 
 void sk_stop_timer(struct sock *sk, struct timer_list *timer);
 
+int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
+                       unsigned int flags);
 int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 
index 62770add15bd80a069747119e564244b8f9055ff..604bc31e23ab1ebc20ddaaa8fa7a94aaf1857281 100644 (file)
@@ -8,13 +8,13 @@ struct tcf_mirred {
        struct tc_action        common;
        int                     tcfm_eaction;
        int                     tcfm_ifindex;
-       int                     tcfm_ok_push;
+       bool                    tcfm_mac_header_xmit;
        struct net_device __rcu *tcfm_dev;
        struct list_head        tcfm_list;
 };
 #define to_mirred(a) ((struct tcf_mirred *)a)
 
-static inline bool is_tcf_mirred_redirect(const struct tc_action *a)
+static inline bool is_tcf_mirred_egress_redirect(const struct tc_action *a)
 {
 #ifdef CONFIG_NET_CLS_ACT
        if (a->ops && a->ops->type == TCA_ACT_MIRRED)
@@ -23,7 +23,7 @@ static inline bool is_tcf_mirred_redirect(const struct tc_action *a)
        return false;
 }
 
-static inline bool is_tcf_mirred_mirror(const struct tc_action *a)
+static inline bool is_tcf_mirred_egress_mirror(const struct tc_action *a)
 {
 #ifdef CONFIG_NET_CLS_ACT
        if (a->ops && a->ops->type == TCA_ACT_MIRRED)
index 5767e9dbcf92453e7e4336481db5956f729c38ed..19cd3d3458049a2fe6d317bc48ff9e5c0524587b 100644 (file)
@@ -27,6 +27,7 @@ struct tcf_skbedit {
        u32             flags;
        u32             priority;
        u32             mark;
+       u32             mask;
        u16             queue_mapping;
        u16             ptype;
 };
index 4948790d393d7617edba64603c60974942289ee4..6134f37ba3ab8b7af9988114d82866a69f691f1e 100644 (file)
@@ -246,6 +246,9 @@ static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb,
 }
 
 /* net/ipv4/udp.c */
+void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len);
+int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb);
+
 void udp_v4_early_demux(struct sk_buff *skb);
 int udp_get_port(struct sock *sk, unsigned short snum,
                 int (*saddr_cmp)(const struct sock *,
@@ -258,6 +261,7 @@ void udp_flush_pending_frames(struct sock *sk);
 void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
 int udp_rcv(struct sk_buff *skb);
 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+int udp_init_sock(struct sock *sk);
 int __udp_disconnect(struct sock *sk, int flags);
 int udp_disconnect(struct sock *sk, int flags);
 unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait);
index f09c70b97ecad2adeb627a1b9d8b8431cee7c695..e2f38e0091b6fd0045cb37930fdfcfdeae40d626 100644 (file)
@@ -143,291 +143,301 @@ union bpf_attr {
        };
 } __attribute__((aligned(8)));
 
+/* BPF helper function descriptions:
+ *
+ * void *bpf_map_lookup_elem(&map, &key)
+ *     Return: Map value or NULL
+ *
+ * int bpf_map_update_elem(&map, &key, &value, flags)
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_map_delete_elem(&map, &key)
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_probe_read(void *dst, int size, void *src)
+ *     Return: 0 on success or negative error
+ *
+ * u64 bpf_ktime_get_ns(void)
+ *     Return: current ktime
+ *
+ * int bpf_trace_printk(const char *fmt, int fmt_size, ...)
+ *     Return: length of buffer written or negative error
+ *
+ * u32 bpf_prandom_u32(void)
+ *     Return: random value
+ *
+ * u32 bpf_raw_smp_processor_id(void)
+ *     Return: SMP processor ID
+ *
+ * int bpf_skb_store_bytes(skb, offset, from, len, flags)
+ *     store bytes into packet
+ *     @skb: pointer to skb
+ *     @offset: offset within packet from skb->mac_header
+ *     @from: pointer where to copy bytes from
+ *     @len: number of bytes to store into packet
+ *     @flags: bit 0 - if true, recompute skb->csum
+ *             other bits - reserved
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_l3_csum_replace(skb, offset, from, to, flags)
+ *     recompute IP checksum
+ *     @skb: pointer to skb
+ *     @offset: offset within packet where IP checksum is located
+ *     @from: old value of header field
+ *     @to: new value of header field
+ *     @flags: bits 0-3 - size of header field
+ *             other bits - reserved
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_l4_csum_replace(skb, offset, from, to, flags)
+ *     recompute TCP/UDP checksum
+ *     @skb: pointer to skb
+ *     @offset: offset within packet where TCP/UDP checksum is located
+ *     @from: old value of header field
+ *     @to: new value of header field
+ *     @flags: bits 0-3 - size of header field
+ *             bit 4 - is pseudo header
+ *             other bits - reserved
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_tail_call(ctx, prog_array_map, index)
+ *     jump into another BPF program
+ *     @ctx: context pointer passed to next program
+ *     @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
+ *     @index: index inside array that selects specific program to run
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_clone_redirect(skb, ifindex, flags)
+ *     redirect to another netdev
+ *     @skb: pointer to skb
+ *     @ifindex: ifindex of the net device
+ *     @flags: bit 0 - if set, redirect to ingress instead of egress
+ *             other bits - reserved
+ *     Return: 0 on success or negative error
+ *
+ * u64 bpf_get_current_pid_tgid(void)
+ *     Return: current->tgid << 32 | current->pid
+ *
+ * u64 bpf_get_current_uid_gid(void)
+ *     Return: current_gid << 32 | current_uid
+ *
+ * int bpf_get_current_comm(char *buf, int size_of_buf)
+ *     stores current->comm into buf
+ *     Return: 0 on success or negative error
+ *
+ * u32 bpf_get_cgroup_classid(skb)
+ *     retrieve a proc's classid
+ *     @skb: pointer to skb
+ *     Return: classid if != 0
+ *
+ * int bpf_skb_vlan_push(skb, vlan_proto, vlan_tci)
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_skb_vlan_pop(skb)
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_skb_get_tunnel_key(skb, key, size, flags)
+ * int bpf_skb_set_tunnel_key(skb, key, size, flags)
+ *     retrieve or populate tunnel metadata
+ *     @skb: pointer to skb
+ *     @key: pointer to 'struct bpf_tunnel_key'
+ *     @size: size of 'struct bpf_tunnel_key'
+ *     @flags: room for future extensions
+ *     Return: 0 on success or negative error
+ *
+ * u64 bpf_perf_event_read(&map, index)
+ *     Return: Number events read or error code
+ *
+ * int bpf_redirect(ifindex, flags)
+ *     redirect to another netdev
+ *     @ifindex: ifindex of the net device
+ *     @flags: bit 0 - if set, redirect to ingress instead of egress
+ *             other bits - reserved
+ *     Return: TC_ACT_REDIRECT
+ *
+ * u32 bpf_get_route_realm(skb)
+ *     retrieve a dst's tclassid
+ *     @skb: pointer to skb
+ *     Return: realm if != 0
+ *
+ * int bpf_perf_event_output(ctx, map, index, data, size)
+ *     output perf raw sample
+ *     @ctx: struct pt_regs*
+ *     @map: pointer to perf_event_array map
+ *     @index: index of event in the map
+ *     @data: data on stack to be output as raw data
+ *     @size: size of data
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_get_stackid(ctx, map, flags)
+ *     walk user or kernel stack and return id
+ *     @ctx: struct pt_regs*
+ *     @map: pointer to stack_trace map
+ *     @flags: bits 0-7 - numer of stack frames to skip
+ *             bit 8 - collect user stack instead of kernel
+ *             bit 9 - compare stacks by hash only
+ *             bit 10 - if two different stacks hash into the same stackid
+ *                      discard old
+ *             other bits - reserved
+ *     Return: >= 0 stackid on success or negative error
+ *
+ * s64 bpf_csum_diff(from, from_size, to, to_size, seed)
+ *     calculate csum diff
+ *     @from: raw from buffer
+ *     @from_size: length of from buffer
+ *     @to: raw to buffer
+ *     @to_size: length of to buffer
+ *     @seed: optional seed
+ *     Return: csum result or negative error code
+ *
+ * int bpf_skb_get_tunnel_opt(skb, opt, size)
+ *     retrieve tunnel options metadata
+ *     @skb: pointer to skb
+ *     @opt: pointer to raw tunnel option data
+ *     @size: size of @opt
+ *     Return: option size
+ *
+ * int bpf_skb_set_tunnel_opt(skb, opt, size)
+ *     populate tunnel options metadata
+ *     @skb: pointer to skb
+ *     @opt: pointer to raw tunnel option data
+ *     @size: size of @opt
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_skb_change_proto(skb, proto, flags)
+ *     Change protocol of the skb. Currently supported is v4 -> v6,
+ *     v6 -> v4 transitions. The helper will also resize the skb. eBPF
+ *     program is expected to fill the new headers via skb_store_bytes
+ *     and lX_csum_replace.
+ *     @skb: pointer to skb
+ *     @proto: new skb->protocol type
+ *     @flags: reserved
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_skb_change_type(skb, type)
+ *     Change packet type of skb.
+ *     @skb: pointer to skb
+ *     @type: new skb->pkt_type type
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_skb_under_cgroup(skb, map, index)
+ *     Check cgroup2 membership of skb
+ *     @skb: pointer to skb
+ *     @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
+ *     @index: index of the cgroup in the bpf_map
+ *     Return:
+ *       == 0 skb failed the cgroup2 descendant test
+ *       == 1 skb succeeded the cgroup2 descendant test
+ *        < 0 error
+ *
+ * u32 bpf_get_hash_recalc(skb)
+ *     Retrieve and possibly recalculate skb->hash.
+ *     @skb: pointer to skb
+ *     Return: hash
+ *
+ * u64 bpf_get_current_task(void)
+ *     Returns current task_struct
+ *     Return: current
+ *
+ * int bpf_probe_write_user(void *dst, void *src, int len)
+ *     safely attempt to write to a location
+ *     @dst: destination address in userspace
+ *     @src: source address on stack
+ *     @len: number of bytes to copy
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_current_task_under_cgroup(map, index)
+ *     Check cgroup2 membership of current task
+ *     @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
+ *     @index: index of the cgroup in the bpf_map
+ *     Return:
+ *       == 0 current failed the cgroup2 descendant test
+ *       == 1 current succeeded the cgroup2 descendant test
+ *        < 0 error
+ *
+ * int bpf_skb_change_tail(skb, len, flags)
+ *     The helper will resize the skb to the given new size, to be used f.e.
+ *     with control messages.
+ *     @skb: pointer to skb
+ *     @len: new skb length
+ *     @flags: reserved
+ *     Return: 0 on success or negative error
+ *
+ * int bpf_skb_pull_data(skb, len)
+ *     The helper will pull in non-linear data in case the skb is non-linear
+ *     and not all of len are part of the linear section. Only needed for
+ *     read/write with direct packet access.
+ *     @skb: pointer to skb
+ *     @len: len to make read/writeable
+ *     Return: 0 on success or negative error
+ *
+ * s64 bpf_csum_update(skb, csum)
+ *     Adds csum into skb->csum in case of CHECKSUM_COMPLETE.
+ *     @skb: pointer to skb
+ *     @csum: csum to add
+ *     Return: csum on success or negative error
+ *
+ * void bpf_set_hash_invalid(skb)
+ *     Invalidate current skb->hash.
+ *     @skb: pointer to skb
+ *
+ * int bpf_get_numa_node_id()
+ *     Return: Id of current NUMA node.
+ */
+#define __BPF_FUNC_MAPPER(FN)          \
+       FN(unspec),                     \
+       FN(map_lookup_elem),            \
+       FN(map_update_elem),            \
+       FN(map_delete_elem),            \
+       FN(probe_read),                 \
+       FN(ktime_get_ns),               \
+       FN(trace_printk),               \
+       FN(get_prandom_u32),            \
+       FN(get_smp_processor_id),       \
+       FN(skb_store_bytes),            \
+       FN(l3_csum_replace),            \
+       FN(l4_csum_replace),            \
+       FN(tail_call),                  \
+       FN(clone_redirect),             \
+       FN(get_current_pid_tgid),       \
+       FN(get_current_uid_gid),        \
+       FN(get_current_comm),           \
+       FN(get_cgroup_classid),         \
+       FN(skb_vlan_push),              \
+       FN(skb_vlan_pop),               \
+       FN(skb_get_tunnel_key),         \
+       FN(skb_set_tunnel_key),         \
+       FN(perf_event_read),            \
+       FN(redirect),                   \
+       FN(get_route_realm),            \
+       FN(perf_event_output),          \
+       FN(skb_load_bytes),             \
+       FN(get_stackid),                \
+       FN(csum_diff),                  \
+       FN(skb_get_tunnel_opt),         \
+       FN(skb_set_tunnel_opt),         \
+       FN(skb_change_proto),           \
+       FN(skb_change_type),            \
+       FN(skb_under_cgroup),           \
+       FN(get_hash_recalc),            \
+       FN(get_current_task),           \
+       FN(probe_write_user),           \
+       FN(current_task_under_cgroup),  \
+       FN(skb_change_tail),            \
+       FN(skb_pull_data),              \
+       FN(csum_update),                \
+       FN(set_hash_invalid),           \
+       FN(get_numa_node_id),
+
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
  */
+#define __BPF_ENUM_FN(x) BPF_FUNC_ ## x
 enum bpf_func_id {
-       BPF_FUNC_unspec,
-       BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
-       BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
-       BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
-       BPF_FUNC_probe_read,      /* int bpf_probe_read(void *dst, int size, void *src) */
-       BPF_FUNC_ktime_get_ns,    /* u64 bpf_ktime_get_ns(void) */
-       BPF_FUNC_trace_printk,    /* int bpf_trace_printk(const char *fmt, int fmt_size, ...) */
-       BPF_FUNC_get_prandom_u32, /* u32 prandom_u32(void) */
-       BPF_FUNC_get_smp_processor_id, /* u32 raw_smp_processor_id(void) */
-
-       /**
-        * skb_store_bytes(skb, offset, from, len, flags) - store bytes into packet
-        * @skb: pointer to skb
-        * @offset: offset within packet from skb->mac_header
-        * @from: pointer where to copy bytes from
-        * @len: number of bytes to store into packet
-        * @flags: bit 0 - if true, recompute skb->csum
-        *         other bits - reserved
-        * Return: 0 on success
-        */
-       BPF_FUNC_skb_store_bytes,
-
-       /**
-        * l3_csum_replace(skb, offset, from, to, flags) - recompute IP checksum
-        * @skb: pointer to skb
-        * @offset: offset within packet where IP checksum is located
-        * @from: old value of header field
-        * @to: new value of header field
-        * @flags: bits 0-3 - size of header field
-        *         other bits - reserved
-        * Return: 0 on success
-        */
-       BPF_FUNC_l3_csum_replace,
-
-       /**
-        * l4_csum_replace(skb, offset, from, to, flags) - recompute TCP/UDP checksum
-        * @skb: pointer to skb
-        * @offset: offset within packet where TCP/UDP checksum is located
-        * @from: old value of header field
-        * @to: new value of header field
-        * @flags: bits 0-3 - size of header field
-        *         bit 4 - is pseudo header
-        *         other bits - reserved
-        * Return: 0 on success
-        */
-       BPF_FUNC_l4_csum_replace,
-
-       /**
-        * bpf_tail_call(ctx, prog_array_map, index) - jump into another BPF program
-        * @ctx: context pointer passed to next program
-        * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
-        * @index: index inside array that selects specific program to run
-        * Return: 0 on success
-        */
-       BPF_FUNC_tail_call,
-
-       /**
-        * bpf_clone_redirect(skb, ifindex, flags) - redirect to another netdev
-        * @skb: pointer to skb
-        * @ifindex: ifindex of the net device
-        * @flags: bit 0 - if set, redirect to ingress instead of egress
-        *         other bits - reserved
-        * Return: 0 on success
-        */
-       BPF_FUNC_clone_redirect,
-
-       /**
-        * u64 bpf_get_current_pid_tgid(void)
-        * Return: current->tgid << 32 | current->pid
-        */
-       BPF_FUNC_get_current_pid_tgid,
-
-       /**
-        * u64 bpf_get_current_uid_gid(void)
-        * Return: current_gid << 32 | current_uid
-        */
-       BPF_FUNC_get_current_uid_gid,
-
-       /**
-        * bpf_get_current_comm(char *buf, int size_of_buf)
-        * stores current->comm into buf
-        * Return: 0 on success
-        */
-       BPF_FUNC_get_current_comm,
-
-       /**
-        * bpf_get_cgroup_classid(skb) - retrieve a proc's classid
-        * @skb: pointer to skb
-        * Return: classid if != 0
-        */
-       BPF_FUNC_get_cgroup_classid,
-       BPF_FUNC_skb_vlan_push, /* bpf_skb_vlan_push(skb, vlan_proto, vlan_tci) */
-       BPF_FUNC_skb_vlan_pop,  /* bpf_skb_vlan_pop(skb) */
-
-       /**
-        * bpf_skb_[gs]et_tunnel_key(skb, key, size, flags)
-        * retrieve or populate tunnel metadata
-        * @skb: pointer to skb
-        * @key: pointer to 'struct bpf_tunnel_key'
-        * @size: size of 'struct bpf_tunnel_key'
-        * @flags: room for future extensions
-        * Retrun: 0 on success
-        */
-       BPF_FUNC_skb_get_tunnel_key,
-       BPF_FUNC_skb_set_tunnel_key,
-       BPF_FUNC_perf_event_read,       /* u64 bpf_perf_event_read(&map, index) */
-       /**
-        * bpf_redirect(ifindex, flags) - redirect to another netdev
-        * @ifindex: ifindex of the net device
-        * @flags: bit 0 - if set, redirect to ingress instead of egress
-        *         other bits - reserved
-        * Return: TC_ACT_REDIRECT
-        */
-       BPF_FUNC_redirect,
-
-       /**
-        * bpf_get_route_realm(skb) - retrieve a dst's tclassid
-        * @skb: pointer to skb
-        * Return: realm if != 0
-        */
-       BPF_FUNC_get_route_realm,
-
-       /**
-        * bpf_perf_event_output(ctx, map, index, data, size) - output perf raw sample
-        * @ctx: struct pt_regs*
-        * @map: pointer to perf_event_array map
-        * @index: index of event in the map
-        * @data: data on stack to be output as raw data
-        * @size: size of data
-        * Return: 0 on success
-        */
-       BPF_FUNC_perf_event_output,
-       BPF_FUNC_skb_load_bytes,
-
-       /**
-        * bpf_get_stackid(ctx, map, flags) - walk user or kernel stack and return id
-        * @ctx: struct pt_regs*
-        * @map: pointer to stack_trace map
-        * @flags: bits 0-7 - numer of stack frames to skip
-        *         bit 8 - collect user stack instead of kernel
-        *         bit 9 - compare stacks by hash only
-        *         bit 10 - if two different stacks hash into the same stackid
-        *                  discard old
-        *         other bits - reserved
-        * Return: >= 0 stackid on success or negative error
-        */
-       BPF_FUNC_get_stackid,
-
-       /**
-        * bpf_csum_diff(from, from_size, to, to_size, seed) - calculate csum diff
-        * @from: raw from buffer
-        * @from_size: length of from buffer
-        * @to: raw to buffer
-        * @to_size: length of to buffer
-        * @seed: optional seed
-        * Return: csum result
-        */
-       BPF_FUNC_csum_diff,
-
-       /**
-        * bpf_skb_[gs]et_tunnel_opt(skb, opt, size)
-        * retrieve or populate tunnel options metadata
-        * @skb: pointer to skb
-        * @opt: pointer to raw tunnel option data
-        * @size: size of @opt
-        * Return: 0 on success for set, option size for get
-        */
-       BPF_FUNC_skb_get_tunnel_opt,
-       BPF_FUNC_skb_set_tunnel_opt,
-
-       /**
-        * bpf_skb_change_proto(skb, proto, flags)
-        * Change protocol of the skb. Currently supported is
-        * v4 -> v6, v6 -> v4 transitions. The helper will also
-        * resize the skb. eBPF program is expected to fill the
-        * new headers via skb_store_bytes and lX_csum_replace.
-        * @skb: pointer to skb
-        * @proto: new skb->protocol type
-        * @flags: reserved
-        * Return: 0 on success or negative error
-        */
-       BPF_FUNC_skb_change_proto,
-
-       /**
-        * bpf_skb_change_type(skb, type)
-        * Change packet type of skb.
-        * @skb: pointer to skb
-        * @type: new skb->pkt_type type
-        * Return: 0 on success or negative error
-        */
-       BPF_FUNC_skb_change_type,
-
-       /**
-        * bpf_skb_under_cgroup(skb, map, index) - Check cgroup2 membership of skb
-        * @skb: pointer to skb
-        * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
-        * @index: index of the cgroup in the bpf_map
-        * Return:
-        *   == 0 skb failed the cgroup2 descendant test
-        *   == 1 skb succeeded the cgroup2 descendant test
-        *    < 0 error
-        */
-       BPF_FUNC_skb_under_cgroup,
-
-       /**
-        * bpf_get_hash_recalc(skb)
-        * Retrieve and possibly recalculate skb->hash.
-        * @skb: pointer to skb
-        * Return: hash
-        */
-       BPF_FUNC_get_hash_recalc,
-
-       /**
-        * u64 bpf_get_current_task(void)
-        * Returns current task_struct
-        * Return: current
-        */
-       BPF_FUNC_get_current_task,
-
-       /**
-        * bpf_probe_write_user(void *dst, void *src, int len)
-        * safely attempt to write to a location
-        * @dst: destination address in userspace
-        * @src: source address on stack
-        * @len: number of bytes to copy
-        * Return: 0 on success or negative error
-        */
-       BPF_FUNC_probe_write_user,
-
-       /**
-        * bpf_current_task_under_cgroup(map, index) - Check cgroup2 membership of current task
-        * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
-        * @index: index of the cgroup in the bpf_map
-        * Return:
-        *   == 0 current failed the cgroup2 descendant test
-        *   == 1 current succeeded the cgroup2 descendant test
-        *    < 0 error
-        */
-       BPF_FUNC_current_task_under_cgroup,
-
-       /**
-        * bpf_skb_change_tail(skb, len, flags)
-        * The helper will resize the skb to the given new size,
-        * to be used f.e. with control messages.
-        * @skb: pointer to skb
-        * @len: new skb length
-        * @flags: reserved
-        * Return: 0 on success or negative error
-        */
-       BPF_FUNC_skb_change_tail,
-
-       /**
-        * bpf_skb_pull_data(skb, len)
-        * The helper will pull in non-linear data in case the
-        * skb is non-linear and not all of len are part of the
-        * linear section. Only needed for read/write with direct
-        * packet access.
-        * @skb: pointer to skb
-        * @len: len to make read/writeable
-        * Return: 0 on success or negative error
-        */
-       BPF_FUNC_skb_pull_data,
-
-       /**
-        * bpf_csum_update(skb, csum)
-        * Adds csum into skb->csum in case of CHECKSUM_COMPLETE.
-        * @skb: pointer to skb
-        * @csum: csum to add
-        * Return: csum on success or negative error
-        */
-       BPF_FUNC_csum_update,
-
-       /**
-        * bpf_set_hash_invalid(skb)
-        * Invalidate current skb>hash.
-        * @skb: pointer to skb
-        */
-       BPF_FUNC_set_hash_invalid,
-
+       __BPF_FUNC_MAPPER(__BPF_ENUM_FN)
        __BPF_FUNC_MAX_ID,
 };
+#undef __BPF_ENUM_FN
 
 /* All flags used by eBPF helper functions, placed here. */
 
index 5512c90af7e30f5593fbba398882f99a62fe65c0..adc899381e0d84eb8f206cce51eeb2865fe71397 100644 (file)
@@ -26,10 +26,11 @@ struct genlmsghdr {
 /*
  * List of reserved static generic netlink identifiers:
  */
-#define GENL_ID_GENERATE       0
 #define GENL_ID_CTRL           NLMSG_MIN_TYPE
 #define GENL_ID_VFS_DQUOT      (NLMSG_MIN_TYPE + 1)
 #define GENL_ID_PMCRAID                (NLMSG_MIN_TYPE + 2)
+/* must be last reserved + 1 */
+#define GENL_START_ALLOC       (NLMSG_MIN_TYPE + 3)
 
 /**************************************************************************
  * Controller
index 117d02e0fc318089eb038f52a30a42a1ce1e1eeb..3e5185e9ef03d612a971cd0a6e7577d58648a20d 100644 (file)
@@ -35,6 +35,9 @@
 #define ETH_FRAME_LEN  1514            /* Max. octets in frame sans FCS */
 #define ETH_FCS_LEN    4               /* Octets in the FCS             */
 
+#define ETH_MIN_MTU    68              /* Min IPv4 MTU per RFC791      */
+#define ETH_MAX_MTU    0xFFFFU         /* 65535, same as IP_MAX_MTU    */
+
 /*
  *     These are the defined Ethernet Protocol ID's.
  */
index 509cd961068d5d89c2b865c7baf1bab4aff2ea2c..bbe201047df6c8cd5e56d8e783d3934163c10d0b 100644 (file)
@@ -43,6 +43,23 @@ struct inet_diag_req_v2 {
        struct inet_diag_sockid id;
 };
 
+/*
+ * SOCK_RAW sockets require the underlied protocol to be
+ * additionally specified so we can use @pad member for
+ * this, but we can't rename it because userspace programs
+ * still may depend on this name. Instead lets use another
+ * structure definition as an alias for struct
+ * @inet_diag_req_v2.
+ */
+struct inet_diag_req_raw {
+       __u8    sdiag_family;
+       __u8    sdiag_protocol;
+       __u8    idiag_ext;
+       __u8    sdiag_raw_protocol;
+       __u32   idiag_states;
+       struct inet_diag_sockid id;
+};
+
 enum {
        INET_DIAG_REQ_NONE,
        INET_DIAG_REQ_BYTECODE,
index 56368e9b462245b6a50a2756abac6233b95650d9..259c9c77fdc1cc8505e36ae06d29f66a8e005bf4 100644 (file)
  *
  * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface.
  *
+ * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if this AP should perform
+ *     multicast to unicast conversion. When enabled, all multicast packets
+ *     with ethertype ARP, IPv4 or IPv6 (possibly within an 802.1Q header)
+ *     will be sent out to each station once with the destination (multicast)
+ *     MAC address replaced by the station's MAC address. Note that this may
+ *     break certain expectations of the receiver, e.g. the ability to drop
+ *     unicast IP packets encapsulated in multicast L2 frames, or the ability
+ *     to not send destination unreachable messages in such cases.
+ *     This can only be toggled per BSS. Configure this on an interface of
+ *     type %NL80211_IFTYPE_AP. It applies to all its VLAN interfaces
+ *     (%NL80211_IFTYPE_AP_VLAN), except for those in 4addr (WDS) mode.
+ *     If %NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED is not present with this
+ *     command, the feature is disabled.
+ *
  * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial
  *     mesh config parameters may be given.
  * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the
  *     This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and
  *     %NL80211_ATTR_COOKIE.
  *
+ * @NL80211_CMD_UPDATE_CONNECT_PARAMS: Update one or more connect parameters
+ *     for subsequent roaming cases if the driver or firmware uses internal
+ *     BSS selection. This command can be issued only while connected and it
+ *     does not result in a change for the current association. Currently,
+ *     only the %NL80211_ATTR_IE data is used and updated with this command.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1069,6 +1089,10 @@ enum nl80211_commands {
        NL80211_CMD_CHANGE_NAN_CONFIG,
        NL80211_CMD_NAN_MATCH,
 
+       NL80211_CMD_SET_MULTICAST_TO_UNICAST,
+
+       NL80211_CMD_UPDATE_CONNECT_PARAMS,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
@@ -1638,8 +1662,16 @@ enum nl80211_commands {
  *     the connection request from a station. nl80211_connect_failed_reason
  *     enum has different reasons of connection failure.
  *
- * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts
- *     with the Authentication transaction sequence number field.
+ * @NL80211_ATTR_AUTH_DATA: Fields and elements in Authentication frames.
+ *     This contains the authentication frame body (non-IE and IE data),
+ *     excluding the Authentication algorithm number, i.e., starting at the
+ *     Authentication transaction sequence number field. It is used with
+ *     authentication algorithms that need special fields to be added into
+ *     the frames (SAE and FILS). Currently, only the SAE cases use the
+ *     initial two fields (Authentication transaction sequence number and
+ *     Status code). However, those fields are included in the attribute data
+ *     for all authentication algorithms to keep the attribute definition
+ *     consistent.
  *
  * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from
  *     association request when used with NL80211_CMD_NEW_STATION)
@@ -1936,6 +1968,14 @@ enum nl80211_commands {
  *     attribute.
  * @NL80211_ATTR_NAN_MATCH: used to report a match. This is a nested attribute.
  *     See &enum nl80211_nan_match_attributes.
+ * @NL80211_ATTR_FILS_KEK: KEK for FILS (Re)Association Request/Response frame
+ *     protection.
+ * @NL80211_ATTR_FILS_NONCES: Nonces (part of AAD) for FILS (Re)Association
+ *     Request/Response frame protection. This attribute contains the 16 octet
+ *     STA Nonce followed by 16 octets of AP Nonce.
+ *
+ * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Indicates whether or not multicast
+ *     packets should be send out as unicast to all stations (flag attribute).
  *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -2195,7 +2235,7 @@ enum nl80211_attrs {
 
        NL80211_ATTR_CONN_FAILED_REASON,
 
-       NL80211_ATTR_SAE_DATA,
+       NL80211_ATTR_AUTH_DATA,
 
        NL80211_ATTR_VHT_CAPABILITY,
 
@@ -2336,6 +2376,11 @@ enum nl80211_attrs {
        NL80211_ATTR_NAN_FUNC,
        NL80211_ATTR_NAN_MATCH,
 
+       NL80211_ATTR_FILS_KEK,
+       NL80211_ATTR_FILS_NONCES,
+
+       NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -2347,6 +2392,7 @@ enum nl80211_attrs {
 #define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
 #define        NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
 #define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER
+#define NL80211_ATTR_SAE_DATA NL80211_ATTR_AUTH_DATA
 
 /*
  * Allow user space programs to use #ifdef on new attributes by defining them
@@ -3660,6 +3706,9 @@ enum nl80211_bss_status {
  * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
  * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
  * @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals
+ * @NL80211_AUTHTYPE_FILS_SK: Fast Initial Link Setup shared key
+ * @NL80211_AUTHTYPE_FILS_SK_PFS: Fast Initial Link Setup shared key with PFS
+ * @NL80211_AUTHTYPE_FILS_PK: Fast Initial Link Setup public key
  * @__NL80211_AUTHTYPE_NUM: internal
  * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
  * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
@@ -3672,6 +3721,9 @@ enum nl80211_auth_type {
        NL80211_AUTHTYPE_FT,
        NL80211_AUTHTYPE_NETWORK_EAP,
        NL80211_AUTHTYPE_SAE,
+       NL80211_AUTHTYPE_FILS_SK,
+       NL80211_AUTHTYPE_FILS_SK_PFS,
+       NL80211_AUTHTYPE_FILS_PK,
 
        /* keep last */
        __NL80211_AUTHTYPE_NUM,
@@ -4280,6 +4332,9 @@ enum nl80211_iface_limit_attrs {
  *     of supported channel widths for radar detection.
  * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
  *     of supported regulatory regions for radar detection.
+ * @NL80211_IFACE_COMB_BI_MIN_GCD: u32 attribute specifying the minimum GCD of
+ *     different beacon intervals supported by all the interface combinations
+ *     in this group (if not present, all beacon intervals be identical).
  * @NUM_NL80211_IFACE_COMB: number of attributes
  * @MAX_NL80211_IFACE_COMB: highest attribute number
  *
@@ -4287,8 +4342,8 @@ enum nl80211_iface_limit_attrs {
  *     limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2
  *     => allows an AP and a STA that must match BIs
  *
- *     numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8
- *     => allows 8 of AP/GO
+ *     numbers = [ #{AP, P2P-GO} <= 8 ], BI min gcd, channels = 1, max = 8,
+ *     => allows 8 of AP/GO that can have BI gcd >= min gcd
  *
  *     numbers = [ #{STA} <= 2 ], channels = 2, max = 2
  *     => allows two STAs on different channels
@@ -4314,6 +4369,7 @@ enum nl80211_if_combination_attrs {
        NL80211_IFACE_COMB_NUM_CHANNELS,
        NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
        NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
+       NL80211_IFACE_COMB_BI_MIN_GCD,
 
        /* keep last */
        NUM_NL80211_IFACE_COMB,
@@ -4634,6 +4690,8 @@ enum nl80211_feature_flags {
  *     configuration (AP/mesh) with HT rates.
  * @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate
  *     configuration (AP/mesh) with VHT rates.
+ * @NL80211_EXT_FEATURE_FILS_STA: This driver supports Fast Initial Link Setup
+ *     with user space SME (NL80211_CMD_AUTHENTICATE) in station mode.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4648,6 +4706,7 @@ enum nl80211_ext_feature_index {
        NL80211_EXT_FEATURE_BEACON_RATE_LEGACY,
        NL80211_EXT_FEATURE_BEACON_RATE_HT,
        NL80211_EXT_FEATURE_BEACON_RATE_VHT,
+       NL80211_EXT_FEATURE_FILS_STA,
 
        /* add new features before the definition below */
        NUM_NL80211_EXT_FEATURES,
index a4d00c608d8f7e307e0be65e1e8b78371e4dc908..2884425738ce73e3bbbbf8dcfa79c6e345022476 100644 (file)
@@ -28,6 +28,7 @@
 #define SKBEDIT_F_QUEUE_MAPPING                0x2
 #define SKBEDIT_F_MARK                 0x4
 #define SKBEDIT_F_PTYPE                        0x8
+#define SKBEDIT_F_MASK                 0x10
 
 struct tc_skbedit {
        tc_gen;
@@ -42,6 +43,7 @@ enum {
        TCA_SKBEDIT_MARK,
        TCA_SKBEDIT_PAD,
        TCA_SKBEDIT_PTYPE,
+       TCA_SKBEDIT_MASK,
        __TCA_SKBEDIT_MAX
 };
 #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
index aa6d981541067d20f7dbe147ccd92532bfd97ee6..82a04143368ef0a29fe6c9d8a3321d098d95c758 100644 (file)
@@ -1043,6 +1043,7 @@ const struct bpf_func_proto bpf_map_delete_elem_proto __weak;
 
 const struct bpf_func_proto bpf_get_prandom_u32_proto __weak;
 const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak;
+const struct bpf_func_proto bpf_get_numa_node_id_proto __weak;
 const struct bpf_func_proto bpf_ktime_get_ns_proto __weak;
 
 const struct bpf_func_proto bpf_get_current_pid_tgid_proto __weak;
index 39918402e6e960b8d40c502d58fa81782b14a9ea..045cbe673356f90c365928475574bb108a057e0a 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/rcupdate.h>
 #include <linux/random.h>
 #include <linux/smp.h>
+#include <linux/topology.h>
 #include <linux/ktime.h>
 #include <linux/sched.h>
 #include <linux/uidgid.h>
@@ -92,6 +93,17 @@ const struct bpf_func_proto bpf_get_smp_processor_id_proto = {
        .ret_type       = RET_INTEGER,
 };
 
+BPF_CALL_0(bpf_get_numa_node_id)
+{
+       return numa_node_id();
+}
+
+const struct bpf_func_proto bpf_get_numa_node_id_proto = {
+       .func           = bpf_get_numa_node_id,
+       .gpl_only       = false,
+       .ret_type       = RET_INTEGER,
+};
+
 BPF_CALL_0(bpf_ktime_get_ns)
 {
        /* NMI safe access to clock monotonic */
index 99a7e5b388f236ea62f23afefac5c252416d2b60..900257578934667e6ee216aff0ae24997854be37 100644 (file)
@@ -19,6 +19,7 @@
 #include <net/netlink.h>
 #include <linux/file.h>
 #include <linux/vmalloc.h>
+#include <linux/stringify.h>
 
 /* bpf_check() is a static code analyzer that walks eBPF program
  * instruction by instruction and updates register/stack state.
@@ -190,6 +191,22 @@ static const char * const reg_type_str[] = {
        [PTR_TO_PACKET_END]     = "pkt_end",
 };
 
+#define __BPF_FUNC_STR_FN(x) [BPF_FUNC_ ## x] = __stringify(bpf_ ## x)
+static const char * const func_id_str[] = {
+       __BPF_FUNC_MAPPER(__BPF_FUNC_STR_FN)
+};
+#undef __BPF_FUNC_STR_FN
+
+static const char *func_id_name(int id)
+{
+       BUILD_BUG_ON(ARRAY_SIZE(func_id_str) != __BPF_FUNC_MAX_ID);
+
+       if (id >= 0 && id < __BPF_FUNC_MAX_ID && func_id_str[id])
+               return func_id_str[id];
+       else
+               return "unknown";
+}
+
 static void print_verifier_state(struct bpf_verifier_state *state)
 {
        struct bpf_reg_state *reg;
@@ -212,9 +229,10 @@ static void print_verifier_state(struct bpf_verifier_state *state)
                else if (t == CONST_PTR_TO_MAP || t == PTR_TO_MAP_VALUE ||
                         t == PTR_TO_MAP_VALUE_OR_NULL ||
                         t == PTR_TO_MAP_VALUE_ADJ)
-                       verbose("(ks=%d,vs=%d)",
+                       verbose("(ks=%d,vs=%d,id=%u)",
                                reg->map_ptr->key_size,
-                               reg->map_ptr->value_size);
+                               reg->map_ptr->value_size,
+                               reg->id);
                if (reg->min_value != BPF_REGISTER_MIN_RANGE)
                        verbose(",min_value=%llu",
                                (unsigned long long)reg->min_value);
@@ -353,7 +371,8 @@ static void print_bpf_insn(struct bpf_insn *insn)
                u8 opcode = BPF_OP(insn->code);
 
                if (opcode == BPF_CALL) {
-                       verbose("(%02x) call %d\n", insn->code, insn->imm);
+                       verbose("(%02x) call %s#%d\n", insn->code,
+                               func_id_name(insn->imm), insn->imm);
                } else if (insn->code == (BPF_JMP | BPF_JA)) {
                        verbose("(%02x) goto pc%+d\n",
                                insn->code, insn->off);
@@ -447,6 +466,7 @@ static void mark_reg_unknown_value(struct bpf_reg_state *regs, u32 regno)
 {
        BUG_ON(regno >= MAX_BPF_REG);
        regs[regno].type = UNKNOWN_VALUE;
+       regs[regno].id = 0;
        regs[regno].imm = 0;
 }
 
@@ -1112,8 +1132,8 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id)
 
        return 0;
 error:
-       verbose("cannot pass map_type %d into func %d\n",
-               map->map_type, func_id);
+       verbose("cannot pass map_type %d into func %s#%d\n",
+               map->map_type, func_id_name(func_id), func_id);
        return -EINVAL;
 }
 
@@ -1170,7 +1190,7 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
 
        /* find function prototype */
        if (func_id < 0 || func_id >= __BPF_FUNC_MAX_ID) {
-               verbose("invalid func %d\n", func_id);
+               verbose("invalid func %s#%d\n", func_id_name(func_id), func_id);
                return -EINVAL;
        }
 
@@ -1178,7 +1198,7 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
                fn = env->prog->aux->ops->get_func_proto(func_id);
 
        if (!fn) {
-               verbose("unknown func %d\n", func_id);
+               verbose("unknown func %s#%d\n", func_id_name(func_id), func_id);
                return -EINVAL;
        }
 
@@ -1198,7 +1218,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
         */
        err = check_raw_mode(fn);
        if (err) {
-               verbose("kernel subsystem misconfigured func %d\n", func_id);
+               verbose("kernel subsystem misconfigured func %s#%d\n",
+                       func_id_name(func_id), func_id);
                return err;
        }
 
@@ -1252,9 +1273,10 @@ static int check_call(struct bpf_verifier_env *env, int func_id)
                        return -EINVAL;
                }
                regs[BPF_REG_0].map_ptr = meta.map_ptr;
+               regs[BPF_REG_0].id = ++env->id_gen;
        } else {
-               verbose("unknown return type %d of func %d\n",
-                       fn->ret_type, func_id);
+               verbose("unknown return type %d of func %s#%d\n",
+                       fn->ret_type, func_id_name(func_id), func_id);
                return -EINVAL;
        }
 
@@ -1644,8 +1666,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                                                insn->src_reg);
                                        return -EACCES;
                                }
-                               regs[insn->dst_reg].type = UNKNOWN_VALUE;
-                               regs[insn->dst_reg].map_ptr = NULL;
+                               mark_reg_unknown_value(regs, insn->dst_reg);
                        }
                } else {
                        /* case: R = imm
@@ -1907,6 +1928,38 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
        check_reg_overflow(true_reg);
 }
 
+static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
+                        enum bpf_reg_type type)
+{
+       struct bpf_reg_state *reg = &regs[regno];
+
+       if (reg->type == PTR_TO_MAP_VALUE_OR_NULL && reg->id == id) {
+               reg->type = type;
+               if (type == UNKNOWN_VALUE)
+                       mark_reg_unknown_value(regs, regno);
+       }
+}
+
+/* The logic is similar to find_good_pkt_pointers(), both could eventually
+ * be folded together at some point.
+ */
+static void mark_map_regs(struct bpf_verifier_state *state, u32 regno,
+                         enum bpf_reg_type type)
+{
+       struct bpf_reg_state *regs = state->regs;
+       int i;
+
+       for (i = 0; i < MAX_BPF_REG; i++)
+               mark_map_reg(regs, i, regs[regno].id, type);
+
+       for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
+               if (state->stack_slot_type[i] != STACK_SPILL)
+                       continue;
+               mark_map_reg(state->spilled_regs, i / BPF_REG_SIZE,
+                            regs[regno].id, type);
+       }
+}
+
 static int check_cond_jmp_op(struct bpf_verifier_env *env,
                             struct bpf_insn *insn, int *insn_idx)
 {
@@ -1994,18 +2047,13 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
        if (BPF_SRC(insn->code) == BPF_K &&
            insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) &&
            dst_reg->type == PTR_TO_MAP_VALUE_OR_NULL) {
-               if (opcode == BPF_JEQ) {
-                       /* next fallthrough insn can access memory via
-                        * this register
-                        */
-                       regs[insn->dst_reg].type = PTR_TO_MAP_VALUE;
-                       /* branch targer cannot access it, since reg == 0 */
-                       mark_reg_unknown_value(other_branch->regs,
-                                              insn->dst_reg);
-               } else {
-                       other_branch->regs[insn->dst_reg].type = PTR_TO_MAP_VALUE;
-                       mark_reg_unknown_value(regs, insn->dst_reg);
-               }
+               /* Mark all identical map registers in each branch as either
+                * safe or unknown depending R == 0 or R != 0 conditional.
+                */
+               mark_map_regs(this_branch, insn->dst_reg,
+                             opcode == BPF_JEQ ? PTR_TO_MAP_VALUE : UNKNOWN_VALUE);
+               mark_map_regs(other_branch, insn->dst_reg,
+                             opcode == BPF_JEQ ? UNKNOWN_VALUE : PTR_TO_MAP_VALUE);
        } else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGT &&
                   dst_reg->type == PTR_TO_PACKET &&
                   regs[insn->src_reg].type == PTR_TO_PACKET_END) {
index b3f05ee20d1845736580d3c4fbd55d67e7fc3b51..9b7f838511cea8ea32f71adf3850e4517cddc8d4 100644 (file)
@@ -41,12 +41,7 @@ static DEFINE_PER_CPU(__u32, taskstats_seqnum);
 static int family_registered;
 struct kmem_cache *taskstats_cache;
 
-static struct genl_family family = {
-       .id             = GENL_ID_GENERATE,
-       .name           = TASKSTATS_GENL_NAME,
-       .version        = TASKSTATS_GENL_VERSION,
-       .maxattr        = TASKSTATS_CMD_ATTR_MAX,
-};
+static struct genl_family family;
 
 static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = {
        [TASKSTATS_CMD_ATTR_PID]  = { .type = NLA_U32 },
@@ -651,6 +646,15 @@ static const struct genl_ops taskstats_ops[] = {
        },
 };
 
+static struct genl_family family __ro_after_init = {
+       .name           = TASKSTATS_GENL_NAME,
+       .version        = TASKSTATS_GENL_VERSION,
+       .maxattr        = TASKSTATS_CMD_ATTR_MAX,
+       .module         = THIS_MODULE,
+       .ops            = taskstats_ops,
+       .n_ops          = ARRAY_SIZE(taskstats_ops),
+};
+
 /* Needed early in initialization */
 void __init taskstats_init_early(void)
 {
@@ -667,7 +671,7 @@ static int __init taskstats_init(void)
 {
        int rc;
 
-       rc = genl_register_family_with_ops(&family, taskstats_ops);
+       rc = genl_register_family(&family);
        if (rc)
                return rc;
 
index 5dcb99281259e40e2b9b6e1b31f6b9d11d15c48b..fa77311dadb23b35d78cf9060daf1dc0cc72b855 100644 (file)
@@ -422,6 +422,8 @@ static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id)
                return bpf_get_trace_printk_proto();
        case BPF_FUNC_get_smp_processor_id:
                return &bpf_get_smp_processor_id_proto;
+       case BPF_FUNC_get_numa_node_id:
+               return &bpf_get_numa_node_id_proto;
        case BPF_FUNC_perf_event_read:
                return &bpf_perf_event_read_proto;
        case BPF_FUNC_probe_write_user:
index 7d3a0af954e8f7b2eeb1a38dd98a60ce3c230aed..6356623fc23881e62c551f33124cf12e3229c525 100644 (file)
@@ -141,15 +141,6 @@ __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev)
 
 EXPORT_SYMBOL(fddi_type_trans);
 
-int fddi_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-EXPORT_SYMBOL(fddi_change_mtu);
-
 static const struct header_ops fddi_header_ops = {
        .create         = fddi_header,
 };
@@ -161,6 +152,8 @@ static void fddi_setup(struct net_device *dev)
        dev->type               = ARPHRD_FDDI;
        dev->hard_header_len    = FDDI_K_SNAP_HLEN+3;   /* Assume 802.2 SNAP hdr len + 3 pad bytes */
        dev->mtu                = FDDI_K_SNAP_DLEN;     /* Assume max payload of 802.2 SNAP frame */
+       dev->min_mtu            = FDDI_K_SNAP_HLEN;
+       dev->max_mtu            = FDDI_K_SNAP_DLEN;
        dev->addr_len           = FDDI_K_ALEN;
        dev->tx_queue_len       = 100;                  /* Long queues on FDDI */
        dev->flags              = IFF_BROADCAST | IFF_MULTICAST;
index ade1a52cdcff8e6a690b38bde8d7af1c140d7d9c..5e4427beab2bc2917aaaa004042d4ee1141a3457 100644 (file)
@@ -116,18 +116,6 @@ __be16 hippi_type_trans(struct sk_buff *skb, struct net_device *dev)
 
 EXPORT_SYMBOL(hippi_type_trans);
 
-int hippi_change_mtu(struct net_device *dev, int new_mtu)
-{
-       /*
-        * HIPPI's got these nice large MTUs.
-        */
-       if ((new_mtu < 68) || (new_mtu > 65280))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-EXPORT_SYMBOL(hippi_change_mtu);
-
 /*
  * For HIPPI we will actually use the lower 4 bytes of the hardware
  * address as the I-FIELD rather than the actual hardware address.
@@ -174,6 +162,8 @@ static void hippi_setup(struct net_device *dev)
        dev->type               = ARPHRD_HIPPI;
        dev->hard_header_len    = HIPPI_HLEN;
        dev->mtu                = 65280;
+       dev->min_mtu            = 68;
+       dev->max_mtu            = 65280;
        dev->addr_len           = HIPPI_ALEN;
        dev->tx_queue_len       = 25 /* 5 */;
        memset(dev->broadcast, 0xFF, HIPPI_ALEN);
index f2531ad66b68b358ea86f624763029404a262868..a793655745317b73481d402d7f6353e8a6815d56 100644 (file)
@@ -515,8 +515,8 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
                return -EFAULT;
 
        /* Null terminate this sucker, just in case. */
-       args.device1[23] = 0;
-       args.u.device2[23] = 0;
+       args.device1[sizeof(args.device1) - 1] = 0;
+       args.u.device2[sizeof(args.u.device2) - 1] = 0;
 
        rtnl_lock();
 
@@ -571,8 +571,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
                err = -EPERM;
                if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
-               if ((args.u.name_type >= 0) &&
-                   (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
+               if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) {
                        struct vlan_net *vn;
 
                        vn = net_generic(net, vlan_net_id);
index fbfacd51aa3407f3d0289468a073da04fecd742e..10da6c588bf84f45cdd237ae5d56c9975be5a1b2 100644 (file)
@@ -826,5 +826,8 @@ void vlan_setup(struct net_device *dev)
        dev->destructor         = vlan_dev_free;
        dev->ethtool_ops        = &vlan_ethtool_ops;
 
+       dev->min_mtu            = 0;
+       dev->max_mtu            = ETH_MAX_MTU;
+
        eth_zero_addr(dev->broadcast);
 }
index aa0047c5c4672947b2b7d153dbd8a394e70ccbdf..fca84e111c8959ace7d6ec9a10dd0081c2944cd7 100644 (file)
@@ -620,14 +620,12 @@ error:
 static const struct net_device_ops br2684_netdev_ops = {
        .ndo_start_xmit         = br2684_start_xmit,
        .ndo_set_mac_address    = br2684_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
 static const struct net_device_ops br2684_netdev_ops_routed = {
        .ndo_start_xmit         = br2684_start_xmit,
        .ndo_set_mac_address    = br2684_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu
 };
 
 static void br2684_setup(struct net_device *netdev)
@@ -651,7 +649,9 @@ static void br2684_setup_routed(struct net_device *netdev)
        netdev->hard_header_len = sizeof(llc_oui_ipv4); /* worst case */
        netdev->netdev_ops = &br2684_netdev_ops_routed;
        netdev->addr_len = 0;
-       netdev->mtu = 1500;
+       netdev->mtu = ETH_DATA_LEN;
+       netdev->min_mtu = 0;
+       netdev->max_mtu = ETH_MAX_MTU;
        netdev->type = ARPHRD_PPP;
        netdev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
        netdev->tx_queue_len = 100;
index 5d2693826afb6a84f8f614129bd9c4abf2824f9e..779b3fa6052d68648c3f8b7a8d3f85292be453e1 100644 (file)
@@ -544,15 +544,6 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
        return 0;
 }
 
-/* shamelessly stolen from drivers/net/net_init.c */
-static int lec_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 68) || (new_mtu > 18190))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static void lec_set_multicast_list(struct net_device *dev)
 {
        /*
@@ -565,7 +556,6 @@ static const struct net_device_ops lec_netdev_ops = {
        .ndo_open               = lec_open,
        .ndo_stop               = lec_close,
        .ndo_start_xmit         = lec_start_xmit,
-       .ndo_change_mtu         = lec_change_mtu,
        .ndo_tx_timeout         = lec_tx_timeout,
        .ndo_set_rx_mode        = lec_set_multicast_list,
 };
@@ -742,6 +732,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg)
                if (!dev_lec[i])
                        return -ENOMEM;
                dev_lec[i]->netdev_ops = &lec_netdev_ops;
+               dev_lec[i]->max_mtu = 18190;
                snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
                if (register_netdev(dev_lec[i])) {
                        free_netdev(dev_lec[i]);
index f20742cbae6d3d69cd959a8baa53922f3d45c356..b73b96a2854b152eebf8e9a5c68caa892318c6e6 100644 (file)
@@ -17,7 +17,7 @@ config BATMAN_ADV
 
 config BATMAN_ADV_BATMAN_V
        bool "B.A.T.M.A.N. V protocol (experimental)"
-       depends on BATMAN_ADV && CFG80211=y || (CFG80211=m && BATMAN_ADV=m)
+       depends on BATMAN_ADV && !(CFG80211=m && BATMAN_ADV=y)
        default n
        help
          This option enables the B.A.T.M.A.N. V protocol, the successor
index e2d18d0b1f06260ad69cb0d8c012ded379f582c3..0b9be62aee45426d7af25e05288ad52de80f8142 100644 (file)
@@ -2486,7 +2486,7 @@ batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
        struct batadv_orig_node *orig_node;
 
        rcu_read_lock();
-       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
                orig_node = gw_node->orig_node;
                router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
                if (!router)
@@ -2674,7 +2674,7 @@ static void batadv_iv_gw_print(struct batadv_priv *bat_priv,
                 "      Gateway      (#/255)           Nexthop [outgoingIF]: advertised uplink bandwidth\n");
 
        rcu_read_lock();
-       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
                /* fails if orig_node has no router */
                if (batadv_iv_gw_write_buffer_text(bat_priv, seq, gw_node) < 0)
                        continue;
@@ -2774,7 +2774,7 @@ static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
        int idx = 0;
 
        rcu_read_lock();
-       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
                if (idx++ < idx_skip)
                        continue;
 
index e79f6f01182eb6731927aea1bc0cba553fb600ff..2ac612d7bab4d0b4035c9e476dab17536349dca3 100644 (file)
@@ -750,7 +750,7 @@ batadv_v_gw_get_best_gw_node(struct batadv_priv *bat_priv)
        u32 max_bw = 0, bw;
 
        rcu_read_lock();
-       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
                if (!kref_get_unless_zero(&gw_node->refcount))
                        continue;
 
@@ -787,7 +787,7 @@ static bool batadv_v_gw_is_eligible(struct batadv_priv *bat_priv,
                                    struct batadv_orig_node *curr_gw_orig,
                                    struct batadv_orig_node *orig_node)
 {
-       struct batadv_gw_node *curr_gw = NULL, *orig_gw = NULL;
+       struct batadv_gw_node *curr_gw, *orig_gw = NULL;
        u32 gw_throughput, orig_throughput, threshold;
        bool ret = false;
 
@@ -889,7 +889,7 @@ static void batadv_v_gw_print(struct batadv_priv *bat_priv,
                 "      Gateway        ( throughput)           Nexthop [outgoingIF]: advertised uplink bandwidth\n");
 
        rcu_read_lock();
-       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
                /* fails if orig_node has no router */
                if (batadv_v_gw_write_buffer_text(bat_priv, seq, gw_node) < 0)
                        continue;
@@ -1009,7 +1009,7 @@ static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
        int idx = 0;
 
        rcu_read_lock();
-       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
+       hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
                if (idx++ < idx_skip)
                        continue;
 
index 1aeeadca620cd090ce763ef017cb01f6a2ec2890..61ff5f82cfbf636971f9c26b4b228c6bd49a2b2a 100644 (file)
@@ -401,7 +401,7 @@ static int batadv_v_ogm_metric_update(struct batadv_priv *bat_priv,
                                      struct batadv_hard_iface *if_incoming,
                                      struct batadv_hard_iface *if_outgoing)
 {
-       struct batadv_orig_ifinfo *orig_ifinfo = NULL;
+       struct batadv_orig_ifinfo *orig_ifinfo;
        struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
        bool protection_started = false;
        int ret = -EINVAL;
@@ -486,7 +486,7 @@ static bool batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
                                      struct batadv_hard_iface *if_outgoing)
 {
        struct batadv_neigh_node *router = NULL;
-       struct batadv_orig_node *orig_neigh_node = NULL;
+       struct batadv_orig_node *orig_neigh_node;
        struct batadv_neigh_node *orig_neigh_router = NULL;
        struct batadv_neigh_ifinfo *router_ifinfo = NULL, *neigh_ifinfo = NULL;
        u32 router_throughput, neigh_throughput;
index b4ffba7dd58331bcba72e045cbe5b63d99c405f1..77925504379dac7d64777393ddae326b5d6d9505 100644 (file)
@@ -186,7 +186,7 @@ struct batadv_debuginfo batadv_debuginfo_##_name = {        \
 /* the following attributes are general and therefore they will be directly
  * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs
  */
-static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open);
+static BATADV_DEBUGINFO(routing_algos, 0444, batadv_algorithms_open);
 
 static struct batadv_debuginfo *batadv_general_debuginfos[] = {
        &batadv_debuginfo_routing_algos,
@@ -194,26 +194,24 @@ static struct batadv_debuginfo *batadv_general_debuginfos[] = {
 };
 
 /* The following attributes are per soft interface */
-static BATADV_DEBUGINFO(neighbors, S_IRUGO, neighbors_open);
-static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open);
-static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open);
-static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
-                       batadv_transtable_global_open);
+static BATADV_DEBUGINFO(neighbors, 0444, neighbors_open);
+static BATADV_DEBUGINFO(originators, 0444, batadv_originators_open);
+static BATADV_DEBUGINFO(gateways, 0444, batadv_gateways_open);
+static BATADV_DEBUGINFO(transtable_global, 0444, batadv_transtable_global_open);
 #ifdef CONFIG_BATMAN_ADV_BLA
-static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
-static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
+static BATADV_DEBUGINFO(bla_claim_table, 0444, batadv_bla_claim_table_open);
+static BATADV_DEBUGINFO(bla_backbone_table, 0444,
                        batadv_bla_backbone_table_open);
 #endif
 #ifdef CONFIG_BATMAN_ADV_DAT
-static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
+static BATADV_DEBUGINFO(dat_cache, 0444, batadv_dat_cache_open);
 #endif
-static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
-                       batadv_transtable_local_open);
+static BATADV_DEBUGINFO(transtable_local, 0444, batadv_transtable_local_open);
 #ifdef CONFIG_BATMAN_ADV_NC
-static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
+static BATADV_DEBUGINFO(nc_nodes, 0444, batadv_nc_nodes_open);
 #endif
 #ifdef CONFIG_BATMAN_ADV_MCAST
-static BATADV_DEBUGINFO(mcast_flags, S_IRUGO, batadv_mcast_flags_open);
+static BATADV_DEBUGINFO(mcast_flags, 0444, batadv_mcast_flags_open);
 #endif
 
 static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
@@ -253,7 +251,7 @@ struct batadv_debuginfo batadv_hardif_debuginfo_##_name = { \
        },                                                      \
 }
 
-static BATADV_HARDIF_DEBUGINFO(originators, S_IRUGO,
+static BATADV_HARDIF_DEBUGINFO(originators, 0444,
                               batadv_originators_hardif_open);
 
 static struct batadv_debuginfo *batadv_hardif_debuginfos[] = {
index e257efdc5d0374cdb13ad8c3282269049eeb4d16..cbb4f3232a7b280be167bd200c27d33f9f953fb8 100644 (file)
@@ -369,12 +369,11 @@ out:
  * batadv_dbg_arp - print a debug message containing all the ARP packet details
  * @bat_priv: the bat priv with all the soft interface information
  * @skb: ARP packet
- * @type: ARP type
  * @hdr_size: size of the possible header before the ARP packet
  * @msg: message to print together with the debugging information
  */
 static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
-                          u16 type, int hdr_size, char *msg)
+                          int hdr_size, char *msg)
 {
        struct batadv_unicast_4addr_packet *unicast_4addr_packet;
        struct batadv_bcast_packet *bcast_pkt;
@@ -441,7 +440,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
 #else
 
 static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
-                          u16 type, int hdr_size, char *msg)
+                          int hdr_size, char *msg)
 {
 }
 
@@ -983,8 +982,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
        if (type != ARPOP_REQUEST)
                goto out;
 
-       batadv_dbg_arp(bat_priv, skb, type, hdr_size,
-                      "Parsing outgoing ARP REQUEST");
+       batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing outgoing ARP REQUEST");
 
        ip_src = batadv_arp_ip_src(skb, hdr_size);
        hw_src = batadv_arp_hw_src(skb, hdr_size);
@@ -1075,8 +1073,7 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
        ip_src = batadv_arp_ip_src(skb, hdr_size);
        ip_dst = batadv_arp_ip_dst(skb, hdr_size);
 
-       batadv_dbg_arp(bat_priv, skb, type, hdr_size,
-                      "Parsing incoming ARP REQUEST");
+       batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing incoming ARP REQUEST");
 
        batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
 
@@ -1149,8 +1146,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
        if (type != ARPOP_REPLY)
                return;
 
-       batadv_dbg_arp(bat_priv, skb, type, hdr_size,
-                      "Parsing outgoing ARP REPLY");
+       batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing outgoing ARP REPLY");
 
        hw_src = batadv_arp_hw_src(skb, hdr_size);
        ip_src = batadv_arp_ip_src(skb, hdr_size);
@@ -1195,8 +1191,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
        if (type != ARPOP_REPLY)
                goto out;
 
-       batadv_dbg_arp(bat_priv, skb, type, hdr_size,
-                      "Parsing incoming ARP REPLY");
+       batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing incoming ARP REPLY");
 
        hw_src = batadv_arp_hw_src(skb, hdr_size);
        ip_src = batadv_arp_ip_src(skb, hdr_size);
index 0934730fb7ffb539cd89dc29e3b7a8d9630c51b6..2b967a34703d2c7a5d78b0cc976106b77dd2dde3 100644 (file)
@@ -73,7 +73,7 @@ void batadv_frag_purge_orig(struct batadv_orig_node *orig_node,
                spin_lock_bh(&chain->lock);
 
                if (!check_cb || check_cb(chain)) {
-                       batadv_frag_clear_chain(&chain->head);
+                       batadv_frag_clear_chain(&chain->fragment_list);
                        chain->size = 0;
                }
 
@@ -117,8 +117,8 @@ static bool batadv_frag_init_chain(struct batadv_frag_table_entry *chain,
        if (chain->seqno == seqno)
                return false;
 
-       if (!hlist_empty(&chain->head))
-               batadv_frag_clear_chain(&chain->head);
+       if (!hlist_empty(&chain->fragment_list))
+               batadv_frag_clear_chain(&chain->fragment_list);
 
        chain->size = 0;
        chain->seqno = seqno;
@@ -176,7 +176,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
        chain = &orig_node->fragments[bucket];
        spin_lock_bh(&chain->lock);
        if (batadv_frag_init_chain(chain, seqno)) {
-               hlist_add_head(&frag_entry_new->list, &chain->head);
+               hlist_add_head(&frag_entry_new->list, &chain->fragment_list);
                chain->size = skb->len - hdr_size;
                chain->timestamp = jiffies;
                chain->total_size = ntohs(frag_packet->total_size);
@@ -185,7 +185,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
        }
 
        /* Find the position for the new fragment. */
-       hlist_for_each_entry(frag_entry_curr, &chain->head, list) {
+       hlist_for_each_entry(frag_entry_curr, &chain->fragment_list, list) {
                /* Drop packet if fragment already exists. */
                if (frag_entry_curr->no == frag_entry_new->no)
                        goto err_unlock;
@@ -220,11 +220,11 @@ out:
                 * exceeds the maximum size of one merged packet. Don't allow
                 * packets to have different total_size.
                 */
-               batadv_frag_clear_chain(&chain->head);
+               batadv_frag_clear_chain(&chain->fragment_list);
                chain->size = 0;
        } else if (ntohs(frag_packet->total_size) == chain->size) {
                /* All fragments received. Hand over chain to caller. */
-               hlist_move_list(&chain->head, chain_out);
+               hlist_move_list(&chain->fragment_list, chain_out);
                chain->size = 0;
        }
 
@@ -252,7 +252,7 @@ batadv_frag_merge_packets(struct hlist_head *chain)
 {
        struct batadv_frag_packet *packet;
        struct batadv_frag_list_entry *entry;
-       struct sk_buff *skb_out = NULL;
+       struct sk_buff *skb_out;
        int size, hdr_size = sizeof(struct batadv_frag_packet);
 
        /* Remove first entry, as this is the destination for the rest of the
@@ -352,7 +352,7 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
                         struct batadv_orig_node *orig_node_src)
 {
        struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
-       struct batadv_orig_node *orig_node_dst = NULL;
+       struct batadv_orig_node *orig_node_dst;
        struct batadv_neigh_node *neigh_node = NULL;
        struct batadv_frag_packet *packet;
        u16 total_size;
index 3202fe329e639abbb4c955092e97c7735a5fead6..b95f619606af86b7e0b557bf67b911ceac5b0d54 100644 (file)
@@ -47,7 +47,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
 static inline bool
 batadv_frag_check_entry(struct batadv_frag_table_entry *frags_entry)
 {
-       if (!hlist_empty(&frags_entry->head) &&
+       if (!hlist_empty(&frags_entry->fragment_list) &&
            batadv_has_timed_out(frags_entry->timestamp, BATADV_FRAG_TIMEOUT))
                return true;
        return false;
index de055d64debe4b335627ad74aeba60d6b0e4f6f2..52b8bd6ec43183519a63483950c2e886e47a6f9e 100644 (file)
@@ -348,7 +348,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
 
        spin_lock_bh(&bat_priv->gw.list_lock);
        kref_get(&gw_node->refcount);
-       hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list);
+       hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.gateway_list);
        spin_unlock_bh(&bat_priv->gw.list_lock);
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -376,7 +376,8 @@ struct batadv_gw_node *batadv_gw_node_get(struct batadv_priv *bat_priv,
        struct batadv_gw_node *gw_node_tmp, *gw_node = NULL;
 
        rcu_read_lock();
-       hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.list, list) {
+       hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.gateway_list,
+                                list) {
                if (gw_node_tmp->orig_node != orig_node)
                        continue;
 
@@ -475,7 +476,7 @@ void batadv_gw_node_free(struct batadv_priv *bat_priv)
 
        spin_lock_bh(&bat_priv->gw.list_lock);
        hlist_for_each_entry_safe(gw_node, node_tmp,
-                                 &bat_priv->gw.list, list) {
+                                 &bat_priv->gw.gateway_list, list) {
                hlist_del_init_rcu(&gw_node->list);
                batadv_gw_node_put(gw_node);
        }
@@ -704,7 +705,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
 {
        struct batadv_neigh_node *neigh_curr = NULL;
        struct batadv_neigh_node *neigh_old = NULL;
-       struct batadv_orig_node *orig_dst_node = NULL;
+       struct batadv_orig_node *orig_dst_node;
        struct batadv_gw_node *gw_node = NULL;
        struct batadv_gw_node *curr_gw = NULL;
        struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo;
index cbbf87075f06fc7c68103a9a65147748b706e40b..557a7044cfbccecd3b2a5e66659a3ac151d819fa 100644 (file)
@@ -61,36 +61,6 @@ void batadv_hash_set_lock_class(struct batadv_hashtable *hash,
 /* free only the hashtable and the hash itself. */
 void batadv_hash_destroy(struct batadv_hashtable *hash);
 
-/* remove the hash structure. if hashdata_free_cb != NULL, this function will be
- * called to remove the elements inside of the hash.  if you don't remove the
- * elements, memory might be leaked.
- */
-static inline void batadv_hash_delete(struct batadv_hashtable *hash,
-                                     batadv_hashdata_free_cb free_cb,
-                                     void *arg)
-{
-       struct hlist_head *head;
-       struct hlist_node *node, *node_tmp;
-       spinlock_t *list_lock; /* spinlock to protect write access */
-       u32 i;
-
-       for (i = 0; i < hash->size; i++) {
-               head = &hash->table[i];
-               list_lock = &hash->list_locks[i];
-
-               spin_lock_bh(list_lock);
-               hlist_for_each_safe(node, node_tmp, head) {
-                       hlist_del_rcu(node);
-
-                       if (free_cb)
-                               free_cb(node, arg);
-               }
-               spin_unlock_bh(list_lock);
-       }
-
-       batadv_hash_destroy(hash);
-}
-
 /**
  *     batadv_hash_add - adds data to the hashtable
  *     @hash: storage hash table
index 378cc1119d6664ff1dcbf5993a8b2871505c6939..b310f381ae028d26ed89dea88ba071b7433cfca4 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/stat.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
 #include <linux/uaccess.h>
@@ -322,8 +321,8 @@ int batadv_socket_setup(struct batadv_priv *bat_priv)
        if (!bat_priv->debug_dir)
                goto err;
 
-       d = debugfs_create_file(BATADV_ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR,
-                               bat_priv->debug_dir, bat_priv, &batadv_fops);
+       d = debugfs_create_file(BATADV_ICMP_SOCKET, 0600, bat_priv->debug_dir,
+                               bat_priv, &batadv_fops);
        if (!d)
                goto err;
 
index 56dc532f7a2c276e98690ed37055d0b4a9fe39c8..c73c31769abaf9c802c408f1e7fae17c9db134b7 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/sched.h> /* for linux/wait.h */
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/stat.h>
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
@@ -212,8 +211,7 @@ int batadv_debug_log_setup(struct batadv_priv *bat_priv)
        spin_lock_init(&bat_priv->debug_log->lock);
        init_waitqueue_head(&bat_priv->debug_log->queue_wait);
 
-       d = debugfs_create_file("log", S_IFREG | S_IRUSR,
-                               bat_priv->debug_dir, bat_priv,
+       d = debugfs_create_file("log", 0400, bat_priv->debug_dir, bat_priv,
                                &batadv_log_fops);
        if (!d)
                goto err;
index d2905a855d1b9b3e55b102ec7c4b33a389395476..3284a7b0325dc631bc8de438a0f62ba8587c9f50 100644 (file)
@@ -71,12 +71,12 @@ int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
 __printf(2, 3);
 
 /* possibly ratelimited debug output */
-#define _batadv_dbg(type, bat_priv, ratelimited, fmt, arg...)  \
-       do {                                                    \
-               if (atomic_read(&bat_priv->log_level) & type && \
-                   (!ratelimited || net_ratelimit()))          \
-                       batadv_debug_log(bat_priv, fmt, ## arg);\
-       }                                                       \
+#define _batadv_dbg(type, bat_priv, ratelimited, fmt, arg...)          \
+       do {                                                            \
+               if (atomic_read(&(bat_priv)->log_level) & (type) &&     \
+                   (!(ratelimited) || net_ratelimit()))                \
+                       batadv_debug_log(bat_priv, fmt, ## arg);        \
+       }                                                               \
        while (0)
 #else /* !CONFIG_BATMAN_ADV_DEBUG */
 __printf(4, 5)
index 2c017ab47557bbb57dfd996fe8cb605a833f977e..5e4e818529d33ca0d54aed1318ed10693dd9356a 100644 (file)
@@ -160,7 +160,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
 
        INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
        INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
-       INIT_HLIST_HEAD(&bat_priv->gw.list);
+       INIT_HLIST_HEAD(&bat_priv->gw.gateway_list);
 #ifdef CONFIG_BATMAN_ADV_MCAST
        INIT_HLIST_HEAD(&bat_priv->mcast.want_all_unsnoopables_list);
        INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv4_list);
index 09af21e27639675234b42e97124d87d8572ccbe2..daddca94feb89f8c53248998dbc4379a01ef6891 100644 (file)
@@ -24,7 +24,7 @@
 #define BATADV_DRIVER_DEVICE "batman-adv"
 
 #ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2016.4"
+#define BATADV_SOURCE_VERSION "2016.5"
 #endif
 
 /* B.A.T.M.A.N. parameters */
@@ -185,7 +185,6 @@ enum batadv_uev_type {
 
 #include <linux/bitops.h> /* for packet.h */
 #include <linux/compiler.h>
-#include <linux/cpumask.h>
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h> /* for packet.h */
 #include <linux/if_vlan.h>
@@ -200,8 +199,8 @@ struct packet_type;
 struct seq_file;
 struct sk_buff;
 
-#define BATADV_PRINT_VID(vid) ((vid & BATADV_VLAN_HAS_TAG) ? \
-                              (int)(vid & VLAN_VID_MASK) : -1)
+#define BATADV_PRINT_VID(vid) (((vid) & BATADV_VLAN_HAS_TAG) ? \
+                              (int)((vid) & VLAN_VID_MASK) : -1)
 
 extern struct list_head batadv_hardif_list;
 
@@ -284,26 +283,6 @@ static inline void batadv_add_counter(struct batadv_priv *bat_priv, size_t idx,
 
 #define batadv_inc_counter(b, i) batadv_add_counter(b, i, 1)
 
-/**
- * batadv_sum_counter - Sum the cpu-local counters for index 'idx'
- * @bat_priv: the bat priv with all the soft interface information
- * @idx: index of counter to sum up
- *
- * Return: sum of all cpu-local counters
- */
-static inline u64 batadv_sum_counter(struct batadv_priv *bat_priv,  size_t idx)
-{
-       u64 *counters, sum = 0;
-       int cpu;
-
-       for_each_possible_cpu(cpu) {
-               counters = per_cpu_ptr(bat_priv->bat_counters, cpu);
-               sum += counters[idx];
-       }
-
-       return sum;
-}
-
 /* Define a macro to reach the control buffer of the skb. The members of the
  * control buffer are defined in struct batadv_skb_cb in types.h.
  * The macro is inspired by the similar macro TCP_SKB_CB() in tcp.h.
index 64cb6acbe0a64bf8da5c5b03c1874b9e886f369f..005012ba9b48279040fe30e40f99892474601bc0 100644 (file)
 #include "tp_meter.h"
 #include "translation-table.h"
 
-struct genl_family batadv_netlink_family = {
-       .id = GENL_ID_GENERATE,
-       .hdrsize = 0,
-       .name = BATADV_NL_NAME,
-       .version = 1,
-       .maxattr = BATADV_ATTR_MAX,
-       .netnsok = true,
-};
+struct genl_family batadv_netlink_family;
 
 /* multicast groups */
 enum batadv_netlink_multicast_groups {
@@ -610,6 +603,19 @@ static struct genl_ops batadv_netlink_ops[] = {
 
 };
 
+struct genl_family batadv_netlink_family __ro_after_init = {
+       .hdrsize = 0,
+       .name = BATADV_NL_NAME,
+       .version = 1,
+       .maxattr = BATADV_ATTR_MAX,
+       .netnsok = true,
+       .module = THIS_MODULE,
+       .ops = batadv_netlink_ops,
+       .n_ops = ARRAY_SIZE(batadv_netlink_ops),
+       .mcgrps = batadv_netlink_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps),
+};
+
 /**
  * batadv_netlink_register - register batadv genl netlink family
  */
@@ -617,9 +623,7 @@ void __init batadv_netlink_register(void)
 {
        int ret;
 
-       ret = genl_register_family_with_ops_groups(&batadv_netlink_family,
-                                                  batadv_netlink_ops,
-                                                  batadv_netlink_mcgrps);
+       ret = genl_register_family(&batadv_netlink_family);
        if (ret)
                pr_warn("unable to register netlink family");
 }
index e3baf697a35c0e1584b08361ef905a6652c6e04f..c213ddec86ade0f7008b15fbdc01651ee7980407 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/stat.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
 #include <linux/workqueue.h>
@@ -1961,17 +1960,16 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv)
        if (!nc_dir)
                goto out;
 
-       file = debugfs_create_u8("min_tq", S_IRUGO | S_IWUSR, nc_dir,
-                                &bat_priv->nc.min_tq);
+       file = debugfs_create_u8("min_tq", 0644, nc_dir, &bat_priv->nc.min_tq);
        if (!file)
                goto out;
 
-       file = debugfs_create_u32("max_fwd_delay", S_IRUGO | S_IWUSR, nc_dir,
+       file = debugfs_create_u32("max_fwd_delay", 0644, nc_dir,
                                  &bat_priv->nc.max_fwd_delay);
        if (!file)
                goto out;
 
-       file = debugfs_create_u32("max_buffer_time", S_IRUGO | S_IWUSR, nc_dir,
+       file = debugfs_create_u32("max_buffer_time", 0644, nc_dir,
                                  &bat_priv->nc.max_buffer_time);
        if (!file)
                goto out;
index 7c8d16086f0fddbcfb85b32e8bff9223befce0ab..c6e7e1e39b709e3cf01ae883a9b568d5f76cda4c 100644 (file)
@@ -364,7 +364,7 @@ struct batadv_orig_ifinfo *
 batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
                       struct batadv_hard_iface *if_outgoing)
 {
-       struct batadv_orig_ifinfo *orig_ifinfo = NULL;
+       struct batadv_orig_ifinfo *orig_ifinfo;
        unsigned long reset_time;
 
        spin_lock_bh(&orig_node->neigh_list_lock);
@@ -520,7 +520,7 @@ batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
                           const u8 *neigh_addr)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
-       struct batadv_hardif_neigh_node *hardif_neigh = NULL;
+       struct batadv_hardif_neigh_node *hardif_neigh;
 
        spin_lock_bh(&hard_iface->neigh_list_lock);
 
@@ -563,7 +563,7 @@ static struct batadv_hardif_neigh_node *
 batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface,
                                  const u8 *neigh_addr)
 {
-       struct batadv_hardif_neigh_node *hardif_neigh = NULL;
+       struct batadv_hardif_neigh_node *hardif_neigh;
 
        /* first check without locking to avoid the overhead */
        hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr);
@@ -683,7 +683,7 @@ batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node,
                                struct batadv_hard_iface *hard_iface,
                                const u8 *neigh_addr)
 {
-       struct batadv_neigh_node *neigh_node = NULL;
+       struct batadv_neigh_node *neigh_node;
 
        /* first check without locking to avoid the overhead */
        neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
@@ -1021,7 +1021,7 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
        batadv_orig_node_vlan_put(vlan);
 
        for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) {
-               INIT_HLIST_HEAD(&orig_node->fragments[i].head);
+               INIT_HLIST_HEAD(&orig_node->fragments[i].fragment_list);
                spin_lock_init(&orig_node->fragments[i].lock);
                orig_node->fragments[i].size = 0;
        }
index 6afc0b86950eca24633fc28138c643598e07c84f..7a36bcfa0ba01993080b2ad1ddca94ca0d50adc9 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/byteorder.h>
 #include <linux/types.h>
 
-#define batadv_tp_is_error(n) ((u8)n > 127 ? 1 : 0)
+#define batadv_tp_is_error(n) ((u8)(n) > 127 ? 1 : 0)
 
 /**
  * enum batadv_packettype - types for batman-adv encapsulated packets
@@ -251,16 +251,6 @@ struct batadv_elp_packet {
 
 #define BATADV_ELP_HLEN sizeof(struct batadv_elp_packet)
 
-/**
- * enum batadv_icmp_user_cmd_type - types for batman-adv icmp cmd modes
- * @BATADV_TP_START: start a throughput meter run
- * @BATADV_TP_STOP: stop a throughput meter run
- */
-enum batadv_icmp_user_cmd_type {
-       BATADV_TP_START         = 0,
-       BATADV_TP_STOP          = 2,
-};
-
 /**
  * struct batadv_icmp_header - common members among all the ICMP packets
  * @packet_type: batman-adv packet type, part of the general header
index 8d4e1f57857455ea5694ed7a8ef014a70cdee7b4..e1e9136db6e8823beb85ab94c8a21f7b3f78739f 100644 (file)
@@ -562,7 +562,7 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
                                    const struct sk_buff *skb,
                                    unsigned long delay)
 {
-       struct batadv_hard_iface *primary_if = NULL;
+       struct batadv_hard_iface *primary_if;
        struct batadv_forw_packet *forw_packet;
        struct batadv_bcast_packet *bcast_packet;
        struct sk_buff *newskb;
index 49e16b6e0ba3391f36aa60fdadf756df7058f0ba..f37c1c769da0dbec2ec79c1b4f35e0d4b8b0b280 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/byteorder/generic.h>
 #include <linux/cache.h>
 #include <linux/compiler.h>
+#include <linux/cpumask.h>
 #include <linux/errno.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -116,6 +117,26 @@ static int batadv_interface_release(struct net_device *dev)
        return 0;
 }
 
+/**
+ * batadv_sum_counter - Sum the cpu-local counters for index 'idx'
+ * @bat_priv: the bat priv with all the soft interface information
+ * @idx: index of counter to sum up
+ *
+ * Return: sum of all cpu-local counters
+ */
+static u64 batadv_sum_counter(struct batadv_priv *bat_priv,  size_t idx)
+{
+       u64 *counters, sum = 0;
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               counters = per_cpu_ptr(bat_priv->bat_counters, cpu);
+               sum += counters[idx];
+       }
+
+       return sum;
+}
+
 static struct net_device_stats *batadv_interface_stats(struct net_device *dev)
 {
        struct batadv_priv *bat_priv = netdev_priv(dev);
index 02d96f224c602cb4568e3357199227ef668f9a23..17c844196eb26c9faf9fd543b88cd86cc1c2c029 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/rcupdate.h>
 #include <linux/rtnetlink.h>
 #include <linux/slab.h>
-#include <linux/stat.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
 #include <linux/stringify.h>
@@ -666,41 +665,36 @@ static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
        return count;
 }
 
-BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
-BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
+BATADV_ATTR_SIF_BOOL(aggregated_ogms, 0644, NULL);
+BATADV_ATTR_SIF_BOOL(bonding, 0644, NULL);
 #ifdef CONFIG_BATMAN_ADV_BLA
-BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR,
-                    batadv_bla_status_update);
+BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, 0644, batadv_bla_status_update);
 #endif
 #ifdef CONFIG_BATMAN_ADV_DAT
-BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
-                    batadv_dat_status_update);
+BATADV_ATTR_SIF_BOOL(distributed_arp_table, 0644, batadv_dat_status_update);
 #endif
-BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
-static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL);
-static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode,
-                  batadv_store_gw_mode);
-BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, S_IRUGO | S_IWUSR,
-                    2 * BATADV_JITTER, INT_MAX, NULL);
-BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0,
-                    BATADV_TQ_MAX_VALUE, NULL);
-static BATADV_ATTR(gw_sel_class, S_IRUGO | S_IWUSR, batadv_show_gw_sel_class,
+BATADV_ATTR_SIF_BOOL(fragmentation, 0644, batadv_update_min_mtu);
+static BATADV_ATTR(routing_algo, 0444, batadv_show_bat_algo, NULL);
+static BATADV_ATTR(gw_mode, 0644, batadv_show_gw_mode, batadv_store_gw_mode);
+BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, 0644, 2 * BATADV_JITTER,
+                    INT_MAX, NULL);
+BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, 0644, 0, BATADV_TQ_MAX_VALUE,
+                    NULL);
+static BATADV_ATTR(gw_sel_class, 0644, batadv_show_gw_sel_class,
                   batadv_store_gw_sel_class);
-static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
+static BATADV_ATTR(gw_bandwidth, 0644, batadv_show_gw_bwidth,
                   batadv_store_gw_bwidth);
 #ifdef CONFIG_BATMAN_ADV_MCAST
-BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL);
+BATADV_ATTR_SIF_BOOL(multicast_mode, 0644, NULL);
 #endif
 #ifdef CONFIG_BATMAN_ADV_DEBUG
-BATADV_ATTR_SIF_UINT(log_level, log_level, S_IRUGO | S_IWUSR, 0,
-                    BATADV_DBG_ALL, NULL);
+BATADV_ATTR_SIF_UINT(log_level, log_level, 0644, 0, BATADV_DBG_ALL, NULL);
 #endif
 #ifdef CONFIG_BATMAN_ADV_NC
-BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
-                    batadv_nc_status_update);
+BATADV_ATTR_SIF_BOOL(network_coding, 0644, batadv_nc_status_update);
 #endif
-static BATADV_ATTR(isolation_mark, S_IRUGO | S_IWUSR,
-                  batadv_show_isolation_mark, batadv_store_isolation_mark);
+static BATADV_ATTR(isolation_mark, 0644, batadv_show_isolation_mark,
+                  batadv_store_isolation_mark);
 
 static struct batadv_attribute *batadv_mesh_attrs[] = {
        &batadv_attr_aggregated_ogms,
@@ -731,7 +725,7 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
        NULL,
 };
 
-BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
+BATADV_ATTR_VLAN_BOOL(ap_isolation, 0644, NULL);
 
 /* array of vlan specific sysfs attributes */
 static struct batadv_attribute *batadv_vlan_attrs[] = {
@@ -1116,14 +1110,13 @@ static ssize_t batadv_show_throughput_override(struct kobject *kobj,
 
 #endif
 
-static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
+static BATADV_ATTR(mesh_iface, 0644, batadv_show_mesh_iface,
                   batadv_store_mesh_iface);
-static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
+static BATADV_ATTR(iface_status, 0444, batadv_show_iface_status, NULL);
 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
-BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR,
+BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, 0644,
                     2 * BATADV_JITTER, INT_MAX, NULL);
-static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR,
-                  batadv_show_throughput_override,
+static BATADV_ATTR(throughput_override, 0644, batadv_show_throughput_override,
                   batadv_store_throughput_override);
 #endif
 
index 7f663092f6de49831680600b2a83aedc15904bac..ad1e3bc0e205059b01fbeb2e5089371636a33197 100644 (file)
@@ -3835,8 +3835,8 @@ void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
 bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
                           unsigned short vid)
 {
-       struct batadv_tt_local_entry *tt_local_entry = NULL;
-       struct batadv_tt_global_entry *tt_global_entry = NULL;
+       struct batadv_tt_local_entry *tt_local_entry;
+       struct batadv_tt_global_entry *tt_global_entry;
        struct batadv_softif_vlan *vlan;
        bool ret = false;
 
@@ -3845,27 +3845,24 @@ bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
                return false;
 
        if (!atomic_read(&vlan->ap_isolation))
-               goto out;
+               goto vlan_put;
 
        tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid);
        if (!tt_local_entry)
-               goto out;
+               goto vlan_put;
 
        tt_global_entry = batadv_tt_global_hash_find(bat_priv, src, vid);
        if (!tt_global_entry)
-               goto out;
-
-       if (!_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
-               goto out;
+               goto local_entry_put;
 
-       ret = true;
+       if (_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
+               ret = true;
 
-out:
+       batadv_tt_global_entry_put(tt_global_entry);
+local_entry_put:
+       batadv_tt_local_entry_put(tt_local_entry);
+vlan_put:
        batadv_softif_vlan_put(vlan);
-       if (tt_global_entry)
-               batadv_tt_global_entry_put(tt_global_entry);
-       if (tt_local_entry)
-               batadv_tt_local_entry_put(tt_local_entry);
        return ret;
 }
 
index b3dd1a381aad9b2bc970515a84648721be624403..673a22e3a68a20704bebab1e326fc82190da3b05 100644 (file)
@@ -184,7 +184,7 @@ struct batadv_orig_ifinfo {
 
 /**
  * struct batadv_frag_table_entry - head in the fragment buffer table
- * @head: head of list with fragments
+ * @fragment_list: head of list with fragments
  * @lock: lock to protect the list of fragments
  * @timestamp: time (jiffie) of last received fragment
  * @seqno: sequence number of the fragments in the list
@@ -192,8 +192,8 @@ struct batadv_orig_ifinfo {
  * @total_size: expected size of the assembled packet
  */
 struct batadv_frag_table_entry {
-       struct hlist_head head;
-       spinlock_t lock; /* protects head */
+       struct hlist_head fragment_list;
+       spinlock_t lock; /* protects fragment_list */
        unsigned long timestamp;
        u16 seqno;
        u16 size;
@@ -706,8 +706,8 @@ struct batadv_priv_debug_log {
 
 /**
  * struct batadv_priv_gw - per mesh interface gateway data
- * @list: list of available gateway nodes
- * @list_lock: lock protecting gw_list & curr_gw
+ * @gateway_list: list of available gateway nodes
+ * @list_lock: lock protecting gateway_list & curr_gw
  * @curr_gw: pointer to currently selected gateway node
  * @mode: gateway operation: off, client or server (see batadv_gw_modes)
  * @sel_class: gateway selection class (applies if gw_mode client)
@@ -716,8 +716,8 @@ struct batadv_priv_debug_log {
  * @reselect: bool indicating a gateway re-selection is in progress
  */
 struct batadv_priv_gw {
-       struct hlist_head list;
-       spinlock_t list_lock; /* protects gw_list & curr_gw */
+       struct hlist_head gateway_list;
+       spinlock_t list_lock; /* protects gateway_list & curr_gw */
        struct batadv_gw_node __rcu *curr_gw;  /* rcu protected pointer */
        atomic_t mode;
        atomic_t sel_class;
@@ -1363,7 +1363,7 @@ struct batadv_skb_cb {
 
 /**
  * struct batadv_forw_packet - structure for bcast packets to be sent/forwarded
- * @list: list node for batadv_socket_client::queue_list
+ * @list: list node for batadv_priv::forw_{bat,bcast}_list
  * @send_time: execution time for delayed_work (packet sending)
  * @own: bool for locally generated packets (local OGMs are re-scheduled after
  *  sending)
index f4fcb4a9d5c1ed6e3fe81190ece8aa245808b395..2b875edf77e1df271715df200821b90929517b57 100644 (file)
@@ -211,7 +211,6 @@ static const struct net_device_ops bnep_netdev_ops = {
        .ndo_set_rx_mode     = bnep_net_set_mc_list,
        .ndo_set_mac_address = bnep_net_set_mac_addr,
        .ndo_tx_timeout      = bnep_net_timeout,
-       .ndo_change_mtu      = eth_change_mtu,
 
 };
 
@@ -222,6 +221,8 @@ void bnep_net_setup(struct net_device *dev)
        dev->addr_len = ETH_ALEN;
 
        ether_setup(dev);
+       dev->min_mtu = 0;
+       dev->max_mtu = ETH_MAX_MTU;
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        dev->netdev_ops = &bnep_netdev_ops;
 
index 89a687f3c0a33a19dd03b38c0b0b25762a81fe93..c08e02b67818fd5f4d27f442eef91f16fdeb978c 100644 (file)
@@ -185,7 +185,7 @@ static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev,
 static int br_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct net_bridge *br = netdev_priv(dev);
-       if (new_mtu < 68 || new_mtu > br_min_mtu(br))
+       if (new_mtu > br_min_mtu(br))
                return -EINVAL;
 
        dev->mtu = new_mtu;
@@ -410,6 +410,7 @@ void br_dev_setup(struct net_device *dev)
        br->bridge_hello_time = br->hello_time = 2 * HZ;
        br->bridge_forward_delay = br->forward_delay = 15 * HZ;
        br->ageing_time = BR_DEFAULT_AGEING_TIME;
+       dev->max_mtu = ETH_MAX_MTU;
 
        br_netfilter_rtable_init(br);
        br_stp_timer_init(br);
index 6b43c8c88f19b37bd4063347719f698beb2c377a..e4a4176171c91fa364e914e2aeb9d357209a1f93 100644 (file)
@@ -535,9 +535,8 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
                 */
                if (fdb->is_local)
                        return 0;
-               br_warn(br, "adding interface %s with same address "
-                      "as a received packet\n",
-                      source ? source->dev->name : br->dev->name);
+               br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)\n",
+                      source ? source->dev->name : br->dev->name, addr, vid);
                fdb_delete(br, fdb);
        }
 
@@ -583,9 +582,8 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
                /* attempt to update an entry for a local interface */
                if (unlikely(fdb->is_local)) {
                        if (net_ratelimit())
-                               br_warn(br, "received packet on %s with "
-                                       "own address as source address\n",
-                                       source->dev->name);
+                               br_warn(br, "received packet on %s with own address as source address (addr:%pM, vlan:%u)\n",
+                                       source->dev->name, addr, vid);
                } else {
                        /* fastpath: update of existing entry */
                        if (unlikely(source != fdb->dst)) {
index fa39fc29870867ca5a7323cdeab9ca3204a2653d..273cb07f57d87186224fb50943af949b99b3cde2 100644 (file)
@@ -390,8 +390,7 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
        rcu_read_lock();
 
        if (adapt_layer == NULL) {
-               pr_debug("link setup response but no client exist,"
-                               "send linkdown back\n");
+               pr_debug("link setup response but no client exist, send linkdown back\n");
                cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL);
                goto unlock;
        }
@@ -401,8 +400,7 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
 
        phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
        if (phyinfo == NULL) {
-               pr_err("ERROR: Link Layer Device disappeared"
-                               "while connecting\n");
+               pr_err("ERROR: Link Layer Device disappeared while connecting\n");
                goto unlock;
        }
 
@@ -436,8 +434,7 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
                servicel = cfdbgl_create(channel_id, &phyinfo->dev_info);
                break;
        default:
-               pr_err("Protocol error. Link setup response "
-                               "- unknown channel type\n");
+               pr_err("Protocol error. Link setup response - unknown channel type\n");
                goto unlock;
        }
        if (!servicel)
index b7de71f8d5d3a5fa947fa7306fa6812e9f166da5..bfb973aebb5b16a8cd04eebdd712bcd6006e86d6 100644 (file)
@@ -323,6 +323,27 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
 }
 EXPORT_SYMBOL(__skb_free_datagram_locked);
 
+int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
+                       unsigned int flags)
+{
+       int err = 0;
+
+       if (flags & MSG_PEEK) {
+               err = -ENOENT;
+               spin_lock_bh(&sk->sk_receive_queue.lock);
+               if (skb == skb_peek(&sk->sk_receive_queue)) {
+                       __skb_unlink(skb, &sk->sk_receive_queue);
+                       atomic_dec(&skb->users);
+                       err = 0;
+               }
+               spin_unlock_bh(&sk->sk_receive_queue.lock);
+       }
+
+       atomic_inc(&sk->sk_drops);
+       return err;
+}
+EXPORT_SYMBOL(__sk_queue_drop_skb);
+
 /**
  *     skb_kill_datagram - Free a datagram skbuff forcibly
  *     @sk: socket
@@ -346,23 +367,10 @@ EXPORT_SYMBOL(__skb_free_datagram_locked);
 
 int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
 {
-       int err = 0;
-
-       if (flags & MSG_PEEK) {
-               err = -ENOENT;
-               spin_lock_bh(&sk->sk_receive_queue.lock);
-               if (skb == skb_peek(&sk->sk_receive_queue)) {
-                       __skb_unlink(skb, &sk->sk_receive_queue);
-                       atomic_dec(&skb->users);
-                       err = 0;
-               }
-               spin_unlock_bh(&sk->sk_receive_queue.lock);
-       }
+       int err = __sk_queue_drop_skb(sk, skb, flags);
 
        kfree_skb(skb);
-       atomic_inc(&sk->sk_drops);
        sk_mem_reclaim_partial(sk);
-
        return err;
 }
 EXPORT_SYMBOL(skb_kill_datagram);
index 820bac239738eb021354ac95ca5bbdff1840cb8e..8341dadf5e946795604c6428b95af61e9a3a3ebf 100644 (file)
 #include <linux/errqueue.h>
 #include <linux/hrtimer.h>
 #include <linux/netfilter_ingress.h>
-#include <linux/sctp.h>
 #include <linux/crash_dump.h>
 
 #include "net-sysfs.h"
@@ -2492,141 +2491,6 @@ out:
 }
 EXPORT_SYMBOL(skb_checksum_help);
 
-/* skb_csum_offload_check - Driver helper function to determine if a device
- * with limited checksum offload capabilities is able to offload the checksum
- * for a given packet.
- *
- * Arguments:
- *   skb - sk_buff for the packet in question
- *   spec - contains the description of what device can offload
- *   csum_encapped - returns true if the checksum being offloaded is
- *           encpasulated. That is it is checksum for the transport header
- *           in the inner headers.
- *   checksum_help - when set indicates that helper function should
- *           call skb_checksum_help if offload checks fail
- *
- * Returns:
- *   true: Packet has passed the checksum checks and should be offloadable to
- *        the device (a driver may still need to check for additional
- *        restrictions of its device)
- *   false: Checksum is not offloadable. If checksum_help was set then
- *        skb_checksum_help was called to resolve checksum for non-GSO
- *        packets and when IP protocol is not SCTP
- */
-bool __skb_csum_offload_chk(struct sk_buff *skb,
-                           const struct skb_csum_offl_spec *spec,
-                           bool *csum_encapped,
-                           bool csum_help)
-{
-       struct iphdr *iph;
-       struct ipv6hdr *ipv6;
-       void *nhdr;
-       int protocol;
-       u8 ip_proto;
-
-       if (skb->protocol == htons(ETH_P_8021Q) ||
-           skb->protocol == htons(ETH_P_8021AD)) {
-               if (!spec->vlan_okay)
-                       goto need_help;
-       }
-
-       /* We check whether the checksum refers to a transport layer checksum in
-        * the outermost header or an encapsulated transport layer checksum that
-        * corresponds to the inner headers of the skb. If the checksum is for
-        * something else in the packet we need help.
-        */
-       if (skb_checksum_start_offset(skb) == skb_transport_offset(skb)) {
-               /* Non-encapsulated checksum */
-               protocol = eproto_to_ipproto(vlan_get_protocol(skb));
-               nhdr = skb_network_header(skb);
-               *csum_encapped = false;
-               if (spec->no_not_encapped)
-                       goto need_help;
-       } else if (skb->encapsulation && spec->encap_okay &&
-                  skb_checksum_start_offset(skb) ==
-                  skb_inner_transport_offset(skb)) {
-               /* Encapsulated checksum */
-               *csum_encapped = true;
-               switch (skb->inner_protocol_type) {
-               case ENCAP_TYPE_ETHER:
-                       protocol = eproto_to_ipproto(skb->inner_protocol);
-                       break;
-               case ENCAP_TYPE_IPPROTO:
-                       protocol = skb->inner_protocol;
-                       break;
-               }
-               nhdr = skb_inner_network_header(skb);
-       } else {
-               goto need_help;
-       }
-
-       switch (protocol) {
-       case IPPROTO_IP:
-               if (!spec->ipv4_okay)
-                       goto need_help;
-               iph = nhdr;
-               ip_proto = iph->protocol;
-               if (iph->ihl != 5 && !spec->ip_options_okay)
-                       goto need_help;
-               break;
-       case IPPROTO_IPV6:
-               if (!spec->ipv6_okay)
-                       goto need_help;
-               if (spec->no_encapped_ipv6 && *csum_encapped)
-                       goto need_help;
-               ipv6 = nhdr;
-               nhdr += sizeof(*ipv6);
-               ip_proto = ipv6->nexthdr;
-               break;
-       default:
-               goto need_help;
-       }
-
-ip_proto_again:
-       switch (ip_proto) {
-       case IPPROTO_TCP:
-               if (!spec->tcp_okay ||
-                   skb->csum_offset != offsetof(struct tcphdr, check))
-                       goto need_help;
-               break;
-       case IPPROTO_UDP:
-               if (!spec->udp_okay ||
-                   skb->csum_offset != offsetof(struct udphdr, check))
-                       goto need_help;
-               break;
-       case IPPROTO_SCTP:
-               if (!spec->sctp_okay ||
-                   skb->csum_offset != offsetof(struct sctphdr, checksum))
-                       goto cant_help;
-               break;
-       case NEXTHDR_HOP:
-       case NEXTHDR_ROUTING:
-       case NEXTHDR_DEST: {
-               u8 *opthdr = nhdr;
-
-               if (protocol != IPPROTO_IPV6 || !spec->ext_hdrs_okay)
-                       goto need_help;
-
-               ip_proto = opthdr[0];
-               nhdr += (opthdr[1] + 1) << 3;
-
-               goto ip_proto_again;
-       }
-       default:
-               goto need_help;
-       }
-
-       /* Passed the tests for offloading checksum */
-       return true;
-
-need_help:
-       if (csum_help && !skb_shinfo(skb)->gso_size)
-               skb_checksum_help(skb);
-cant_help:
-       return false;
-}
-EXPORT_SYMBOL(__skb_csum_offload_chk);
-
 __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
 {
        __be16 type = skb->protocol;
@@ -5275,6 +5139,13 @@ static struct netdev_adjacent *__netdev_find_adj(struct net_device *adj_dev,
        return NULL;
 }
 
+static int __netdev_has_upper_dev(struct net_device *upper_dev, void *data)
+{
+       struct net_device *dev = data;
+
+       return upper_dev == dev;
+}
+
 /**
  * netdev_has_upper_dev - Check if device is linked to an upper device
  * @dev: device
@@ -5289,10 +5160,29 @@ bool netdev_has_upper_dev(struct net_device *dev,
 {
        ASSERT_RTNL();
 
-       return __netdev_find_adj(upper_dev, &dev->all_adj_list.upper);
+       return netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev,
+                                            upper_dev);
 }
 EXPORT_SYMBOL(netdev_has_upper_dev);
 
+/**
+ * netdev_has_upper_dev_all - Check if device is linked to an upper device
+ * @dev: device
+ * @upper_dev: upper device to check
+ *
+ * Find out if a device is linked to specified upper device and return true
+ * in case it is. Note that this checks the entire upper device chain.
+ * The caller must hold rcu lock.
+ */
+
+bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
+                                 struct net_device *upper_dev)
+{
+       return !!netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev,
+                                              upper_dev);
+}
+EXPORT_SYMBOL(netdev_has_upper_dev_all_rcu);
+
 /**
  * netdev_has_any_upper_dev - Check if device is linked to some device
  * @dev: device
@@ -5304,7 +5194,7 @@ static bool netdev_has_any_upper_dev(struct net_device *dev)
 {
        ASSERT_RTNL();
 
-       return !list_empty(&dev->all_adj_list.upper);
+       return !list_empty(&dev->adj_list.upper);
 }
 
 /**
@@ -5331,6 +5221,20 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
 }
 EXPORT_SYMBOL(netdev_master_upper_dev_get);
 
+/**
+ * netdev_has_any_lower_dev - Check if device is linked to some device
+ * @dev: device
+ *
+ * Find out if a device is linked to a lower device and return true in case
+ * it is. The caller must hold the RTNL lock.
+ */
+static bool netdev_has_any_lower_dev(struct net_device *dev)
+{
+       ASSERT_RTNL();
+
+       return !list_empty(&dev->adj_list.lower);
+}
+
 void *netdev_adjacent_get_private(struct list_head *adj_list)
 {
        struct netdev_adjacent *adj;
@@ -5367,16 +5271,8 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
 }
 EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
 
-/**
- * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list
- * @dev: device
- * @iter: list_head ** of the current position
- *
- * Gets the next device from the dev's upper list, starting from iter
- * position. The caller must hold RCU read lock.
- */
-struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
-                                                    struct list_head **iter)
+static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
+                                                   struct list_head **iter)
 {
        struct netdev_adjacent *upper;
 
@@ -5384,14 +5280,41 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
 
        upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
 
-       if (&upper->list == &dev->all_adj_list.upper)
+       if (&upper->list == &dev->adj_list.upper)
                return NULL;
 
        *iter = &upper->list;
 
        return upper->dev;
 }
-EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu);
+
+int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
+                                 int (*fn)(struct net_device *dev,
+                                           void *data),
+                                 void *data)
+{
+       struct net_device *udev;
+       struct list_head *iter;
+       int ret;
+
+       for (iter = &dev->adj_list.upper,
+            udev = netdev_next_upper_dev_rcu(dev, &iter);
+            udev;
+            udev = netdev_next_upper_dev_rcu(dev, &iter)) {
+               /* first is the upper device itself */
+               ret = fn(udev, data);
+               if (ret)
+                       return ret;
+
+               /* then look at all of its upper devices */
+               ret = netdev_walk_all_upper_dev_rcu(udev, fn, data);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(netdev_walk_all_upper_dev_rcu);
 
 /**
  * netdev_lower_get_next_private - Get the next ->private from the
@@ -5474,55 +5397,90 @@ void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
 }
 EXPORT_SYMBOL(netdev_lower_get_next);
 
-/**
- * netdev_all_lower_get_next - Get the next device from all lower neighbour list
- * @dev: device
- * @iter: list_head ** of the current position
- *
- * Gets the next netdev_adjacent from the dev's all lower neighbour
- * list, starting from iter position. The caller must hold RTNL lock or
- * its own locking that guarantees that the neighbour all lower
- * list will remain unchanged.
- */
-struct net_device *netdev_all_lower_get_next(struct net_device *dev, struct list_head **iter)
+static struct net_device *netdev_next_lower_dev(struct net_device *dev,
+                                               struct list_head **iter)
 {
        struct netdev_adjacent *lower;
 
-       lower = list_entry(*iter, struct netdev_adjacent, list);
+       lower = list_entry((*iter)->next, struct netdev_adjacent, list);
 
-       if (&lower->list == &dev->all_adj_list.lower)
+       if (&lower->list == &dev->adj_list.lower)
                return NULL;
 
-       *iter = lower->list.next;
+       *iter = &lower->list;
 
        return lower->dev;
 }
-EXPORT_SYMBOL(netdev_all_lower_get_next);
 
-/**
- * netdev_all_lower_get_next_rcu - Get the next device from all
- *                                lower neighbour list, RCU variant
- * @dev: device
- * @iter: list_head ** of the current position
- *
- * Gets the next netdev_adjacent from the dev's all lower neighbour
- * list, starting from iter position. The caller must hold RCU read lock.
- */
-struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
-                                                struct list_head **iter)
+int netdev_walk_all_lower_dev(struct net_device *dev,
+                             int (*fn)(struct net_device *dev,
+                                       void *data),
+                             void *data)
+{
+       struct net_device *ldev;
+       struct list_head *iter;
+       int ret;
+
+       for (iter = &dev->adj_list.lower,
+            ldev = netdev_next_lower_dev(dev, &iter);
+            ldev;
+            ldev = netdev_next_lower_dev(dev, &iter)) {
+               /* first is the lower device itself */
+               ret = fn(ldev, data);
+               if (ret)
+                       return ret;
+
+               /* then look at all of its lower devices */
+               ret = netdev_walk_all_lower_dev(ldev, fn, data);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev);
+
+static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
+                                                   struct list_head **iter)
 {
        struct netdev_adjacent *lower;
 
        lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
-
-       if (&lower->list == &dev->all_adj_list.lower)
+       if (&lower->list == &dev->adj_list.lower)
                return NULL;
 
        *iter = &lower->list;
 
        return lower->dev;
 }
-EXPORT_SYMBOL(netdev_all_lower_get_next_rcu);
+
+int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
+                                 int (*fn)(struct net_device *dev,
+                                           void *data),
+                                 void *data)
+{
+       struct net_device *ldev;
+       struct list_head *iter;
+       int ret;
+
+       for (iter = &dev->adj_list.lower,
+            ldev = netdev_next_lower_dev_rcu(dev, &iter);
+            ldev;
+            ldev = netdev_next_lower_dev_rcu(dev, &iter)) {
+               /* first is the lower device itself */
+               ret = fn(ldev, data);
+               if (ret)
+                       return ret;
+
+               /* then look at all of its lower devices */
+               ret = netdev_walk_all_lower_dev_rcu(ldev, fn, data);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev_rcu);
 
 /**
  * netdev_lower_get_first_private_rcu - Get the first ->private from the
@@ -5595,7 +5553,6 @@ static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev,
 
 static int __netdev_adjacent_dev_insert(struct net_device *dev,
                                        struct net_device *adj_dev,
-                                       u16 ref_nr,
                                        struct list_head *dev_list,
                                        void *private, bool master)
 {
@@ -5605,7 +5562,10 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
        adj = __netdev_find_adj(adj_dev, dev_list);
 
        if (adj) {
-               adj->ref_nr += ref_nr;
+               adj->ref_nr += 1;
+               pr_debug("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d\n",
+                        dev->name, adj_dev->name, adj->ref_nr);
+
                return 0;
        }
 
@@ -5615,12 +5575,12 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
 
        adj->dev = adj_dev;
        adj->master = master;
-       adj->ref_nr = ref_nr;
+       adj->ref_nr = 1;
        adj->private = private;
        dev_hold(adj_dev);
 
-       pr_debug("dev_hold for %s, because of link added from %s to %s\n",
-                adj_dev->name, dev->name, adj_dev->name);
+       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);
 
        if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) {
                ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list);
@@ -5659,17 +5619,22 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
 {
        struct netdev_adjacent *adj;
 
+       pr_debug("Remove adjacency: dev %s adj_dev %s ref_nr %d\n",
+                dev->name, adj_dev->name, ref_nr);
+
        adj = __netdev_find_adj(adj_dev, dev_list);
 
        if (!adj) {
-               pr_err("tried to remove device %s from %s\n",
+               pr_err("Adjacency does not exist for device %s from %s\n",
                       dev->name, adj_dev->name);
-               BUG();
+               WARN_ON(1);
+               return;
        }
 
        if (adj->ref_nr > ref_nr) {
-               pr_debug("%s to %s ref_nr-%d = %d\n", dev->name, adj_dev->name,
-                        ref_nr, adj->ref_nr-ref_nr);
+               pr_debug("adjacency: %s to %s ref_nr - %d = %d\n",
+                        dev->name, adj_dev->name, ref_nr,
+                        adj->ref_nr - ref_nr);
                adj->ref_nr -= ref_nr;
                return;
        }
@@ -5681,7 +5646,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
                netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);
 
        list_del_rcu(&adj->list);
-       pr_debug("dev_put for %s, because link removed from %s to %s\n",
+       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(adj_dev);
        kfree_rcu(adj, rcu);
@@ -5689,38 +5654,27 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
 
 static int __netdev_adjacent_dev_link_lists(struct net_device *dev,
                                            struct net_device *upper_dev,
-                                           u16 ref_nr,
                                            struct list_head *up_list,
                                            struct list_head *down_list,
                                            void *private, bool master)
 {
        int ret;
 
-       ret = __netdev_adjacent_dev_insert(dev, upper_dev, ref_nr, up_list,
+       ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list,
                                           private, master);
        if (ret)
                return ret;
 
-       ret = __netdev_adjacent_dev_insert(upper_dev, dev, ref_nr, down_list,
+       ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list,
                                           private, false);
        if (ret) {
-               __netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list);
+               __netdev_adjacent_dev_remove(dev, upper_dev, 1, up_list);
                return ret;
        }
 
        return 0;
 }
 
-static int __netdev_adjacent_dev_link(struct net_device *dev,
-                                     struct net_device *upper_dev,
-                                     u16 ref_nr)
-{
-       return __netdev_adjacent_dev_link_lists(dev, upper_dev, ref_nr,
-                                               &dev->all_adj_list.upper,
-                                               &upper_dev->all_adj_list.lower,
-                                               NULL, false);
-}
-
 static void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
                                               struct net_device *upper_dev,
                                               u16 ref_nr,
@@ -5731,40 +5685,19 @@ static void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
        __netdev_adjacent_dev_remove(upper_dev, dev, ref_nr, down_list);
 }
 
-static void __netdev_adjacent_dev_unlink(struct net_device *dev,
-                                        struct net_device *upper_dev,
-                                        u16 ref_nr)
-{
-       __netdev_adjacent_dev_unlink_lists(dev, upper_dev, ref_nr,
-                                          &dev->all_adj_list.upper,
-                                          &upper_dev->all_adj_list.lower);
-}
-
 static int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
                                                struct net_device *upper_dev,
                                                void *private, bool master)
 {
-       int ret = __netdev_adjacent_dev_link(dev, upper_dev, 1);
-
-       if (ret)
-               return ret;
-
-       ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, 1,
-                                              &dev->adj_list.upper,
-                                              &upper_dev->adj_list.lower,
-                                              private, master);
-       if (ret) {
-               __netdev_adjacent_dev_unlink(dev, upper_dev, 1);
-               return ret;
-       }
-
-       return 0;
+       return __netdev_adjacent_dev_link_lists(dev, upper_dev,
+                                               &dev->adj_list.upper,
+                                               &upper_dev->adj_list.lower,
+                                               private, master);
 }
 
 static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
                                                   struct net_device *upper_dev)
 {
-       __netdev_adjacent_dev_unlink(dev, upper_dev, 1);
        __netdev_adjacent_dev_unlink_lists(dev, upper_dev, 1,
                                           &dev->adj_list.upper,
                                           &upper_dev->adj_list.lower);
@@ -5775,7 +5708,6 @@ static int __netdev_upper_dev_link(struct net_device *dev,
                                   void *upper_priv, void *upper_info)
 {
        struct netdev_notifier_changeupper_info changeupper_info;
-       struct netdev_adjacent *i, *j, *to_i, *to_j;
        int ret = 0;
 
        ASSERT_RTNL();
@@ -5784,10 +5716,10 @@ static int __netdev_upper_dev_link(struct net_device *dev,
                return -EBUSY;
 
        /* To prevent loops, check if dev is not upper device to upper_dev. */
-       if (__netdev_find_adj(dev, &upper_dev->all_adj_list.upper))
+       if (netdev_has_upper_dev(upper_dev, dev))
                return -EBUSY;
 
-       if (__netdev_find_adj(upper_dev, &dev->adj_list.upper))
+       if (netdev_has_upper_dev(dev, upper_dev))
                return -EEXIST;
 
        if (master && netdev_master_upper_dev_get(dev))
@@ -5809,80 +5741,15 @@ static int __netdev_upper_dev_link(struct net_device *dev,
        if (ret)
                return ret;
 
-       /* Now that we linked these devs, make all the upper_dev's
-        * all_adj_list.upper visible to every dev's all_adj_list.lower an
-        * versa, and don't forget the devices itself. All of these
-        * links are non-neighbours.
-        */
-       list_for_each_entry(i, &dev->all_adj_list.lower, list) {
-               list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
-                       pr_debug("Interlinking %s with %s, non-neighbour\n",
-                                i->dev->name, j->dev->name);
-                       ret = __netdev_adjacent_dev_link(i->dev, j->dev, i->ref_nr);
-                       if (ret)
-                               goto rollback_mesh;
-               }
-       }
-
-       /* add dev to every upper_dev's upper device */
-       list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
-               pr_debug("linking %s's upper device %s with %s\n",
-                        upper_dev->name, i->dev->name, dev->name);
-               ret = __netdev_adjacent_dev_link(dev, i->dev, i->ref_nr);
-               if (ret)
-                       goto rollback_upper_mesh;
-       }
-
-       /* add upper_dev to every dev's lower device */
-       list_for_each_entry(i, &dev->all_adj_list.lower, list) {
-               pr_debug("linking %s's lower device %s with %s\n", dev->name,
-                        i->dev->name, upper_dev->name);
-               ret = __netdev_adjacent_dev_link(i->dev, upper_dev, i->ref_nr);
-               if (ret)
-                       goto rollback_lower_mesh;
-       }
-
        ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
                                            &changeupper_info.info);
        ret = notifier_to_errno(ret);
        if (ret)
-               goto rollback_lower_mesh;
+               goto rollback;
 
        return 0;
 
-rollback_lower_mesh:
-       to_i = i;
-       list_for_each_entry(i, &dev->all_adj_list.lower, list) {
-               if (i == to_i)
-                       break;
-               __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr);
-       }
-
-       i = NULL;
-
-rollback_upper_mesh:
-       to_i = i;
-       list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
-               if (i == to_i)
-                       break;
-               __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr);
-       }
-
-       i = j = NULL;
-
-rollback_mesh:
-       to_i = i;
-       to_j = j;
-       list_for_each_entry(i, &dev->all_adj_list.lower, list) {
-               list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
-                       if (i == to_i && j == to_j)
-                               break;
-                       __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr);
-               }
-               if (i == to_i)
-                       break;
-       }
-
+rollback:
        __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
 
        return ret;
@@ -5939,7 +5806,6 @@ void netdev_upper_dev_unlink(struct net_device *dev,
                             struct net_device *upper_dev)
 {
        struct netdev_notifier_changeupper_info changeupper_info;
-       struct netdev_adjacent *i, *j;
        ASSERT_RTNL();
 
        changeupper_info.upper_dev = upper_dev;
@@ -5951,23 +5817,6 @@ void netdev_upper_dev_unlink(struct net_device *dev,
 
        __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
 
-       /* Here is the tricky part. We must remove all dev's lower
-        * devices from all upper_dev's upper devices and vice
-        * versa, to maintain the graph relationship.
-        */
-       list_for_each_entry(i, &dev->all_adj_list.lower, list)
-               list_for_each_entry(j, &upper_dev->all_adj_list.upper, list)
-                       __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr);
-
-       /* remove also the devices itself from lower/upper device
-        * list
-        */
-       list_for_each_entry(i, &dev->all_adj_list.lower, list)
-               __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr);
-
-       list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
-               __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr);
-
        call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
                                      &changeupper_info.info);
 }
@@ -6505,9 +6354,18 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
        if (new_mtu == dev->mtu)
                return 0;
 
-       /*      MTU must be positive.    */
-       if (new_mtu < 0)
+       /* MTU must be positive, and in range */
+       if (new_mtu < 0 || new_mtu < dev->min_mtu) {
+               net_err_ratelimited("%s: Invalid MTU %d requested, hw min %d\n",
+                                   dev->name, new_mtu, dev->min_mtu);
                return -EINVAL;
+       }
+
+       if (dev->max_mtu > 0 && new_mtu > dev->max_mtu) {
+               net_err_ratelimited("%s: Invalid MTU %d requested, hw max %d\n",
+                                   dev->name, new_mtu, dev->max_mtu);
+               return -EINVAL;
+       }
 
        if (!netif_device_present(dev))
                return -ENODEV;
@@ -6782,6 +6640,7 @@ static void rollback_registered_many(struct list_head *head)
 
                /* Notifier chain MUST detach us all upper devices. */
                WARN_ON(netdev_has_any_upper_dev(dev));
+               WARN_ON(netdev_has_any_lower_dev(dev));
 
                /* Remove entries from kobject tree */
                netdev_unregister_kobject(dev);
@@ -7660,8 +7519,6 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
        INIT_LIST_HEAD(&dev->link_watch_list);
        INIT_LIST_HEAD(&dev->adj_list.upper);
        INIT_LIST_HEAD(&dev->adj_list.lower);
-       INIT_LIST_HEAD(&dev->all_adj_list.upper);
-       INIT_LIST_HEAD(&dev->all_adj_list.lower);
        INIT_LIST_HEAD(&dev->ptype_all);
        INIT_LIST_HEAD(&dev->ptype_specific);
 #ifdef CONFIG_NET_SCHED
index 1b5063088f1a7193f7789506e95cc6dbc8ab73f0..c14f8b661db99f1bb2b0d6a475dbddca18703b85 100644 (file)
@@ -341,15 +341,7 @@ static void devlink_nl_post_doit(const struct genl_ops *ops,
        mutex_unlock(&devlink_mutex);
 }
 
-static struct genl_family devlink_nl_family = {
-       .id             = GENL_ID_GENERATE,
-       .name           = DEVLINK_GENL_NAME,
-       .version        = DEVLINK_GENL_VERSION,
-       .maxattr        = DEVLINK_ATTR_MAX,
-       .netnsok        = true,
-       .pre_doit       = devlink_nl_pre_doit,
-       .post_doit      = devlink_nl_post_doit,
-};
+static struct genl_family devlink_nl_family;
 
 enum devlink_multicast_groups {
        DEVLINK_MCGRP_CONFIG,
@@ -608,6 +600,8 @@ static int devlink_port_type_set(struct devlink *devlink,
        if (devlink->ops && devlink->ops->port_type_set) {
                if (port_type == DEVLINK_PORT_TYPE_NOTSET)
                        return -EINVAL;
+               if (port_type == devlink_port->type)
+                       return 0;
                err = devlink->ops->port_type_set(devlink_port, port_type);
                if (err)
                        return err;
@@ -1618,6 +1612,20 @@ static const struct genl_ops devlink_nl_ops[] = {
        },
 };
 
+static struct genl_family devlink_nl_family __ro_after_init = {
+       .name           = DEVLINK_GENL_NAME,
+       .version        = DEVLINK_GENL_VERSION,
+       .maxattr        = DEVLINK_ATTR_MAX,
+       .netnsok        = true,
+       .pre_doit       = devlink_nl_pre_doit,
+       .post_doit      = devlink_nl_post_doit,
+       .module         = THIS_MODULE,
+       .ops            = devlink_nl_ops,
+       .n_ops          = ARRAY_SIZE(devlink_nl_ops),
+       .mcgrps         = devlink_nl_mcgrps,
+       .n_mcgrps       = ARRAY_SIZE(devlink_nl_mcgrps),
+};
+
 /**
  *     devlink_alloc - Allocate new devlink instance resources
  *
@@ -1840,9 +1848,7 @@ EXPORT_SYMBOL_GPL(devlink_sb_unregister);
 
 static int __init devlink_module_init(void)
 {
-       return genl_register_family_with_ops_groups(&devlink_nl_family,
-                                                   devlink_nl_ops,
-                                                   devlink_nl_mcgrps);
+       return genl_register_family(&devlink_nl_family);
 }
 
 static void __exit devlink_module_exit(void)
index 72cfb0c611254cbe48885e4d3a7b497e91d94fed..8e0c0635ee975e1c71a126677f63ff220f7f0c44 100644 (file)
@@ -59,12 +59,7 @@ struct dm_hw_stat_delta {
        unsigned long last_drop_val;
 };
 
-static struct genl_family net_drop_monitor_family = {
-       .id             = GENL_ID_GENERATE,
-       .hdrsize        = 0,
-       .name           = "NET_DM",
-       .version        = 2,
-};
+static struct genl_family net_drop_monitor_family;
 
 static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data);
 
@@ -351,6 +346,17 @@ static const struct genl_ops dropmon_ops[] = {
        },
 };
 
+static struct genl_family net_drop_monitor_family __ro_after_init = {
+       .hdrsize        = 0,
+       .name           = "NET_DM",
+       .version        = 2,
+       .module         = THIS_MODULE,
+       .ops            = dropmon_ops,
+       .n_ops          = ARRAY_SIZE(dropmon_ops),
+       .mcgrps         = dropmon_mcgrps,
+       .n_mcgrps       = ARRAY_SIZE(dropmon_mcgrps),
+};
+
 static struct notifier_block dropmon_net_notifier = {
        .notifier_call = dropmon_net_event
 };
@@ -367,8 +373,7 @@ static int __init init_net_drop_monitor(void)
                return -ENOSPC;
        }
 
-       rc = genl_register_family_with_ops_groups(&net_drop_monitor_family,
-                                                 dropmon_ops, dropmon_mcgrps);
+       rc = genl_register_family(&net_drop_monitor_family);
        if (rc) {
                pr_err("Could not create drop monitor netlink family\n");
                return rc;
index 00351cdf7d0c3f5fe1657e02b96b7a90891e0385..cd9e2ba66b0e0bc32ba8b3f6fba701aa307ce669 100644 (file)
@@ -2492,6 +2492,8 @@ sk_filter_func_proto(enum bpf_func_id func_id)
                return &bpf_get_prandom_u32_proto;
        case BPF_FUNC_get_smp_processor_id:
                return &bpf_get_raw_smp_processor_id_proto;
+       case BPF_FUNC_get_numa_node_id:
+               return &bpf_get_numa_node_id_proto;
        case BPF_FUNC_tail_call:
                return &bpf_tail_call_proto;
        case BPF_FUNC_ktime_get_ns:
index ab193e5def07ef6e3854a039e123eefed12d906e..87e01815ec8526e81a318338cc20e418539300ec 100644 (file)
@@ -721,7 +721,7 @@ EXPORT_SYMBOL(make_flow_keys_digest);
 
 static struct flow_dissector flow_keys_dissector_symmetric __read_mostly;
 
-u32 __skb_get_hash_symmetric(struct sk_buff *skb)
+u32 __skb_get_hash_symmetric(const struct sk_buff *skb)
 {
        struct flow_keys keys;
 
index e5f84c26ba1a6fd89d5651d0408c8d6ef123db7b..88fd64250b021ea342e8fa39cff4e21a53ece182 100644 (file)
@@ -130,6 +130,19 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
 }
 EXPORT_SYMBOL(lwtunnel_build_state);
 
+void lwtstate_free(struct lwtunnel_state *lws)
+{
+       const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type];
+
+       if (ops->destroy_state) {
+               ops->destroy_state(lws);
+               kfree_rcu(lws, rcu);
+       } else {
+               kfree(lws);
+       }
+}
+EXPORT_SYMBOL(lwtstate_free);
+
 int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate)
 {
        const struct lwtunnel_encap_ops *ops;
index 6e4f3472108015f0fbd7ac6f3dfe7e74a019e8be..d4fe28606ff5334e7efdbd347ab86420d52a4d7d 100644 (file)
@@ -950,10 +950,13 @@ net_rx_queue_update_kobjects(struct net_device *dev, int old_num, int new_num)
        }
 
        while (--i >= new_num) {
+               struct kobject *kobj = &dev->_rx[i].kobj;
+
+               if (!list_empty(&dev_net(dev)->exit_list))
+                       kobj->uevent_suppress = 1;
                if (dev->sysfs_rx_queue_group)
-                       sysfs_remove_group(&dev->_rx[i].kobj,
-                                          dev->sysfs_rx_queue_group);
-               kobject_put(&dev->_rx[i].kobj);
+                       sysfs_remove_group(kobj, dev->sysfs_rx_queue_group);
+               kobject_put(kobj);
        }
 
        return error;
@@ -1340,6 +1343,8 @@ netdev_queue_update_kobjects(struct net_device *dev, int old_num, int new_num)
        while (--i >= new_num) {
                struct netdev_queue *queue = dev->_tx + i;
 
+               if (!list_empty(&dev_net(dev)->exit_list))
+                       queue->kobj.uevent_suppress = 1;
 #ifdef CONFIG_BQL
                sysfs_remove_group(&queue->kobj, &dql_group);
 #endif
@@ -1525,6 +1530,9 @@ void netdev_unregister_kobject(struct net_device *ndev)
 {
        struct device *dev = &(ndev->dev);
 
+       if (!list_empty(&dev_net(ndev)->exit_list))
+               dev_set_uevent_suppress(dev, 1);
+
        kobject_get(&dev->kobj);
 
        remove_queue_kobjects(ndev);
index f61c0e02a4130318060e35180d3cab391daf64af..1309d78e2a64fab1d9d01226743a26bcab6d613d 100644 (file)
@@ -382,7 +382,14 @@ struct net *copy_net_ns(unsigned long flags,
 
        get_user_ns(user_ns);
 
-       mutex_lock(&net_mutex);
+       rv = mutex_lock_killable(&net_mutex);
+       if (rv < 0) {
+               net_free(net);
+               dec_net_namespaces(ucounts);
+               put_user_ns(user_ns);
+               return ERR_PTR(rv);
+       }
+
        net->ucounts = ucounts;
        rv = setup_net(net, user_ns);
        if (rv == 0) {
index c73e28fc9c2a45225af39f7905072456d4380c7f..d8e4532e89e7c28737c95c723e5f5b3d184a7805 100644 (file)
@@ -2091,24 +2091,18 @@ int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb)
 EXPORT_SYMBOL(sk_wait_data);
 
 /**
- *     __sk_mem_schedule - increase sk_forward_alloc and memory_allocated
+ *     __sk_mem_raise_allocated - increase memory_allocated
  *     @sk: socket
  *     @size: memory size to allocate
+ *     @amt: pages to allocate
  *     @kind: allocation type
  *
- *     If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
- *     rmem allocation. This function assumes that protocols which have
- *     memory_pressure use sk_wmem_queued as write buffer accounting.
+ *     Similar to __sk_mem_schedule(), but does not update sk_forward_alloc
  */
-int __sk_mem_schedule(struct sock *sk, int size, int kind)
+int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
 {
        struct proto *prot = sk->sk_prot;
-       int amt = sk_mem_pages(size);
-       long allocated;
-
-       sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
-
-       allocated = sk_memory_allocated_add(sk, amt);
+       long allocated = sk_memory_allocated_add(sk, amt);
 
        if (mem_cgroup_sockets_enabled && sk->sk_memcg &&
            !mem_cgroup_charge_skmem(sk->sk_memcg, amt))
@@ -2169,9 +2163,6 @@ suppress_allocation:
 
        trace_sock_exceed_buf_limit(sk, prot, allocated);
 
-       /* Alas. Undo changes. */
-       sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
-
        sk_memory_allocated_sub(sk, amt);
 
        if (mem_cgroup_sockets_enabled && sk->sk_memcg)
@@ -2179,18 +2170,40 @@ suppress_allocation:
 
        return 0;
 }
+EXPORT_SYMBOL(__sk_mem_raise_allocated);
+
+/**
+ *     __sk_mem_schedule - increase sk_forward_alloc and memory_allocated
+ *     @sk: socket
+ *     @size: memory size to allocate
+ *     @kind: allocation type
+ *
+ *     If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
+ *     rmem allocation. This function assumes that protocols which have
+ *     memory_pressure use sk_wmem_queued as write buffer accounting.
+ */
+int __sk_mem_schedule(struct sock *sk, int size, int kind)
+{
+       int ret, amt = sk_mem_pages(size);
+
+       sk->sk_forward_alloc += amt << SK_MEM_QUANTUM_SHIFT;
+       ret = __sk_mem_raise_allocated(sk, size, amt, kind);
+       if (!ret)
+               sk->sk_forward_alloc -= amt << SK_MEM_QUANTUM_SHIFT;
+       return ret;
+}
 EXPORT_SYMBOL(__sk_mem_schedule);
 
 /**
- *     __sk_mem_reclaim - reclaim memory_allocated
+ *     __sk_mem_reduce_allocated - reclaim memory_allocated
  *     @sk: socket
- *     @amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple)
+ *     @amount: number of quanta
+ *
+ *     Similar to __sk_mem_reclaim(), but does not update sk_forward_alloc
  */
-void __sk_mem_reclaim(struct sock *sk, int amount)
+void __sk_mem_reduce_allocated(struct sock *sk, int amount)
 {
-       amount >>= SK_MEM_QUANTUM_SHIFT;
        sk_memory_allocated_sub(sk, amount);
-       sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
 
        if (mem_cgroup_sockets_enabled && sk->sk_memcg)
                mem_cgroup_uncharge_skmem(sk->sk_memcg, amount);
@@ -2199,6 +2212,19 @@ void __sk_mem_reclaim(struct sock *sk, int amount)
            (sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)))
                sk_leave_memory_pressure(sk);
 }
+EXPORT_SYMBOL(__sk_mem_reduce_allocated);
+
+/**
+ *     __sk_mem_reclaim - reclaim sk_forward_alloc and memory_allocated
+ *     @sk: socket
+ *     @amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple)
+ */
+void __sk_mem_reclaim(struct sock *sk, int amount)
+{
+       amount >>= SK_MEM_QUANTUM_SHIFT;
+       sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
+       __sk_mem_reduce_allocated(sk, amount);
+}
 EXPORT_SYMBOL(__sk_mem_reclaim);
 
 int sk_set_peek_off(struct sock *sk, int val)
index 345a3aeb8c7e36449a765298cd6512eab8cfef4b..a957acac2337680f619fef09f19660a3b4c309d3 100644 (file)
@@ -588,13 +588,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        if (inet_csk_reqsk_queue_is_full(sk))
                goto drop;
 
-       /*
-        * Accept backlog is full. If we have already queued enough
-        * of warm entries in syn queue, drop request. It is better than
-        * clogging syn queue with openreqs with exponentially increasing
-        * timeout.
-        */
-       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+       if (sk_acceptq_is_full(sk))
                goto drop;
 
        req = inet_reqsk_alloc(&dccp_request_sock_ops, sk, true);
index 3828f94b234c1104a3e745b3c0a76ab343aed4b6..32f9f1a189f8b8082bfdebd97baa04045562a3c6 100644 (file)
@@ -325,7 +325,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        if (inet_csk_reqsk_queue_is_full(sk))
                goto drop;
 
-       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+       if (sk_acceptq_is_full(sk))
                goto drop;
 
        req = inet_reqsk_alloc(&dccp6_request_sock_ops, sk, true);
index 6b1282c006b145d2b96921243b9e26e91c427f88..d0c7bce88743b93f1b01b6fc98ea9c816f5d533d 100644 (file)
@@ -641,7 +641,8 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
 
 /* ethtool operations *******************************************************/
 static int
-dsa_slave_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+dsa_slave_get_link_ksettings(struct net_device *dev,
+                            struct ethtool_link_ksettings *cmd)
 {
        struct dsa_slave_priv *p = netdev_priv(dev);
        int err;
@@ -650,19 +651,20 @@ dsa_slave_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        if (p->phy != NULL) {
                err = phy_read_status(p->phy);
                if (err == 0)
-                       err = phy_ethtool_gset(p->phy, cmd);
+                       err = phy_ethtool_ksettings_get(p->phy, cmd);
        }
 
        return err;
 }
 
 static int
-dsa_slave_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+dsa_slave_set_link_ksettings(struct net_device *dev,
+                            const struct ethtool_link_ksettings *cmd)
 {
        struct dsa_slave_priv *p = netdev_priv(dev);
 
        if (p->phy != NULL)
-               return phy_ethtool_sset(p->phy, cmd);
+               return phy_ethtool_ksettings_set(p->phy, cmd);
 
        return -EOPNOTSUPP;
 }
@@ -990,8 +992,6 @@ void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
 }
 
 static const struct ethtool_ops dsa_slave_ethtool_ops = {
-       .get_settings           = dsa_slave_get_settings,
-       .set_settings           = dsa_slave_set_settings,
        .get_drvinfo            = dsa_slave_get_drvinfo,
        .get_regs_len           = dsa_slave_get_regs_len,
        .get_regs               = dsa_slave_get_regs,
@@ -1007,6 +1007,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
        .get_wol                = dsa_slave_get_wol,
        .set_eee                = dsa_slave_set_eee,
        .get_eee                = dsa_slave_get_eee,
+       .get_link_ksettings     = dsa_slave_get_link_ksettings,
+       .set_link_ksettings     = dsa_slave_set_link_ksettings,
 };
 
 static const struct net_device_ops dsa_slave_netdev_ops = {
@@ -1245,6 +1247,8 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
        slave_dev->priv_flags |= IFF_NO_QUEUE;
        slave_dev->netdev_ops = &dsa_slave_netdev_ops;
        slave_dev->switchdev_ops = &dsa_slave_switchdev_ops;
+       slave_dev->min_mtu = 0;
+       slave_dev->max_mtu = ETH_MAX_MTU;
        SET_NETDEV_DEVTYPE(slave_dev, &dsa_type);
 
        netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one,
index 02acfff36028bfc3260d7568881bb412be312d27..d9e2fe1da72444cf186d41dfee34551c0856b032 100644 (file)
@@ -322,8 +322,7 @@ EXPORT_SYMBOL(eth_mac_addr);
  */
 int eth_change_mtu(struct net_device *dev, int new_mtu)
 {
-       if (new_mtu < 68 || new_mtu > ETH_DATA_LEN)
-               return -EINVAL;
+       netdev_warn(dev, "%s is deprecated\n", __func__);
        dev->mtu = new_mtu;
        return 0;
 }
@@ -357,6 +356,8 @@ void ether_setup(struct net_device *dev)
        dev->type               = ARPHRD_ETHER;
        dev->hard_header_len    = ETH_HLEN;
        dev->mtu                = ETH_DATA_LEN;
+       dev->min_mtu            = ETH_MIN_MTU;
+       dev->max_mtu            = ETH_DATA_LEN;
        dev->addr_len           = ETH_ALEN;
        dev->tx_queue_len       = 1000; /* Ethernet wants good queues */
        dev->flags              = IFF_BROADCAST|IFF_MULTICAST;
index 16737cd8dae8ecb753b9c858fd18ee66a272b76d..fc65b145f6e71b87115aeb14dee408cef876d10b 100644 (file)
@@ -398,6 +398,7 @@ void hsr_dev_setup(struct net_device *dev)
        random_ether_addr(dev->dev_addr);
 
        ether_setup(dev);
+       dev->min_mtu = 0;
        dev->header_ops = &hsr_header_ops;
        dev->netdev_ops = &hsr_device_ops;
        SET_NETDEV_DEVTYPE(dev, &hsr_type);
index d4d1617f43a8bfb842a8017dc51655ae1065942b..1ab30e7d3f99e19c5e54fd9747cfce7a5c1f559b 100644 (file)
@@ -131,13 +131,7 @@ static const struct nla_policy hsr_genl_policy[HSR_A_MAX + 1] = {
        [HSR_A_IF2_SEQ] = { .type = NLA_U16 },
 };
 
-static struct genl_family hsr_genl_family = {
-       .id = GENL_ID_GENERATE,
-       .hdrsize = 0,
-       .name = "HSR",
-       .version = 1,
-       .maxattr = HSR_A_MAX,
-};
+static struct genl_family hsr_genl_family;
 
 static const struct genl_multicast_group hsr_mcgrps[] = {
        { .name = "hsr-network", },
@@ -467,6 +461,18 @@ static const struct genl_ops hsr_ops[] = {
        },
 };
 
+static struct genl_family hsr_genl_family __ro_after_init = {
+       .hdrsize = 0,
+       .name = "HSR",
+       .version = 1,
+       .maxattr = HSR_A_MAX,
+       .module = THIS_MODULE,
+       .ops = hsr_ops,
+       .n_ops = ARRAY_SIZE(hsr_ops),
+       .mcgrps = hsr_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(hsr_mcgrps),
+};
+
 int __init hsr_netlink_init(void)
 {
        int rc;
@@ -475,8 +481,7 @@ int __init hsr_netlink_init(void)
        if (rc)
                goto fail_rtnl_link_register;
 
-       rc = genl_register_family_with_ops_groups(&hsr_genl_family, hsr_ops,
-                                                 hsr_mcgrps);
+       rc = genl_register_family(&hsr_genl_family);
        if (rc)
                goto fail_genl_register_family;
 
index c8133c07ceee4ce29411a5f9ea47c0c529231223..6bde9e5a55031c9a184c418588a78790405b1b83 100644 (file)
 static unsigned int ieee802154_seq_num;
 static DEFINE_SPINLOCK(ieee802154_seq_lock);
 
-struct genl_family nl802154_family = {
-       .id             = GENL_ID_GENERATE,
-       .hdrsize        = 0,
-       .name           = IEEE802154_NL_NAME,
-       .version        = 1,
-       .maxattr        = IEEE802154_ATTR_MAX,
-};
-
 /* Requests to userspace */
 struct sk_buff *ieee802154_nl_create(int flags, u8 req)
 {
@@ -139,11 +131,21 @@ static const struct genl_multicast_group ieee802154_mcgrps[] = {
        [IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, },
 };
 
+struct genl_family nl802154_family __ro_after_init = {
+       .hdrsize        = 0,
+       .name           = IEEE802154_NL_NAME,
+       .version        = 1,
+       .maxattr        = IEEE802154_ATTR_MAX,
+       .module         = THIS_MODULE,
+       .ops            = ieee8021154_ops,
+       .n_ops          = ARRAY_SIZE(ieee8021154_ops),
+       .mcgrps         = ieee802154_mcgrps,
+       .n_mcgrps       = ARRAY_SIZE(ieee802154_mcgrps),
+};
+
 int __init ieee802154_nl_init(void)
 {
-       return genl_register_family_with_ops_groups(&nl802154_family,
-                                                   ieee8021154_ops,
-                                                   ieee802154_mcgrps);
+       return genl_register_family(&nl802154_family);
 }
 
 void ieee802154_nl_exit(void)
index d90a4ed5b8a037e1dacef4cac0c44b158efabbb8..fc60cd061f3966a2381803a8e4d85206770253dc 100644 (file)
 #include "rdev-ops.h"
 #include "core.h"
 
-static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
-                            struct genl_info *info);
-
-static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
-                              struct genl_info *info);
-
 /* the netlink family */
-static struct genl_family nl802154_fam = {
-       .id = GENL_ID_GENERATE,         /* don't bother with a hardcoded ID */
-       .name = NL802154_GENL_NAME,     /* have users key off the name instead */
-       .hdrsize = 0,                   /* no private header */
-       .version = 1,                   /* no particular meaning now */
-       .maxattr = NL802154_ATTR_MAX,
-       .netnsok = true,
-       .pre_doit = nl802154_pre_doit,
-       .post_doit = nl802154_post_doit,
-};
+static struct genl_family nl802154_fam;
 
 /* multicast groups */
 enum nl802154_multicast_groups {
@@ -263,13 +248,14 @@ nl802154_prepare_wpan_dev_dump(struct sk_buff *skb,
 
        if (!cb->args[0]) {
                err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
-                                 nl802154_fam.attrbuf, nl802154_fam.maxattr,
+                                 genl_family_attrbuf(&nl802154_fam),
+                                 nl802154_fam.maxattr,
                                  nl802154_policy);
                if (err)
                        goto out_unlock;
 
                *wpan_dev = __cfg802154_wpan_dev_from_attrs(sock_net(skb->sk),
-                                                           nl802154_fam.attrbuf);
+                                                           genl_family_attrbuf(&nl802154_fam));
                if (IS_ERR(*wpan_dev)) {
                        err = PTR_ERR(*wpan_dev);
                        goto out_unlock;
@@ -575,7 +561,7 @@ static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
                                        struct netlink_callback *cb,
                                        struct nl802154_dump_wpan_phy_state *state)
 {
-       struct nlattr **tb = nl802154_fam.attrbuf;
+       struct nlattr **tb = genl_family_attrbuf(&nl802154_fam);
        int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
                              tb, nl802154_fam.maxattr, nl802154_policy);
 
@@ -2476,11 +2462,25 @@ static const struct genl_ops nl802154_ops[] = {
 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
 };
 
+static struct genl_family nl802154_fam __ro_after_init = {
+       .name = NL802154_GENL_NAME,     /* have users key off the name instead */
+       .hdrsize = 0,                   /* no private header */
+       .version = 1,                   /* no particular meaning now */
+       .maxattr = NL802154_ATTR_MAX,
+       .netnsok = true,
+       .pre_doit = nl802154_pre_doit,
+       .post_doit = nl802154_post_doit,
+       .module = THIS_MODULE,
+       .ops = nl802154_ops,
+       .n_ops = ARRAY_SIZE(nl802154_ops),
+       .mcgrps = nl802154_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(nl802154_mcgrps),
+};
+
 /* initialisation/exit functions */
-int nl802154_init(void)
+int __init nl802154_init(void)
 {
-       return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops,
-                                                   nl802154_mcgrps);
+       return genl_register_family(&nl802154_fam);
 }
 
 void nl802154_exit(void)
index 300b06888fdfd0139eddf202b1d4ef9ee90c1f76..28e051a8e847c7d111fd0c2a2b1a69597b3c03ca 100644 (file)
@@ -430,6 +430,14 @@ config INET_UDP_DIAG
          Support for UDP socket monitoring interface used by the ss tool.
          If unsure, say Y.
 
+config INET_RAW_DIAG
+       tristate "RAW: socket monitoring interface"
+       depends on INET_DIAG && (IPV6 || IPV6=n)
+       default n
+       ---help---
+         Support for RAW socket monitoring interface used by the ss tool.
+         If unsure, say Y.
+
 config INET_DIAG_DESTROY
        bool "INET: allow privileged process to administratively close sockets"
        depends on INET_DIAG
index bc6a6c8b9bcd79a737fdea3ec872b4a2e1dc58b0..48af58a5686e3e9d81120217e5949d06f5ee6ce9 100644 (file)
@@ -40,6 +40,7 @@ obj-$(CONFIG_NETFILTER)       += netfilter.o netfilter/
 obj-$(CONFIG_INET_DIAG) += inet_diag.o 
 obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
 obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o
+obj-$(CONFIG_INET_RAW_DIAG) += raw_diag.o
 obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
 obj-$(CONFIG_TCP_CONG_BBR) += tcp_bbr.o
 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
index 030d1531e897a14c44d6dbf04dc21df2c87da399..805f6607f8d9a89661bed62db6b370b964d43f1d 100644 (file)
@@ -622,14 +622,7 @@ static int fou_destroy(struct net *net, struct fou_cfg *cfg)
        return err;
 }
 
-static struct genl_family fou_nl_family = {
-       .id             = GENL_ID_GENERATE,
-       .hdrsize        = 0,
-       .name           = FOU_GENL_NAME,
-       .version        = FOU_GENL_VERSION,
-       .maxattr        = FOU_ATTR_MAX,
-       .netnsok        = true,
-};
+static struct genl_family fou_nl_family;
 
 static const struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = {
        [FOU_ATTR_PORT] = { .type = NLA_U16, },
@@ -831,6 +824,17 @@ static const struct genl_ops fou_nl_ops[] = {
        },
 };
 
+static struct genl_family fou_nl_family __ro_after_init = {
+       .hdrsize        = 0,
+       .name           = FOU_GENL_NAME,
+       .version        = FOU_GENL_VERSION,
+       .maxattr        = FOU_ATTR_MAX,
+       .netnsok        = true,
+       .module         = THIS_MODULE,
+       .ops            = fou_nl_ops,
+       .n_ops          = ARRAY_SIZE(fou_nl_ops),
+};
+
 size_t fou_encap_hlen(struct ip_tunnel_encap *e)
 {
        return sizeof(struct udphdr);
@@ -1086,8 +1090,7 @@ static int __init fou_init(void)
        if (ret)
                goto exit;
 
-       ret = genl_register_family_with_ops(&fou_nl_family,
-                                           fou_nl_ops);
+       ret = genl_register_family(&fou_nl_family);
        if (ret < 0)
                goto unregister;
 
index e4d16fc5bbb3fec077f8e3bb3ff8811a66046edc..3b34024202d8144d823abe1bce5cb2d34b24e9de 100644 (file)
@@ -200,6 +200,15 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                if (sock_diag_put_meminfo(sk, skb, INET_DIAG_SKMEMINFO))
                        goto errout;
 
+       /*
+        * RAW sockets might have user-defined protocols assigned,
+        * so report the one supplied on socket creation.
+        */
+       if (sk->sk_type == SOCK_RAW) {
+               if (nla_put_u8(skb, INET_DIAG_PROTOCOL, sk->sk_protocol))
+                       goto errout;
+       }
+
        if (!icsk) {
                handler->idiag_get_info(sk, r, NULL);
                goto out;
@@ -863,7 +872,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
        s_num = num = cb->args[2];
 
        if (cb->args[0] == 0) {
-               if (!(idiag_states & TCPF_LISTEN))
+               if (!(idiag_states & TCPF_LISTEN) || r->id.idiag_dport)
                        goto skip_listen_ht;
 
                for (i = s_i; i < INET_LHTABLE_SIZE; i++) {
@@ -872,7 +881,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 
                        num = 0;
                        ilb = &hashinfo->listening_hash[i];
-                       spin_lock_bh(&ilb->lock);
+                       spin_lock(&ilb->lock);
                        sk_for_each(sk, &ilb->head) {
                                struct inet_sock *inet = inet_sk(sk);
 
@@ -892,26 +901,18 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
                                    r->id.idiag_sport)
                                        goto next_listen;
 
-                               if (r->id.idiag_dport ||
-                                   cb->args[3] > 0)
-                                       goto next_listen;
-
                                if (inet_csk_diag_dump(sk, skb, cb, r,
                                                       bc, net_admin) < 0) {
-                                       spin_unlock_bh(&ilb->lock);
+                                       spin_unlock(&ilb->lock);
                                        goto done;
                                }
 
 next_listen:
-                               cb->args[3] = 0;
-                               cb->args[4] = 0;
                                ++num;
                        }
-                       spin_unlock_bh(&ilb->lock);
+                       spin_unlock(&ilb->lock);
 
                        s_num = 0;
-                       cb->args[3] = 0;
-                       cb->args[4] = 0;
                }
 skip_listen_ht:
                cb->args[0] = 1;
index 5719d6ba0824b377aef689f4e0e1c425fc8df910..12a92e3349ed5ab322496b553abf944acd9f1d4c 100644 (file)
@@ -358,6 +358,7 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net,
 {
        struct ip_tunnel *nt;
        struct net_device *dev;
+       int t_hlen;
 
        BUG_ON(!itn->fb_tunnel_dev);
        dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms);
@@ -367,6 +368,9 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net,
        dev->mtu = ip_tunnel_bind_dev(dev);
 
        nt = netdev_priv(dev);
+       t_hlen = nt->hlen + sizeof(struct iphdr);
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
        ip_tunnel_add(itn, nt);
        return nt;
 }
@@ -929,7 +933,7 @@ int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
        int t_hlen = tunnel->hlen + sizeof(struct iphdr);
        int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
 
-       if (new_mtu < 68)
+       if (new_mtu < ETH_MIN_MTU)
                return -EINVAL;
 
        if (new_mtu > max_mtu) {
index ecbe5a7c2d6d3fb6a55e4c8464eab4853f4fe909..d78d738fb1720881ad1b681cc80564f1312f2c6f 100644 (file)
@@ -89,9 +89,10 @@ struct raw_frag_vec {
        int hlen;
 };
 
-static struct raw_hashinfo raw_v4_hashinfo = {
+struct raw_hashinfo raw_v4_hashinfo = {
        .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
 };
+EXPORT_SYMBOL_GPL(raw_v4_hashinfo);
 
 int raw_hash_sk(struct sock *sk)
 {
@@ -120,7 +121,7 @@ void raw_unhash_sk(struct sock *sk)
 }
 EXPORT_SYMBOL_GPL(raw_unhash_sk);
 
-static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
+struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
                unsigned short num, __be32 raddr, __be32 laddr, int dif)
 {
        sk_for_each_from(sk) {
@@ -136,6 +137,7 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
 found:
        return sk;
 }
+EXPORT_SYMBOL_GPL(__raw_v4_lookup);
 
 /*
  *     0 - deliver
@@ -912,6 +914,20 @@ static int compat_raw_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg
 }
 #endif
 
+int raw_abort(struct sock *sk, int err)
+{
+       lock_sock(sk);
+
+       sk->sk_err = err;
+       sk->sk_error_report(sk);
+       udp_disconnect(sk, 0);
+
+       release_sock(sk);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(raw_abort);
+
 struct proto raw_prot = {
        .name              = "RAW",
        .owner             = THIS_MODULE,
@@ -937,6 +953,7 @@ struct proto raw_prot = {
        .compat_getsockopt = compat_raw_getsockopt,
        .compat_ioctl      = compat_raw_ioctl,
 #endif
+       .diag_destroy      = raw_abort,
 };
 
 #ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c
new file mode 100644 (file)
index 0000000..be93090
--- /dev/null
@@ -0,0 +1,262 @@
+#include <linux/module.h>
+
+#include <linux/inet_diag.h>
+#include <linux/sock_diag.h>
+
+#include <net/inet_sock.h>
+#include <net/raw.h>
+#include <net/rawv6.h>
+
+#ifdef pr_fmt
+# undef pr_fmt
+#endif
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+static struct raw_hashinfo *
+raw_get_hashinfo(const struct inet_diag_req_v2 *r)
+{
+       if (r->sdiag_family == AF_INET) {
+               return &raw_v4_hashinfo;
+#if IS_ENABLED(CONFIG_IPV6)
+       } else if (r->sdiag_family == AF_INET6) {
+               return &raw_v6_hashinfo;
+#endif
+       } else {
+               pr_warn_once("Unexpected inet family %d\n",
+                            r->sdiag_family);
+               WARN_ON_ONCE(1);
+               return ERR_PTR(-EINVAL);
+       }
+}
+
+/*
+ * Due to requirement of not breaking user API we can't simply
+ * rename @pad field in inet_diag_req_v2 structure, instead
+ * use helper to figure it out.
+ */
+
+static struct sock *raw_lookup(struct net *net, struct sock *from,
+                              const struct inet_diag_req_v2 *req)
+{
+       struct inet_diag_req_raw *r = (void *)req;
+       struct sock *sk = NULL;
+
+       if (r->sdiag_family == AF_INET)
+               sk = __raw_v4_lookup(net, from, r->sdiag_raw_protocol,
+                                    r->id.idiag_dst[0],
+                                    r->id.idiag_src[0],
+                                    r->id.idiag_if);
+#if IS_ENABLED(CONFIG_IPV6)
+       else
+               sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol,
+                                    (const struct in6_addr *)r->id.idiag_src,
+                                    (const struct in6_addr *)r->id.idiag_dst,
+                                    r->id.idiag_if);
+#endif
+       return sk;
+}
+
+static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 *r)
+{
+       struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
+       struct sock *sk = NULL, *s;
+       int slot;
+
+       if (IS_ERR(hashinfo))
+               return ERR_CAST(hashinfo);
+
+       read_lock(&hashinfo->lock);
+       for (slot = 0; slot < RAW_HTABLE_SIZE; slot++) {
+               sk_for_each(s, &hashinfo->ht[slot]) {
+                       sk = raw_lookup(net, s, r);
+                       if (sk) {
+                               /*
+                                * Grab it and keep until we fill
+                                * diag meaage to be reported, so
+                                * caller should call sock_put then.
+                                * We can do that because we're keeping
+                                * hashinfo->lock here.
+                                */
+                               sock_hold(sk);
+                               break;
+                       }
+               }
+       }
+       read_unlock(&hashinfo->lock);
+
+       return sk ? sk : ERR_PTR(-ENOENT);
+}
+
+static int raw_diag_dump_one(struct sk_buff *in_skb,
+                            const struct nlmsghdr *nlh,
+                            const struct inet_diag_req_v2 *r)
+{
+       struct net *net = sock_net(in_skb->sk);
+       struct sk_buff *rep;
+       struct sock *sk;
+       int err;
+
+       sk = raw_sock_get(net, r);
+       if (IS_ERR(sk))
+               return PTR_ERR(sk);
+
+       rep = nlmsg_new(sizeof(struct inet_diag_msg) +
+                       sizeof(struct inet_diag_meminfo) + 64,
+                       GFP_KERNEL);
+       if (!rep) {
+               sock_put(sk);
+               return -ENOMEM;
+       }
+
+       err = inet_sk_diag_fill(sk, NULL, rep, r,
+                               sk_user_ns(NETLINK_CB(in_skb).sk),
+                               NETLINK_CB(in_skb).portid,
+                               nlh->nlmsg_seq, 0, nlh,
+                               netlink_net_capable(in_skb, CAP_NET_ADMIN));
+       sock_put(sk);
+
+       if (err < 0) {
+               kfree_skb(rep);
+               return err;
+       }
+
+       err = netlink_unicast(net->diag_nlsk, rep,
+                             NETLINK_CB(in_skb).portid,
+                             MSG_DONTWAIT);
+       if (err > 0)
+               err = 0;
+       return err;
+}
+
+static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
+                       struct netlink_callback *cb,
+                       const struct inet_diag_req_v2 *r,
+                       struct nlattr *bc, bool net_admin)
+{
+       if (!inet_diag_bc_sk(bc, sk))
+               return 0;
+
+       return inet_sk_diag_fill(sk, NULL, skb, r,
+                                sk_user_ns(NETLINK_CB(cb->skb).sk),
+                                NETLINK_CB(cb->skb).portid,
+                                cb->nlh->nlmsg_seq, NLM_F_MULTI,
+                                cb->nlh, net_admin);
+}
+
+static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
+                         const struct inet_diag_req_v2 *r, struct nlattr *bc)
+{
+       bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
+       struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
+       struct net *net = sock_net(skb->sk);
+       int num, s_num, slot, s_slot;
+       struct sock *sk = NULL;
+
+       if (IS_ERR(hashinfo))
+               return;
+
+       s_slot = cb->args[0];
+       num = s_num = cb->args[1];
+
+       read_lock(&hashinfo->lock);
+       for (slot = s_slot; slot < RAW_HTABLE_SIZE; s_num = 0, slot++) {
+               num = 0;
+
+               sk_for_each(sk, &hashinfo->ht[slot]) {
+                       struct inet_sock *inet = inet_sk(sk);
+
+                       if (!net_eq(sock_net(sk), net))
+                               continue;
+                       if (num < s_num)
+                               goto next;
+                       if (sk->sk_family != r->sdiag_family)
+                               goto next;
+                       if (r->id.idiag_sport != inet->inet_sport &&
+                           r->id.idiag_sport)
+                               goto next;
+                       if (r->id.idiag_dport != inet->inet_dport &&
+                           r->id.idiag_dport)
+                               goto next;
+                       if (sk_diag_dump(sk, skb, cb, r, bc, net_admin) < 0)
+                               goto out_unlock;
+next:
+                       num++;
+               }
+       }
+
+out_unlock:
+       read_unlock(&hashinfo->lock);
+
+       cb->args[0] = slot;
+       cb->args[1] = num;
+}
+
+static void raw_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
+                             void *info)
+{
+       r->idiag_rqueue = sk_rmem_alloc_get(sk);
+       r->idiag_wqueue = sk_wmem_alloc_get(sk);
+}
+
+#ifdef CONFIG_INET_DIAG_DESTROY
+static int raw_diag_destroy(struct sk_buff *in_skb,
+                           const struct inet_diag_req_v2 *r)
+{
+       struct net *net = sock_net(in_skb->sk);
+       struct sock *sk;
+
+       sk = raw_sock_get(net, r);
+       if (IS_ERR(sk))
+               return PTR_ERR(sk);
+       return sock_diag_destroy(sk, ECONNABORTED);
+}
+#endif
+
+static const struct inet_diag_handler raw_diag_handler = {
+       .dump                   = raw_diag_dump,
+       .dump_one               = raw_diag_dump_one,
+       .idiag_get_info         = raw_diag_get_info,
+       .idiag_type             = IPPROTO_RAW,
+       .idiag_info_size        = 0,
+#ifdef CONFIG_INET_DIAG_DESTROY
+       .destroy                = raw_diag_destroy,
+#endif
+};
+
+static void __always_unused __check_inet_diag_req_raw(void)
+{
+       /*
+        * Make sure the two structures are identical,
+        * except the @pad field.
+        */
+#define __offset_mismatch(m1, m2)                      \
+       (offsetof(struct inet_diag_req_v2, m1) !=       \
+        offsetof(struct inet_diag_req_raw, m2))
+
+       BUILD_BUG_ON(sizeof(struct inet_diag_req_v2) !=
+                    sizeof(struct inet_diag_req_raw));
+       BUILD_BUG_ON(__offset_mismatch(sdiag_family, sdiag_family));
+       BUILD_BUG_ON(__offset_mismatch(sdiag_protocol, sdiag_protocol));
+       BUILD_BUG_ON(__offset_mismatch(idiag_ext, idiag_ext));
+       BUILD_BUG_ON(__offset_mismatch(pad, sdiag_raw_protocol));
+       BUILD_BUG_ON(__offset_mismatch(idiag_states, idiag_states));
+       BUILD_BUG_ON(__offset_mismatch(id, id));
+#undef __offset_mismatch
+}
+
+static int __init raw_diag_init(void)
+{
+       return inet_diag_register(&raw_diag_handler);
+}
+
+static void __exit raw_diag_exit(void)
+{
+       inet_diag_unregister(&raw_diag_handler);
+}
+
+module_init(raw_diag_init);
+module_exit(raw_diag_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-255 /* AF_INET - IPPROTO_RAW */);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 10-255 /* AF_INET6 - IPPROTO_RAW */);
index 0ea66c2c93444198fa21629dac617160f78a5cee..b89bce4c721eed530f5cfc725b759147b38cef42 100644 (file)
  * observed, or adjust the sending rate if it estimates there is a
  * traffic policer, in order to keep the drop rate reasonable.
  *
+ * Here is a state transition diagram for BBR:
+ *
+ *             |
+ *             V
+ *    +---> STARTUP  ----+
+ *    |        |         |
+ *    |        V         |
+ *    |      DRAIN   ----+
+ *    |        |         |
+ *    |        V         |
+ *    +---> PROBE_BW ----+
+ *    |      ^    |      |
+ *    |      |    |      |
+ *    |      +----+      |
+ *    |                  |
+ *    +---- PROBE_RTT <--+
+ *
+ * A BBR flow starts in STARTUP, and ramps up its sending rate quickly.
+ * When it estimates the pipe is full, it enters DRAIN to drain the queue.
+ * In steady state a BBR flow only uses PROBE_BW and PROBE_RTT.
+ * A long-lived BBR flow spends the vast majority of its time remaining
+ * (repeatedly) in PROBE_BW, fully probing and utilizing the pipe's bandwidth
+ * in a fair manner, with a small, bounded queue. *If* a flow has been
+ * continuously sending for the entire min_rtt window, and hasn't seen an RTT
+ * sample that matches or decreases its min_rtt estimate for 10 seconds, then
+ * it briefly enters PROBE_RTT to cut inflight to a minimum value to re-probe
+ * the path's two-way propagation delay (min_rtt). When exiting PROBE_RTT, if
+ * we estimated that we reached the full bw of the pipe then we enter PROBE_BW;
+ * otherwise we enter STARTUP to try to fill the pipe.
+ *
  * BBR is described in detail in:
  *   "BBR: Congestion-Based Congestion Control",
  *   Neal Cardwell, Yuchung Cheng, C. Stephen Gunn, Soheil Hassas Yeganeh,
@@ -51,7 +81,7 @@ enum bbr_mode {
        BBR_STARTUP,    /* ramp up sending rate rapidly to fill pipe */
        BBR_DRAIN,      /* drain any queue created during startup */
        BBR_PROBE_BW,   /* discover, share bw: pace around estimated bw */
-       BBR_PROBE_RTT,  /* cut cwnd to min to probe min_rtt */
+       BBR_PROBE_RTT,  /* cut inflight to min to probe min_rtt */
 };
 
 /* BBR congestion control block */
index a27b9c0e27c08b4e4aeaff3d0bfdf3ae561ba4d8..f2c59c8e57ff195c803ac05e6897242a6b097d00 100644 (file)
@@ -6298,13 +6298,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
                        goto drop;
        }
 
-
-       /* Accept backlog is full. If we have already queued enough
-        * of warm entries in syn queue, drop request. It is better than
-        * clogging syn queue with openreqs with exponentially increasing
-        * timeout.
-        */
-       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
+       if (sk_acceptq_is_full(sk)) {
                NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
                goto drop;
        }
index 61b7be303eeca39f4c581f2ebef42639e672a036..b9b8282633d49f4f62fba8840605fd17f611804c 100644 (file)
@@ -1891,7 +1891,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
        if (!sk) {
 get_head:
                ilb = &tcp_hashinfo.listening_hash[st->bucket];
-               spin_lock_bh(&ilb->lock);
+               spin_lock(&ilb->lock);
                sk = sk_head(&ilb->head);
                st->offset = 0;
                goto get_sk;
@@ -1908,7 +1908,7 @@ get_sk:
                if (sk->sk_family == st->family)
                        return sk;
        }
-       spin_unlock_bh(&ilb->lock);
+       spin_unlock(&ilb->lock);
        st->offset = 0;
        if (++st->bucket < INET_LHTABLE_SIZE)
                goto get_head;
@@ -2116,7 +2116,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
        switch (st->state) {
        case TCP_SEQ_STATE_LISTENING:
                if (v != SEQ_START_TOKEN)
-                       spin_unlock_bh(&tcp_hashinfo.listening_hash[st->bucket].lock);
+                       spin_unlock(&tcp_hashinfo.listening_hash[st->bucket].lock);
                break;
        case TCP_SEQ_STATE_ESTABLISHED:
                if (v)
index bf1f3b2b29d1226b572fdc6286c697c2f75b805b..d46f4d5b1c62edf95791e9d47d966c3bc61e1888 100644 (file)
@@ -742,14 +742,7 @@ void tcp_fastopen_cache_set(struct sock *sk, u16 mss,
        rcu_read_unlock();
 }
 
-static struct genl_family tcp_metrics_nl_family = {
-       .id             = GENL_ID_GENERATE,
-       .hdrsize        = 0,
-       .name           = TCP_METRICS_GENL_NAME,
-       .version        = TCP_METRICS_GENL_VERSION,
-       .maxattr        = TCP_METRICS_ATTR_MAX,
-       .netnsok        = true,
-};
+static struct genl_family tcp_metrics_nl_family;
 
 static const struct nla_policy tcp_metrics_nl_policy[TCP_METRICS_ATTR_MAX + 1] = {
        [TCP_METRICS_ATTR_ADDR_IPV4]    = { .type = NLA_U32, },
@@ -1116,6 +1109,17 @@ static const struct genl_ops tcp_metrics_nl_ops[] = {
        },
 };
 
+static struct genl_family tcp_metrics_nl_family __ro_after_init = {
+       .hdrsize        = 0,
+       .name           = TCP_METRICS_GENL_NAME,
+       .version        = TCP_METRICS_GENL_VERSION,
+       .maxattr        = TCP_METRICS_ATTR_MAX,
+       .netnsok        = true,
+       .module         = THIS_MODULE,
+       .ops            = tcp_metrics_nl_ops,
+       .n_ops          = ARRAY_SIZE(tcp_metrics_nl_ops),
+};
+
 static unsigned int tcpmhash_entries;
 static int __init set_tcpmhash_entries(char *str)
 {
@@ -1179,8 +1183,7 @@ void __init tcp_metrics_init(void)
        if (ret < 0)
                panic("Could not allocate the tcp_metrics hash table\n");
 
-       ret = genl_register_family_with_ops(&tcp_metrics_nl_family,
-                                           tcp_metrics_nl_ops);
+       ret = genl_register_family(&tcp_metrics_nl_family);
        if (ret < 0)
                panic("Could not register tcp_metrics generic netlink\n");
 }
index d123d68f4d1de093a9e9b36f210600fa7406d5e9..195992e0440d8809f3939d33302d8f68608d3b84 100644 (file)
@@ -1172,6 +1172,112 @@ out:
        return ret;
 }
 
+static void udp_rmem_release(struct sock *sk, int size, int partial)
+{
+       int amt;
+
+       atomic_sub(size, &sk->sk_rmem_alloc);
+
+       spin_lock_bh(&sk->sk_receive_queue.lock);
+       sk->sk_forward_alloc += size;
+       amt = (sk->sk_forward_alloc - partial) & ~(SK_MEM_QUANTUM - 1);
+       sk->sk_forward_alloc -= amt;
+       spin_unlock_bh(&sk->sk_receive_queue.lock);
+
+       if (amt)
+               __sk_mem_reduce_allocated(sk, amt >> SK_MEM_QUANTUM_SHIFT);
+}
+
+static void udp_rmem_free(struct sk_buff *skb)
+{
+       udp_rmem_release(skb->sk, skb->truesize, 1);
+}
+
+int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
+{
+       struct sk_buff_head *list = &sk->sk_receive_queue;
+       int rmem, delta, amt, err = -ENOMEM;
+       int size = skb->truesize;
+
+       /* try to avoid the costly atomic add/sub pair when the receive
+        * queue is full; always allow at least a packet
+        */
+       rmem = atomic_read(&sk->sk_rmem_alloc);
+       if (rmem && (rmem + size > sk->sk_rcvbuf))
+               goto drop;
+
+       /* we drop only if the receive buf is full and the receive
+        * queue contains some other skb
+        */
+       rmem = atomic_add_return(size, &sk->sk_rmem_alloc);
+       if ((rmem > sk->sk_rcvbuf) && (rmem > size))
+               goto uncharge_drop;
+
+       spin_lock(&list->lock);
+       if (size >= sk->sk_forward_alloc) {
+               amt = sk_mem_pages(size);
+               delta = amt << SK_MEM_QUANTUM_SHIFT;
+               if (!__sk_mem_raise_allocated(sk, delta, amt, SK_MEM_RECV)) {
+                       err = -ENOBUFS;
+                       spin_unlock(&list->lock);
+                       goto uncharge_drop;
+               }
+
+               sk->sk_forward_alloc += delta;
+       }
+
+       sk->sk_forward_alloc -= size;
+
+       /* the skb owner in now the udp socket */
+       skb->sk = sk;
+       skb->destructor = udp_rmem_free;
+       skb->dev = NULL;
+       sock_skb_set_dropcount(sk, skb);
+
+       __skb_queue_tail(list, skb);
+       spin_unlock(&list->lock);
+
+       if (!sock_flag(sk, SOCK_DEAD))
+               sk->sk_data_ready(sk);
+
+       return 0;
+
+uncharge_drop:
+       atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
+
+drop:
+       atomic_inc(&sk->sk_drops);
+       return err;
+}
+EXPORT_SYMBOL_GPL(__udp_enqueue_schedule_skb);
+
+static void udp_destruct_sock(struct sock *sk)
+{
+       /* reclaim completely the forward allocated memory */
+       __skb_queue_purge(&sk->sk_receive_queue);
+       udp_rmem_release(sk, 0, 0);
+       inet_sock_destruct(sk);
+}
+
+int udp_init_sock(struct sock *sk)
+{
+       sk->sk_destruct = udp_destruct_sock;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(udp_init_sock);
+
+void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)
+{
+       if (unlikely(READ_ONCE(sk->sk_peek_off) >= 0)) {
+               bool slow = lock_sock_fast(sk);
+
+               sk_peek_offset_bwd(sk, len);
+               unlock_sock_fast(sk, slow);
+       }
+       consume_skb(skb);
+}
+EXPORT_SYMBOL_GPL(skb_consume_udp);
+
 /**
  *     first_packet_length     - return length of first packet in receive queue
  *     @sk: socket
@@ -1201,13 +1307,7 @@ static int first_packet_length(struct sock *sk)
        res = skb ? skb->len : -1;
        spin_unlock_bh(&rcvq->lock);
 
-       if (!skb_queue_empty(&list_kill)) {
-               bool slow = lock_sock_fast(sk);
-
-               __skb_queue_purge(&list_kill);
-               sk_mem_reclaim_partial(sk);
-               unlock_sock_fast(sk, slow);
-       }
+       __skb_queue_purge(&list_kill);
        return res;
 }
 
@@ -1256,7 +1356,6 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
        int err;
        int is_udplite = IS_UDPLITE(sk);
        bool checksum_valid = false;
-       bool slow;
 
        if (flags & MSG_ERRQUEUE)
                return ip_recv_error(sk, msg, len, addr_len);
@@ -1297,13 +1396,12 @@ try_again:
        }
 
        if (unlikely(err)) {
-               trace_kfree_skb(skb, udp_recvmsg);
                if (!peeked) {
                        atomic_inc(&sk->sk_drops);
                        UDP_INC_STATS(sock_net(sk),
                                      UDP_MIB_INERRORS, is_udplite);
                }
-               skb_free_datagram_locked(sk, skb);
+               kfree_skb(skb);
                return err;
        }
 
@@ -1328,16 +1426,15 @@ try_again:
        if (flags & MSG_TRUNC)
                err = ulen;
 
-       __skb_free_datagram_locked(sk, skb, peeking ? -err : err);
+       skb_consume_udp(sk, skb, peeking ? -err : err);
        return err;
 
 csum_copy_err:
-       slow = lock_sock_fast(sk);
-       if (!skb_kill_datagram(sk, skb, flags)) {
+       if (!__sk_queue_drop_skb(sk, skb, flags)) {
                UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
                UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
        }
-       unlock_sock_fast(sk, slow);
+       kfree_skb(skb);
 
        /* starting over for a new packet, but check if we need to yield */
        cond_resched();
@@ -1465,7 +1562,7 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                sk_incoming_cpu_update(sk);
        }
 
-       rc = __sock_queue_rcv_skb(sk, skb);
+       rc = __udp_enqueue_schedule_skb(sk, skb);
        if (rc < 0) {
                int is_udplite = IS_UDPLITE(sk);
 
@@ -1480,7 +1577,6 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
        }
 
        return 0;
-
 }
 
 static struct static_key udp_encap_needed __read_mostly;
@@ -1502,7 +1598,6 @@ EXPORT_SYMBOL(udp_encap_enable);
 int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        struct udp_sock *up = udp_sk(sk);
-       int rc;
        int is_udplite = IS_UDPLITE(sk);
 
        /*
@@ -1589,25 +1684,9 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                goto drop;
 
        udp_csum_pull_header(skb);
-       if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
-               __UDP_INC_STATS(sock_net(sk), UDP_MIB_RCVBUFERRORS,
-                               is_udplite);
-               goto drop;
-       }
-
-       rc = 0;
 
        ipv4_pktinfo_prepare(sk, skb);
-       bh_lock_sock(sk);
-       if (!sock_owned_by_user(sk))
-               rc = __udp_queue_rcv_skb(sk, skb);
-       else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) {
-               bh_unlock_sock(sk);
-               goto drop;
-       }
-       bh_unlock_sock(sk);
-
-       return rc;
+       return __udp_queue_rcv_skb(sk, skb);
 
 csum_error:
        __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
@@ -2217,13 +2296,13 @@ struct proto udp_prot = {
        .connect           = ip4_datagram_connect,
        .disconnect        = udp_disconnect,
        .ioctl             = udp_ioctl,
+       .init              = udp_init_sock,
        .destroy           = udp_destroy_sock,
        .setsockopt        = udp_setsockopt,
        .getsockopt        = udp_getsockopt,
        .sendmsg           = udp_sendmsg,
        .recvmsg           = udp_recvmsg,
        .sendpage          = udp_sendpage,
-       .backlog_rcv       = __udp_queue_rcv_skb,
        .release_cb        = ip4_datagram_release_cb,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
index e50c27a93e17d8e44260d89bbbdf70c046e665cb..a7bc54ab46e2d10ab18abdc3fcef511f06574343 100644 (file)
@@ -6,29 +6,88 @@
 #include <linux/socket.h>
 #include <linux/types.h>
 #include <net/checksum.h>
+#include <net/dst_cache.h>
 #include <net/ip.h>
 #include <net/ip6_fib.h>
+#include <net/ip6_route.h>
 #include <net/lwtunnel.h>
 #include <net/protocol.h>
 #include <uapi/linux/ila.h>
 #include "ila.h"
 
+struct ila_lwt {
+       struct ila_params p;
+       struct dst_cache dst_cache;
+       u32 connected : 1;
+};
+
+static inline struct ila_lwt *ila_lwt_lwtunnel(
+       struct lwtunnel_state *lwt)
+{
+       return (struct ila_lwt *)lwt->data;
+}
+
 static inline struct ila_params *ila_params_lwtunnel(
-       struct lwtunnel_state *lwstate)
+       struct lwtunnel_state *lwt)
 {
-       return (struct ila_params *)lwstate->data;
+       return &ila_lwt_lwtunnel(lwt)->p;
 }
 
 static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
-       struct dst_entry *dst = skb_dst(skb);
+       struct dst_entry *orig_dst = skb_dst(skb);
+       struct rt6_info *rt = (struct rt6_info *)orig_dst;
+       struct ila_lwt *ilwt = ila_lwt_lwtunnel(orig_dst->lwtstate);
+       struct dst_entry *dst;
+       int err = -EINVAL;
 
        if (skb->protocol != htons(ETH_P_IPV6))
                goto drop;
 
-       ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate), true);
+       ila_update_ipv6_locator(skb, ila_params_lwtunnel(orig_dst->lwtstate),
+                               true);
 
-       return dst->lwtstate->orig_output(net, sk, skb);
+       if (rt->rt6i_flags & (RTF_GATEWAY | RTF_CACHE)) {
+               /* Already have a next hop address in route, no need for
+                * dest cache route.
+                */
+               return orig_dst->lwtstate->orig_output(net, sk, skb);
+       }
+
+       dst = dst_cache_get(&ilwt->dst_cache);
+       if (unlikely(!dst)) {
+               struct ipv6hdr *ip6h = ipv6_hdr(skb);
+               struct flowi6 fl6;
+
+               /* Lookup a route for the new destination. Take into
+                * account that the base route may already have a gateway.
+                */
+
+               memset(&fl6, 0, sizeof(fl6));
+               fl6.flowi6_oif = orig_dst->dev->ifindex;
+               fl6.flowi6_iif = LOOPBACK_IFINDEX;
+               fl6.daddr = *rt6_nexthop((struct rt6_info *)orig_dst,
+                                        &ip6h->daddr);
+
+               dst = ip6_route_output(net, NULL, &fl6);
+               if (dst->error) {
+                       err = -EHOSTUNREACH;
+                       dst_release(dst);
+                       goto drop;
+               }
+
+               dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+               if (IS_ERR(dst)) {
+                       err = PTR_ERR(dst);
+                       goto drop;
+               }
+
+               if (ilwt->connected)
+                       dst_cache_set_ip6(&ilwt->dst_cache, dst, &fl6.saddr);
+       }
+
+       skb_dst_set(skb, dst);
+       return dst_output(net, sk, skb);
 
 drop:
        kfree_skb(skb);
@@ -60,9 +119,9 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
                           unsigned int family, const void *cfg,
                           struct lwtunnel_state **ts)
 {
+       struct ila_lwt *ilwt;
        struct ila_params *p;
        struct nlattr *tb[ILA_ATTR_MAX + 1];
-       size_t encap_len = sizeof(*p);
        struct lwtunnel_state *newts;
        const struct fib6_config *cfg6 = cfg;
        struct ila_addr *iaddr;
@@ -71,7 +130,7 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
        if (family != AF_INET6)
                return -EINVAL;
 
-       if (cfg6->fc_dst_len < sizeof(struct ila_locator) + 1) {
+       if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) {
                /* Need to have full locator and at least type field
                 * included in destination
                 */
@@ -95,11 +154,17 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
        if (!tb[ILA_ATTR_LOCATOR])
                return -EINVAL;
 
-       newts = lwtunnel_state_alloc(encap_len);
+       newts = lwtunnel_state_alloc(sizeof(*ilwt));
        if (!newts)
                return -ENOMEM;
 
-       newts->len = encap_len;
+       ilwt = ila_lwt_lwtunnel(newts);
+       ret = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
+       if (ret) {
+               kfree(newts);
+               return ret;
+       }
+
        p = ila_params_lwtunnel(newts);
 
        p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);
@@ -120,11 +185,19 @@ static int ila_build_state(struct net_device *dev, struct nlattr *nla,
        newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
                        LWTUNNEL_STATE_INPUT_REDIRECT;
 
+       if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
+               ilwt->connected = 1;
+
        *ts = newts;
 
        return 0;
 }
 
+static void ila_destroy_state(struct lwtunnel_state *lwt)
+{
+       dst_cache_destroy(&ila_lwt_lwtunnel(lwt)->dst_cache);
+}
+
 static int ila_fill_encap_info(struct sk_buff *skb,
                               struct lwtunnel_state *lwtstate)
 {
@@ -159,6 +232,7 @@ static int ila_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
 
 static const struct lwtunnel_encap_ops ila_encap_ops = {
        .build_state = ila_build_state,
+       .destroy_state = ila_destroy_state,
        .output = ila_output,
        .input = ila_input,
        .fill_encap = ila_fill_encap_info,
index e604013dd8147a36ac247ef44f0c37c6519cbcc4..628ae6d85b59a2bb731df8a8fb888d97546a53c0 100644 (file)
@@ -118,15 +118,7 @@ static const struct rhashtable_params rht_params = {
        .obj_cmpfn = ila_cmpfn,
 };
 
-static struct genl_family ila_nl_family = {
-       .id             = GENL_ID_GENERATE,
-       .hdrsize        = 0,
-       .name           = ILA_GENL_NAME,
-       .version        = ILA_GENL_VERSION,
-       .maxattr        = ILA_ATTR_MAX,
-       .netnsok        = true,
-       .parallel_ops   = true,
-};
+static struct genl_family ila_nl_family;
 
 static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
        [ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
@@ -561,6 +553,18 @@ static const struct genl_ops ila_nl_ops[] = {
        },
 };
 
+static struct genl_family ila_nl_family __ro_after_init = {
+       .hdrsize        = 0,
+       .name           = ILA_GENL_NAME,
+       .version        = ILA_GENL_VERSION,
+       .maxattr        = ILA_ATTR_MAX,
+       .netnsok        = true,
+       .parallel_ops   = true,
+       .module         = THIS_MODULE,
+       .ops            = ila_nl_ops,
+       .n_ops          = ARRAY_SIZE(ila_nl_ops),
+};
+
 #define ILA_HASH_TABLE_SIZE 1024
 
 static __net_init int ila_init_net(struct net *net)
@@ -623,7 +627,7 @@ static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral)
        return 0;
 }
 
-int ila_xlat_init(void)
+int __init ila_xlat_init(void)
 {
        int ret;
 
@@ -631,8 +635,7 @@ int ila_xlat_init(void)
        if (ret)
                goto exit;
 
-       ret = genl_register_family_with_ops(&ila_nl_family,
-                                           ila_nl_ops);
+       ret = genl_register_family(&ila_nl_family);
        if (ret < 0)
                goto unregister;
 
index 87784560dc46bceaf184f811222f312383f11e04..03e050d225083cbbd154e32528ff0e510f679d49 100644 (file)
@@ -1637,7 +1637,7 @@ int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
        struct ip6_tnl *tnl = netdev_priv(dev);
 
        if (tnl->parms.proto == IPPROTO_IPIP) {
-               if (new_mtu < 68)
+               if (new_mtu < ETH_MIN_MTU)
                        return -EINVAL;
        } else {
                if (new_mtu < IPV6_MIN_MTU)
@@ -1790,6 +1790,8 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
        dev->mtu = ETH_DATA_LEN - t_hlen;
        if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
                dev->mtu -= 8;
+       dev->min_mtu = ETH_MIN_MTU;
+       dev->max_mtu = 0xFFF8 - dev->hard_header_len;
 
        return 0;
 
index 8a02ca8a11af4b388bfe996711458efd46b641cf..35c5b2d8c401a99f1344c50ddd3956c4e6f6a53e 100644 (file)
@@ -812,30 +812,11 @@ vti6_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        return err;
 }
 
-/**
- * vti6_tnl_change_mtu - change mtu manually for tunnel device
- *   @dev: virtual device associated with tunnel
- *   @new_mtu: the new mtu
- *
- * Return:
- *   0 on success,
- *   %-EINVAL if mtu too small
- **/
-static int vti6_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu < IPV6_MIN_MTU)
-               return -EINVAL;
-
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static const struct net_device_ops vti6_netdev_ops = {
        .ndo_init       = vti6_dev_init,
        .ndo_uninit     = vti6_dev_uninit,
        .ndo_start_xmit = vti6_tnl_xmit,
        .ndo_do_ioctl   = vti6_ioctl,
-       .ndo_change_mtu = vti6_change_mtu,
        .ndo_get_stats64 = ip_tunnel_get_stats64,
        .ndo_get_iflink = ip6_tnl_get_iflink,
 };
@@ -855,6 +836,8 @@ static void vti6_dev_setup(struct net_device *dev)
        dev->type = ARPHRD_TUNNEL6;
        dev->hard_header_len = LL_MAX_HEADER + sizeof(struct ipv6hdr);
        dev->mtu = ETH_DATA_LEN;
+       dev->min_mtu = IPV6_MIN_MTU;
+       dev->max_mtu = IP_MAX_MTU;
        dev->flags |= IFF_NOARP;
        dev->addr_len = sizeof(struct in6_addr);
        netif_keep_dst(dev);
index 054a1d84fc5e940577d9c96fad3578d7038833b9..610e09354b2e6536349dcef297c336d193b9f748 100644 (file)
 
 #define        ICMPV6_HDRLEN   4       /* ICMPv6 header, RFC 4443 Section 2.1 */
 
-static struct raw_hashinfo raw_v6_hashinfo = {
+struct raw_hashinfo raw_v6_hashinfo = {
        .lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock),
 };
+EXPORT_SYMBOL_GPL(raw_v6_hashinfo);
 
-static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
+struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
                unsigned short num, const struct in6_addr *loc_addr,
                const struct in6_addr *rmt_addr, int dif)
 {
@@ -102,6 +103,7 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
 found:
        return sk;
 }
+EXPORT_SYMBOL_GPL(__raw_v6_lookup);
 
 /*
  *     0 - deliver
@@ -1259,6 +1261,7 @@ struct proto rawv6_prot = {
        .compat_getsockopt = compat_rawv6_getsockopt,
        .compat_ioctl      = compat_rawv6_ioctl,
 #endif
+       .diag_destroy      = raw_abort,
 };
 
 #ifdef CONFIG_PROC_FS
index b1cdf8009d29c4a36a9c7f3f545930134b0d51d5..dc7a3449ffc1c1eceaf2c2e6e6acff4423d6d1d5 100644 (file)
@@ -1318,23 +1318,11 @@ done:
        return err;
 }
 
-static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
-{
-       struct ip_tunnel *tunnel = netdev_priv(dev);
-       int t_hlen = tunnel->hlen + sizeof(struct iphdr);
-
-       if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - t_hlen)
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static const struct net_device_ops ipip6_netdev_ops = {
        .ndo_init       = ipip6_tunnel_init,
        .ndo_uninit     = ipip6_tunnel_uninit,
        .ndo_start_xmit = sit_tunnel_xmit,
        .ndo_do_ioctl   = ipip6_tunnel_ioctl,
-       .ndo_change_mtu = ipip6_tunnel_change_mtu,
        .ndo_get_stats64 = ip_tunnel_get_stats64,
        .ndo_get_iflink = ip_tunnel_get_iflink,
 };
@@ -1365,6 +1353,8 @@ static void ipip6_tunnel_setup(struct net_device *dev)
        dev->type               = ARPHRD_SIT;
        dev->hard_header_len    = LL_MAX_HEADER + t_hlen;
        dev->mtu                = ETH_DATA_LEN - t_hlen;
+       dev->min_mtu            = IPV6_MIN_MTU;
+       dev->max_mtu            = 0xFFF8 - t_hlen;
        dev->flags              = IFF_NOARP;
        netif_keep_dst(dev);
        dev->addr_len           = 4;
index b2ef061e6836af29048d1d86ed7b29587f3dd410..a7700bbf67887b5245038b6ba9cb273d8b7ca642 100644 (file)
@@ -334,7 +334,6 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
        int is_udplite = IS_UDPLITE(sk);
        bool checksum_valid = false;
        int is_udp4;
-       bool slow;
 
        if (flags & MSG_ERRQUEUE)
                return ipv6_recv_error(sk, msg, len, addr_len);
@@ -378,7 +377,6 @@ try_again:
                        goto csum_copy_err;
        }
        if (unlikely(err)) {
-               trace_kfree_skb(skb, udpv6_recvmsg);
                if (!peeked) {
                        atomic_inc(&sk->sk_drops);
                        if (is_udp4)
@@ -388,7 +386,7 @@ try_again:
                                UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS,
                                               is_udplite);
                }
-               skb_free_datagram_locked(sk, skb);
+               kfree_skb(skb);
                return err;
        }
        if (!peeked) {
@@ -438,12 +436,11 @@ try_again:
        if (flags & MSG_TRUNC)
                err = ulen;
 
-       __skb_free_datagram_locked(sk, skb, peeking ? -err : err);
+       skb_consume_udp(sk, skb, peeking ? -err : err);
        return err;
 
 csum_copy_err:
-       slow = lock_sock_fast(sk);
-       if (!skb_kill_datagram(sk, skb, flags)) {
+       if (!__sk_queue_drop_skb(sk, skb, flags)) {
                if (is_udp4) {
                        UDP_INC_STATS(sock_net(sk),
                                      UDP_MIB_CSUMERRORS, is_udplite);
@@ -456,7 +453,7 @@ csum_copy_err:
                                       UDP_MIB_INERRORS, is_udplite);
                }
        }
-       unlock_sock_fast(sk, slow);
+       kfree_skb(skb);
 
        /* starting over for a new packet, but check if we need to yield */
        cond_resched();
@@ -524,7 +521,7 @@ static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                sk_incoming_cpu_update(sk);
        }
 
-       rc = __sock_queue_rcv_skb(sk, skb);
+       rc = __udp_enqueue_schedule_skb(sk, skb);
        if (rc < 0) {
                int is_udplite = IS_UDPLITE(sk);
 
@@ -536,6 +533,7 @@ static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                kfree_skb(skb);
                return -1;
        }
+
        return 0;
 }
 
@@ -557,7 +555,6 @@ EXPORT_SYMBOL(udpv6_encap_enable);
 int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        struct udp_sock *up = udp_sk(sk);
-       int rc;
        int is_udplite = IS_UDPLITE(sk);
 
        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
@@ -623,25 +620,10 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                goto drop;
 
        udp_csum_pull_header(skb);
-       if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
-               __UDP6_INC_STATS(sock_net(sk),
-                                UDP_MIB_RCVBUFERRORS, is_udplite);
-               goto drop;
-       }
 
        skb_dst_drop(skb);
 
-       bh_lock_sock(sk);
-       rc = 0;
-       if (!sock_owned_by_user(sk))
-               rc = __udpv6_queue_rcv_skb(sk, skb);
-       else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) {
-               bh_unlock_sock(sk);
-               goto drop;
-       }
-       bh_unlock_sock(sk);
-
-       return rc;
+       return __udpv6_queue_rcv_skb(sk, skb);
 
 csum_error:
        __UDP6_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
@@ -1434,12 +1416,12 @@ struct proto udpv6_prot = {
        .connect           = ip6_datagram_connect,
        .disconnect        = udp_disconnect,
        .ioctl             = udp_ioctl,
+       .init              = udp_init_sock,
        .destroy           = udpv6_destroy_sock,
        .setsockopt        = udpv6_setsockopt,
        .getsockopt        = udpv6_getsockopt,
        .sendmsg           = udpv6_sendmsg,
        .recvmsg           = udpv6_recvmsg,
-       .backlog_rcv       = __udpv6_queue_rcv_skb,
        .release_cb        = ip6_datagram_release_cb,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
index d8b7267280c38fdea5930764d5ca8d2b11746fd7..74d09f91709e6121ed80b8f089283615a5ffce5e 100644 (file)
@@ -51,7 +51,6 @@ static const struct net_device_ops irlan_eth_netdev_ops = {
        .ndo_stop               = irlan_eth_close,
        .ndo_start_xmit         = irlan_eth_xmit,
        .ndo_set_rx_mode        = irlan_eth_set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
 };
 
@@ -67,7 +66,8 @@ static void irlan_eth_setup(struct net_device *dev)
 
        dev->netdev_ops         = &irlan_eth_netdev_ops;
        dev->destructor         = free_netdev;
-
+       dev->min_mtu            = 0;
+       dev->max_mtu            = ETH_MAX_MTU;
 
        /*
         * Lets do all queueing in IrTTP instead of this device driver.
index e15c40e86660cf204cc1bc734abde164fb3ef22e..7fc340e574cf3b1e5484cbcbabe3a1e33be582b4 100644 (file)
 
 
 
-static struct genl_family irda_nl_family = {
-       .id = GENL_ID_GENERATE,
-       .name = IRDA_NL_NAME,
-       .hdrsize = 0,
-       .version = IRDA_NL_VERSION,
-       .maxattr = IRDA_NL_CMD_MAX,
-};
+static struct genl_family irda_nl_family;
 
 static struct net_device * ifname_to_netdev(struct net *net, struct genl_info *info)
 {
@@ -147,9 +141,19 @@ static const struct genl_ops irda_nl_ops[] = {
 
 };
 
-int irda_nl_register(void)
+static struct genl_family irda_nl_family __ro_after_init = {
+       .name = IRDA_NL_NAME,
+       .hdrsize = 0,
+       .version = IRDA_NL_VERSION,
+       .maxattr = IRDA_NL_CMD_MAX,
+       .module = THIS_MODULE,
+       .ops = irda_nl_ops,
+       .n_ops = ARRAY_SIZE(irda_nl_ops),
+};
+
+int __init irda_nl_register(void)
 {
-       return genl_register_family_with_ops(&irda_nl_family, irda_nl_ops);
+       return genl_register_family(&irda_nl_family);
 }
 
 void irda_nl_unregister(void)
index 02b45a8e8b35729a65c6d796136a846aa2df648b..cfb9e5f4e28f52c699072eaf41f12f3a6e667160 100644 (file)
@@ -453,19 +453,27 @@ static void iucv_sever_path(struct sock *sk, int with_user_data)
        }
 }
 
-/* Send FIN through an IUCV socket for HIPER transport */
+/* Send controlling flags through an IUCV socket for HIPER transport */
 static int iucv_send_ctrl(struct sock *sk, u8 flags)
 {
        int err = 0;
        int blen;
        struct sk_buff *skb;
+       u8 shutdown = 0;
 
        blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
+       if (sk->sk_shutdown & SEND_SHUTDOWN) {
+               /* controlling flags should be sent anyway */
+               shutdown = sk->sk_shutdown;
+               sk->sk_shutdown &= RCV_SHUTDOWN;
+       }
        skb = sock_alloc_send_skb(sk, blen, 1, &err);
        if (skb) {
                skb_reserve(skb, blen);
                err = afiucv_hs_send(NULL, sk, skb, flags);
        }
+       if (shutdown)
+               sk->sk_shutdown = shutdown;
        return err;
 }
 
@@ -1315,8 +1323,13 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
        }
 
        IUCV_SKB_CB(skb)->offset = 0;
-       if (sock_queue_rcv_skb(sk, skb))
-               skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb);
+       if (sk_filter(sk, skb)) {
+               atomic_inc(&sk->sk_drops);      /* skb rejected by filter */
+               kfree_skb(skb);
+               return;
+       }
+       if (__sock_queue_rcv_skb(sk, skb))      /* handle rcv queue full */
+               skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
 }
 
 /* iucv_process_message_q() - Process outstanding IUCV messages
@@ -1430,13 +1443,13 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg,
                rskb = skb_dequeue(&iucv->backlog_skb_q);
                while (rskb) {
                        IUCV_SKB_CB(rskb)->offset = 0;
-                       if (sock_queue_rcv_skb(sk, rskb)) {
+                       if (__sock_queue_rcv_skb(sk, rskb)) {
+                               /* handle rcv queue full */
                                skb_queue_head(&iucv->backlog_skb_q,
                                                rskb);
                                break;
-                       } else {
-                               rskb = skb_dequeue(&iucv->backlog_skb_q);
                        }
+                       rskb = skb_dequeue(&iucv->backlog_skb_q);
                }
                if (skb_queue_empty(&iucv->backlog_skb_q)) {
                        if (!list_empty(&iucv->message_q.list))
@@ -2116,12 +2129,17 @@ static int afiucv_hs_callback_rx(struct sock *sk, struct sk_buff *skb)
        skb_reset_transport_header(skb);
        skb_reset_network_header(skb);
        IUCV_SKB_CB(skb)->offset = 0;
+       if (sk_filter(sk, skb)) {
+               atomic_inc(&sk->sk_drops);      /* skb rejected by filter */
+               kfree_skb(skb);
+               return NET_RX_SUCCESS;
+       }
+
        spin_lock(&iucv->message_q.lock);
        if (skb_queue_empty(&iucv->backlog_skb_q)) {
-               if (sock_queue_rcv_skb(sk, skb)) {
+               if (__sock_queue_rcv_skb(sk, skb))
                        /* handle rcv queue full */
                        skb_queue_tail(&iucv->backlog_skb_q, skb);
-               }
        } else
                skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
        spin_unlock(&iucv->message_q.lock);
index 965f7e344cef8961a85c4e2e6d36f7d1b043f3d7..e2c6ae0245652521bbe96bd8227443b5f0267589 100644 (file)
@@ -259,6 +259,8 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
                session->mtu = dev->mtu - session->hdr_len;
        dev->mtu = session->mtu;
        dev->needed_headroom += session->hdr_len;
+       dev->min_mtu = 0;
+       dev->max_mtu = ETH_MAX_MTU;
 
        priv = netdev_priv(dev);
        priv->dev = dev;
index bf3117771822af3f8cdfcbc956d5b8018050c732..59aa2d204e4aa0ceda4d10068e73cb1ef1498af0 100644 (file)
 #include "l2tp_core.h"
 
 
-static struct genl_family l2tp_nl_family = {
-       .id             = GENL_ID_GENERATE,
-       .name           = L2TP_GENL_NAME,
-       .version        = L2TP_GENL_VERSION,
-       .hdrsize        = 0,
-       .maxattr        = L2TP_ATTR_MAX,
-       .netnsok        = true,
-};
+static struct genl_family l2tp_nl_family;
 
 static const struct genl_multicast_group l2tp_multicast_group[] = {
        {
@@ -977,6 +970,19 @@ static const struct genl_ops l2tp_nl_ops[] = {
        },
 };
 
+static struct genl_family l2tp_nl_family __ro_after_init = {
+       .name           = L2TP_GENL_NAME,
+       .version        = L2TP_GENL_VERSION,
+       .hdrsize        = 0,
+       .maxattr        = L2TP_ATTR_MAX,
+       .netnsok        = true,
+       .module         = THIS_MODULE,
+       .ops            = l2tp_nl_ops,
+       .n_ops          = ARRAY_SIZE(l2tp_nl_ops),
+       .mcgrps         = l2tp_multicast_group,
+       .n_mcgrps       = ARRAY_SIZE(l2tp_multicast_group),
+};
+
 int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops)
 {
        int ret;
@@ -1010,12 +1016,10 @@ void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type)
 }
 EXPORT_SYMBOL_GPL(l2tp_nl_unregister_ops);
 
-static int l2tp_nl_init(void)
+static int __init l2tp_nl_init(void)
 {
        pr_info("L2TP netlink interface\n");
-       return genl_register_family_with_ops_groups(&l2tp_nl_family,
-                                                   l2tp_nl_ops,
-                                                   l2tp_multicast_group);
+       return genl_register_family(&l2tp_nl_family);
 }
 
 static void l2tp_nl_cleanup(void)
index f9137a8341f4db16b9dca579b0ed8f5300a59767..0b202b343fd44bee43df293aaf663e3a6fd3e0d2 100644 (file)
@@ -19,6 +19,7 @@ mac80211-y := \
        aes_gcm.o \
        aes_cmac.o \
        aes_gmac.o \
+       fils_aead.o \
        cfg.o \
        ethtool.o \
        rx.o \
index bdf0790d89cca6fe3f64c097c84299ac35e1f3d0..d0bd5fff5f0a6241cd057183ed701de938c60757 100644 (file)
@@ -23,7 +23,7 @@
 #define AAD_LEN 20
 
 
-static void gf_mulx(u8 *pad)
+void gf_mulx(u8 *pad)
 {
        int i, carry;
 
@@ -35,9 +35,9 @@ static void gf_mulx(u8 *pad)
                pad[AES_BLOCK_SIZE - 1] ^= 0x87;
 }
 
-static void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
-                           const u8 *addr[], const size_t *len, u8 *mac,
-                           size_t mac_len)
+void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
+                    const u8 *addr[], const size_t *len, u8 *mac,
+                    size_t mac_len)
 {
        u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
        const u8 *pos, *end;
index 3702041f44fdb16ce382c701eb53ef9493009f52..c827e1d5de8b11a2b9cb8d0d17a7385e83bdd8bc 100644 (file)
 
 #include <linux/crypto.h>
 
+void gf_mulx(u8 *pad);
+void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
+                    const u8 *addr[], const size_t *len, u8 *mac,
+                    size_t mac_len);
 struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
                                                   size_t key_len);
 void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
index f6749dced021bc8176c3a8ae1b4fe263bd6730f6..3b5fd4188f2ac7c67c269ad425812221294c823e 100644 (file)
@@ -315,11 +315,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
        mutex_lock(&sta->ampdu_mlme.mtx);
 
        if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
-               tid_agg_rx = rcu_dereference_protected(
-                               sta->ampdu_mlme.tid_rx[tid],
-                               lockdep_is_held(&sta->ampdu_mlme.mtx));
-
-               if (tid_agg_rx->dialog_token == dialog_token) {
+               if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
                        ht_dbg_ratelimited(sta->sdata,
                                           "updated AddBA Req from %pM on tid %u\n",
                                           sta->sta.addr, tid);
@@ -396,7 +392,6 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
        }
 
        /* update data */
-       tid_agg_rx->dialog_token = dialog_token;
        tid_agg_rx->ssn = start_seq_num;
        tid_agg_rx->head_seq_num = start_seq_num;
        tid_agg_rx->buf_size = buf_size;
@@ -418,6 +413,7 @@ end:
        if (status == WLAN_STATUS_SUCCESS) {
                __set_bit(tid, sta->ampdu_mlme.agg_session_valid);
                __clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
+               sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
        }
        mutex_unlock(&sta->ampdu_mlme.mtx);
 
index fd6541f3ade3e1342ac0fdce3ae3403de5752770..e91e503bf99257d7e8f3945c1500eebaa91f5e81 100644 (file)
@@ -357,10 +357,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        mutex_lock(&local->sta_mtx);
 
        if (mac_addr) {
-               if (ieee80211_vif_is_mesh(&sdata->vif))
-                       sta = sta_info_get(sdata, mac_addr);
-               else
-                       sta = sta_info_get_bss(sdata, mac_addr);
+               sta = sta_info_get_bss(sdata, mac_addr);
                /*
                 * The ASSOC test makes sure the driver is ready to
                 * receive the key. When wpa_supplicant has roamed
@@ -867,6 +864,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
        }
        sdata->needed_rx_chains = sdata->local->rx_chains;
 
+       sdata->vif.bss_conf.beacon_int = params->beacon_interval;
+
        mutex_lock(&local->mtx);
        err = ieee80211_vif_use_channel(sdata, &params->chandef,
                                        IEEE80211_CHANCTX_SHARED);
@@ -897,7 +896,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
                                              vlan->vif.type);
        }
 
-       sdata->vif.bss_conf.beacon_int = params->beacon_interval;
        sdata->vif.bss_conf.dtim_period = params->dtim_period;
        sdata->vif.bss_conf.enable_beacon = true;
        sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p;
@@ -1523,9 +1521,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
                goto out_err;
 
        if (params->vlan && params->vlan != sta->sdata->dev) {
-               bool prev_4addr = false;
-               bool new_4addr = false;
-
                vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
                if (params->vlan->ieee80211_ptr->use_4addr) {
@@ -1535,26 +1530,21 @@ static int ieee80211_change_station(struct wiphy *wiphy,
                        }
 
                        rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
-                       new_4addr = true;
                        __ieee80211_check_fast_rx_iface(vlansdata);
                }
 
                if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-                   sta->sdata->u.vlan.sta) {
+                   sta->sdata->u.vlan.sta)
                        RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
-                       prev_4addr = true;
-               }
+
+               if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+                       ieee80211_vif_dec_num_mcast(sta->sdata);
 
                sta->sdata = vlansdata;
                ieee80211_check_fast_xmit(sta);
 
-               if (sta->sta_state == IEEE80211_STA_AUTHORIZED &&
-                   prev_4addr != new_4addr) {
-                       if (new_4addr)
-                               atomic_dec(&sta->sdata->bss->num_mcast_sta);
-                       else
-                               atomic_inc(&sta->sdata->bss->num_mcast_sta);
-               }
+               if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+                       ieee80211_vif_inc_num_mcast(sta->sdata);
 
                ieee80211_send_layer2_update(sta);
        }
@@ -2480,13 +2470,6 @@ int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
            smps_mode == IEEE80211_SMPS_AUTOMATIC)
                return 0;
 
-        /* If no associated stations, there's no need to do anything */
-       if (!atomic_read(&sdata->u.ap.num_mcast_sta)) {
-               sdata->smps_mode = smps_mode;
-               ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
-               return 0;
-       }
-
        ht_dbg(sdata,
               "SMPS %d requested in AP mode, sending Action frame to %d stations\n",
               smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));
index f56e2f487d096aef3f7e1c083688548f92ed7110..e02ba42ca827501fdefc155d0ad71f2d4ffc2f36 100644 (file)
@@ -210,6 +210,7 @@ static const char *hw_flag_names[] = {
        FLAG(TX_AMSDU),
        FLAG(TX_FRAG_LIST),
        FLAG(REPORTS_LOW_ACK),
+       FLAG(SUPPORTS_TX_FRAG),
 #undef FLAG
 };
 
index bcec1240f41d90bec8b97a3bf52f8a8fcf918384..1a05f85cb1f0610b41ea212df2624a9078ea16cd 100644 (file)
@@ -477,6 +477,7 @@ IEEE80211_IF_FILE_RW(tdls_wider_bw);
 IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC);
 IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC);
 IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC);
+IEEE80211_IF_FILE(num_mcast_sta_vlan, u.vlan.num_mcast_sta, ATOMIC);
 
 static ssize_t ieee80211_if_fmt_num_buffered_multicast(
        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@@ -684,6 +685,13 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
        DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
 }
 
+static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
+{
+       /* add num_mcast_sta_vlan using name num_mcast_sta */
+       debugfs_create_file("num_mcast_sta", 0400, sdata->vif.debugfs_dir,
+                           sdata, &num_mcast_sta_vlan_ops);
+}
+
 static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
 {
        DEBUGFS_ADD_MODE(tsf, 0600);
@@ -787,6 +795,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
        case NL80211_IFTYPE_AP:
                add_ap_files(sdata);
                break;
+       case NL80211_IFTYPE_AP_VLAN:
+               add_vlan_files(sdata);
+               break;
        case NL80211_IFTYPE_WDS:
                add_wds_files(sdata);
                break;
index a2fcdb47a0e68443baecfc805bfc33e617dd8146..f6003b8c2c3335925d605d46d0072a8a96fed930 100644 (file)
@@ -199,13 +199,18 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
                       "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
 
        for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
+               bool tid_rx_valid;
+
                tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]);
                tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]);
+               tid_rx_valid = test_bit(i, sta->ampdu_mlme.agg_session_valid);
 
                p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
-               p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_rx);
+               p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
+                              tid_rx_valid);
                p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
-                               tid_rx ? tid_rx->dialog_token : 0);
+                              tid_rx_valid ?
+                                       sta->ampdu_mlme.tid_rx_token[i] : 0);
                p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
                                tid_rx ? tid_rx->ssn : 0);
 
diff --git a/net/mac80211/fils_aead.c b/net/mac80211/fils_aead.c
new file mode 100644 (file)
index 0000000..ecfdd97
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * FILS AEAD for (Re)Association Request/Response frames
+ * Copyright 2016, Qualcomm Atheros, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/skcipher.h>
+
+#include "ieee80211_i.h"
+#include "aes_cmac.h"
+#include "fils_aead.h"
+
+static int aes_s2v(struct crypto_cipher *tfm,
+                  size_t num_elem, const u8 *addr[], size_t len[], u8 *v)
+{
+       u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
+       size_t i;
+       const u8 *data[2];
+       size_t data_len[2], data_elems;
+
+       /* D = AES-CMAC(K, <zero>) */
+       memset(tmp, 0, AES_BLOCK_SIZE);
+       data[0] = tmp;
+       data_len[0] = AES_BLOCK_SIZE;
+       aes_cmac_vector(tfm, 1, data, data_len, d, AES_BLOCK_SIZE);
+
+       for (i = 0; i < num_elem - 1; i++) {
+               /* D = dbl(D) xor AES_CMAC(K, Si) */
+               gf_mulx(d); /* dbl */
+               aes_cmac_vector(tfm, 1, &addr[i], &len[i], tmp,
+                               AES_BLOCK_SIZE);
+               crypto_xor(d, tmp, AES_BLOCK_SIZE);
+       }
+
+       if (len[i] >= AES_BLOCK_SIZE) {
+               /* len(Sn) >= 128 */
+               size_t j;
+               const u8 *pos;
+
+               /* T = Sn xorend D */
+
+               /* Use a temporary buffer to perform xorend on Sn (addr[i]) to
+                * avoid modifying the const input argument.
+                */
+               data[0] = addr[i];
+               data_len[0] = len[i] - AES_BLOCK_SIZE;
+               pos = addr[i] + data_len[0];
+               for (j = 0; j < AES_BLOCK_SIZE; j++)
+                       tmp[j] = pos[j] ^ d[j];
+               data[1] = tmp;
+               data_len[1] = AES_BLOCK_SIZE;
+               data_elems = 2;
+       } else {
+               /* len(Sn) < 128 */
+               /* T = dbl(D) xor pad(Sn) */
+               gf_mulx(d); /* dbl */
+               memset(tmp, 0, AES_BLOCK_SIZE);
+               memcpy(tmp, addr[i], len[i]);
+               tmp[len[i]] = 0x80;
+               crypto_xor(d, tmp, AES_BLOCK_SIZE);
+               data[0] = d;
+               data_len[0] = sizeof(d);
+               data_elems = 1;
+       }
+       /* V = AES-CMAC(K, T) */
+       aes_cmac_vector(tfm, data_elems, data, data_len, v, AES_BLOCK_SIZE);
+
+       return 0;
+}
+
+/* Note: addr[] and len[] needs to have one extra slot at the end. */
+static int aes_siv_encrypt(const u8 *key, size_t key_len,
+                          const u8 *plain, size_t plain_len,
+                          size_t num_elem, const u8 *addr[],
+                          size_t len[], u8 *out)
+{
+       u8 v[AES_BLOCK_SIZE];
+       struct crypto_cipher *tfm;
+       struct crypto_skcipher *tfm2;
+       struct skcipher_request *req;
+       int res;
+       struct scatterlist src[1], dst[1];
+       u8 *tmp;
+
+       key_len /= 2; /* S2V key || CTR key */
+
+       addr[num_elem] = plain;
+       len[num_elem] = plain_len;
+       num_elem++;
+
+       /* S2V */
+
+       tfm = crypto_alloc_cipher("aes", 0, 0);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+       /* K1 for S2V */
+       res = crypto_cipher_setkey(tfm, key, key_len);
+       if (!res)
+               res = aes_s2v(tfm, num_elem, addr, len, v);
+       crypto_free_cipher(tfm);
+       if (res)
+               return res;
+
+       /* Use a temporary buffer of the plaintext to handle need for
+        * overwriting this during AES-CTR.
+        */
+       tmp = kmemdup(plain, plain_len, GFP_KERNEL);
+       if (!tmp)
+               return -ENOMEM;
+
+       /* IV for CTR before encrypted data */
+       memcpy(out, v, AES_BLOCK_SIZE);
+
+       /* Synthetic IV to be used as the initial counter in CTR:
+        * Q = V bitand (1^64 || 0^1 || 1^31 || 0^1 || 1^31)
+        */
+       v[8] &= 0x7f;
+       v[12] &= 0x7f;
+
+       /* CTR */
+
+       tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, 0);
+       if (IS_ERR(tfm2)) {
+               kfree(tmp);
+               return PTR_ERR(tfm2);
+       }
+       /* K2 for CTR */
+       res = crypto_skcipher_setkey(tfm2, key + key_len, key_len);
+       if (res)
+               goto fail;
+
+       req = skcipher_request_alloc(tfm2, GFP_KERNEL);
+       if (!req) {
+               res = -ENOMEM;
+               goto fail;
+       }
+
+       sg_init_one(src, tmp, plain_len);
+       sg_init_one(dst, out + AES_BLOCK_SIZE, plain_len);
+       skcipher_request_set_crypt(req, src, dst, plain_len, v);
+       res = crypto_skcipher_encrypt(req);
+       skcipher_request_free(req);
+fail:
+       kfree(tmp);
+       crypto_free_skcipher(tfm2);
+       return res;
+}
+
+/* Note: addr[] and len[] needs to have one extra slot at the end. */
+static int aes_siv_decrypt(const u8 *key, size_t key_len,
+                          const u8 *iv_crypt, size_t iv_c_len,
+                          size_t num_elem, const u8 *addr[], size_t len[],
+                          u8 *out)
+{
+       struct crypto_cipher *tfm;
+       struct crypto_skcipher *tfm2;
+       struct skcipher_request *req;
+       struct scatterlist src[1], dst[1];
+       size_t crypt_len;
+       int res;
+       u8 frame_iv[AES_BLOCK_SIZE], iv[AES_BLOCK_SIZE];
+       u8 check[AES_BLOCK_SIZE];
+
+       crypt_len = iv_c_len - AES_BLOCK_SIZE;
+       key_len /= 2; /* S2V key || CTR key */
+       addr[num_elem] = out;
+       len[num_elem] = crypt_len;
+       num_elem++;
+
+       memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
+       memcpy(frame_iv, iv_crypt, AES_BLOCK_SIZE);
+
+       /* Synthetic IV to be used as the initial counter in CTR:
+        * Q = V bitand (1^64 || 0^1 || 1^31 || 0^1 || 1^31)
+        */
+       iv[8] &= 0x7f;
+       iv[12] &= 0x7f;
+
+       /* CTR */
+
+       tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, 0);
+       if (IS_ERR(tfm2))
+               return PTR_ERR(tfm2);
+       /* K2 for CTR */
+       res = crypto_skcipher_setkey(tfm2, key + key_len, key_len);
+       if (res) {
+               crypto_free_skcipher(tfm2);
+               return res;
+       }
+
+       req = skcipher_request_alloc(tfm2, GFP_KERNEL);
+       if (!req) {
+               crypto_free_skcipher(tfm2);
+               return -ENOMEM;
+       }
+
+       sg_init_one(src, iv_crypt + AES_BLOCK_SIZE, crypt_len);
+       sg_init_one(dst, out, crypt_len);
+       skcipher_request_set_crypt(req, src, dst, crypt_len, iv);
+       res = crypto_skcipher_decrypt(req);
+       skcipher_request_free(req);
+       crypto_free_skcipher(tfm2);
+       if (res)
+               return res;
+
+       /* S2V */
+
+       tfm = crypto_alloc_cipher("aes", 0, 0);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+       /* K1 for S2V */
+       res = crypto_cipher_setkey(tfm, key, key_len);
+       if (!res)
+               res = aes_s2v(tfm, num_elem, addr, len, check);
+       crypto_free_cipher(tfm);
+       if (res)
+               return res;
+       if (memcmp(check, frame_iv, AES_BLOCK_SIZE) != 0)
+               return -EINVAL;
+       return 0;
+}
+
+int fils_encrypt_assoc_req(struct sk_buff *skb,
+                          struct ieee80211_mgd_assoc_data *assoc_data)
+{
+       struct ieee80211_mgmt *mgmt = (void *)skb->data;
+       u8 *capab, *ies, *encr;
+       const u8 *addr[5 + 1], *session;
+       size_t len[5 + 1];
+       size_t crypt_len;
+
+       if (ieee80211_is_reassoc_req(mgmt->frame_control)) {
+               capab = (u8 *)&mgmt->u.reassoc_req.capab_info;
+               ies = mgmt->u.reassoc_req.variable;
+       } else {
+               capab = (u8 *)&mgmt->u.assoc_req.capab_info;
+               ies = mgmt->u.assoc_req.variable;
+       }
+
+       session = cfg80211_find_ext_ie(WLAN_EID_EXT_FILS_SESSION,
+                                      ies, skb->data + skb->len - ies);
+       if (!session || session[1] != 1 + 8)
+               return -EINVAL;
+       /* encrypt after FILS Session element */
+       encr = (u8 *)session + 2 + 1 + 8;
+
+       /* AES-SIV AAD vectors */
+
+       /* The STA's MAC address */
+       addr[0] = mgmt->sa;
+       len[0] = ETH_ALEN;
+       /* The AP's BSSID */
+       addr[1] = mgmt->da;
+       len[1] = ETH_ALEN;
+       /* The STA's nonce */
+       addr[2] = assoc_data->fils_nonces;
+       len[2] = FILS_NONCE_LEN;
+       /* The AP's nonce */
+       addr[3] = &assoc_data->fils_nonces[FILS_NONCE_LEN];
+       len[3] = FILS_NONCE_LEN;
+       /* The (Re)Association Request frame from the Capability Information
+        * field to the FILS Session element (both inclusive).
+        */
+       addr[4] = capab;
+       len[4] = encr - capab;
+
+       crypt_len = skb->data + skb->len - encr;
+       skb_put(skb, AES_BLOCK_SIZE);
+       return aes_siv_encrypt(assoc_data->fils_kek, assoc_data->fils_kek_len,
+                              encr, crypt_len, 1, addr, len, encr);
+}
+
+int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+                           u8 *frame, size_t *frame_len,
+                           struct ieee80211_mgd_assoc_data *assoc_data)
+{
+       struct ieee80211_mgmt *mgmt = (void *)frame;
+       u8 *capab, *ies, *encr;
+       const u8 *addr[5 + 1], *session;
+       size_t len[5 + 1];
+       int res;
+       size_t crypt_len;
+
+       if (*frame_len < 24 + 6)
+               return -EINVAL;
+
+       capab = (u8 *)&mgmt->u.assoc_resp.capab_info;
+       ies = mgmt->u.assoc_resp.variable;
+       session = cfg80211_find_ext_ie(WLAN_EID_EXT_FILS_SESSION,
+                                      ies, frame + *frame_len - ies);
+       if (!session || session[1] != 1 + 8) {
+               mlme_dbg(sdata,
+                        "No (valid) FILS Session element in (Re)Association Response frame from %pM",
+                        mgmt->sa);
+               return -EINVAL;
+       }
+       /* decrypt after FILS Session element */
+       encr = (u8 *)session + 2 + 1 + 8;
+
+       /* AES-SIV AAD vectors */
+
+       /* The AP's BSSID */
+       addr[0] = mgmt->sa;
+       len[0] = ETH_ALEN;
+       /* The STA's MAC address */
+       addr[1] = mgmt->da;
+       len[1] = ETH_ALEN;
+       /* The AP's nonce */
+       addr[2] = &assoc_data->fils_nonces[FILS_NONCE_LEN];
+       len[2] = FILS_NONCE_LEN;
+       /* The STA's nonce */
+       addr[3] = assoc_data->fils_nonces;
+       len[3] = FILS_NONCE_LEN;
+       /* The (Re)Association Response frame from the Capability Information
+        * field to the FILS Session element (both inclusive).
+        */
+       addr[4] = capab;
+       len[4] = encr - capab;
+
+       crypt_len = frame + *frame_len - encr;
+       if (crypt_len < AES_BLOCK_SIZE) {
+               mlme_dbg(sdata,
+                        "Not enough room for AES-SIV data after FILS Session element in (Re)Association Response frame from %pM",
+                        mgmt->sa);
+               return -EINVAL;
+       }
+       res = aes_siv_decrypt(assoc_data->fils_kek, assoc_data->fils_kek_len,
+                             encr, crypt_len, 5, addr, len, encr);
+       if (res != 0) {
+               mlme_dbg(sdata,
+                        "AES-SIV decryption of (Re)Association Response frame from %pM failed",
+                        mgmt->sa);
+               return res;
+       }
+       *frame_len -= AES_BLOCK_SIZE;
+       return 0;
+}
diff --git a/net/mac80211/fils_aead.h b/net/mac80211/fils_aead.h
new file mode 100644 (file)
index 0000000..fbc6523
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * FILS AEAD for (Re)Association Request/Response frames
+ * Copyright 2016, Qualcomm Atheros, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef FILS_AEAD_H
+#define FILS_AEAD_H
+
+int fils_encrypt_assoc_req(struct sk_buff *skb,
+                          struct ieee80211_mgd_assoc_data *assoc_data);
+int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+                           u8 *frame, size_t *frame_len,
+                           struct ieee80211_mgd_assoc_data *assoc_data);
+
+#endif /* FILS_AEAD_H */
index 34c2add2c455978936c5379218620d41269a43a6..d37a577f63a1809b3ef56bfa471d46241edd0de5 100644 (file)
@@ -84,6 +84,8 @@ struct ieee80211_local;
 #define IEEE80211_DEFAULT_MAX_SP_LEN           \
        IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
 
+extern const u8 ieee80211_ac_to_qos_mask[IEEE80211_NUM_ACS];
+
 #define IEEE80211_DEAUTH_FRAME_LEN     (24 /* hdr */ + 2 /* reason */)
 
 #define IEEE80211_MAX_NAN_INSTANCE_ID 255
@@ -307,6 +309,7 @@ struct ieee80211_if_vlan {
 
        /* used for all tx if the VLAN is configured to 4-addr mode */
        struct sta_info __rcu *sta;
+       atomic_t num_mcast_sta; /* number of stations receiving multicast */
 };
 
 struct mesh_stats {
@@ -398,6 +401,10 @@ struct ieee80211_mgd_assoc_data {
 
        struct ieee80211_vht_cap ap_vht_cap;
 
+       u8 fils_nonces[2 * FILS_NONCE_LEN];
+       u8 fils_kek[FILS_MAX_KEK_LEN];
+       size_t fils_kek_len;
+
        size_t ie_len;
        u8 ie[];
 };
@@ -442,7 +449,7 @@ struct ieee80211_if_managed {
        struct ieee80211_mgd_auth_data *auth_data;
        struct ieee80211_mgd_assoc_data *assoc_data;
 
-       u8 bssid[ETH_ALEN];
+       u8 bssid[ETH_ALEN] __aligned(2);
 
        u16 aid;
 
@@ -1527,6 +1534,23 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
        return false;
 }
 
+void ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata);
+void ieee80211_vif_dec_num_mcast(struct ieee80211_sub_if_data *sdata);
+
+/* This function returns the number of multicast stations connected to this
+ * interface. It returns -1 if that number is not tracked, that is for netdevs
+ * not in AP or AP_VLAN mode or when using 4addr.
+ */
+static inline int
+ieee80211_vif_get_num_mcast_if(struct ieee80211_sub_if_data *sdata)
+{
+       if (sdata->vif.type == NL80211_IFTYPE_AP)
+               return atomic_read(&sdata->u.ap.num_mcast_sta);
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
+               return atomic_read(&sdata->u.vlan.num_mcast_sta);
+       return -1;
+}
+
 u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
                                     struct ieee80211_rx_status *status,
                                     unsigned int mpdu_len,
index 638ec0759078c18ec6816bb9de5abe6f6cb40487..41497b670e2bde0e55a2a35f5fbbdb60148ddd54 100644 (file)
@@ -150,15 +150,6 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
                ieee80211_hw_config(local, change);
 }
 
-static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN)
-               return -EINVAL;
-
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
                                bool check_dup)
 {
@@ -1166,7 +1157,6 @@ static const struct net_device_ops ieee80211_dataif_ops = {
        .ndo_uninit             = ieee80211_uninit,
        .ndo_start_xmit         = ieee80211_subif_start_xmit,
        .ndo_set_rx_mode        = ieee80211_set_multicast_list,
-       .ndo_change_mtu         = ieee80211_change_mtu,
        .ndo_set_mac_address    = ieee80211_change_mac,
        .ndo_select_queue       = ieee80211_netdev_select_queue,
        .ndo_get_stats64        = ieee80211_get_stats64,
@@ -1200,7 +1190,6 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
        .ndo_uninit             = ieee80211_uninit,
        .ndo_start_xmit         = ieee80211_monitor_start_xmit,
        .ndo_set_rx_mode        = ieee80211_set_multicast_list,
-       .ndo_change_mtu         = ieee80211_change_mtu,
        .ndo_set_mac_address    = ieee80211_change_mac,
        .ndo_select_queue       = ieee80211_monitor_select_queue,
        .ndo_get_stats64        = ieee80211_get_stats64,
@@ -1884,6 +1873,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
                netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
 
+               /* MTU range: 256 - 2304 */
+               ndev->min_mtu = 256;
+               ndev->max_mtu = IEEE80211_MAX_DATA_LEN;
+
                ret = register_netdevice(ndev);
                if (ret) {
                        ieee80211_if_free(ndev);
@@ -2005,3 +1998,19 @@ void ieee80211_iface_exit(void)
 {
        unregister_netdevice_notifier(&mac80211_netdev_notifier);
 }
+
+void ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata)
+{
+       if (sdata->vif.type == NL80211_IFTYPE_AP)
+               atomic_inc(&sdata->u.ap.num_mcast_sta);
+       else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               atomic_inc(&sdata->u.vlan.num_mcast_sta);
+}
+
+void ieee80211_vif_dec_num_mcast(struct ieee80211_sub_if_data *sdata)
+{
+       if (sdata->vif.type == NL80211_IFTYPE_AP)
+               atomic_dec(&sdata->u.ap.num_mcast_sta);
+       else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               atomic_dec(&sdata->u.vlan.num_mcast_sta);
+}
index 1075ac24c8c5f433690749970d9e27393351caa9..1822c77f2b1c3125ec1bc63fa6b7de085a26bbed 100644 (file)
@@ -549,6 +549,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
                           NL80211_FEATURE_MAC_ON_CREATE |
                           NL80211_FEATURE_USERSPACE_MPM |
                           NL80211_FEATURE_FULL_AP_CLIENT_STATE;
+       wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
 
        if (!ops->hw_scan)
                wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
@@ -821,6 +822,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
             !local->ops->tdls_recv_channel_switch))
                return -EOPNOTSUPP;
 
+       if (WARN_ON(ieee80211_hw_check(hw, SUPPORTS_TX_FRAG) &&
+                   !local->ops->set_frag_threshold))
+               return -EINVAL;
+
        if (WARN_ON(local->hw.wiphy->interface_modes &
                        BIT(NL80211_IFTYPE_NAN) &&
                    (!local->ops->start_nan || !local->ops->stop_nan)))
index 7486f2dab4ba70ade0b2faf48ffa7f3880ac2ad4..d157b250ff7710088dfeee928045f2612e8c5464 100644 (file)
@@ -30,6 +30,7 @@
 #include "driver-ops.h"
 #include "rate.h"
 #include "led.h"
+#include "fils_aead.h"
 
 #define IEEE80211_AUTH_TIMEOUT         (HZ / 5)
 #define IEEE80211_AUTH_TIMEOUT_LONG    (HZ / 2)
@@ -652,6 +653,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                        2 + sizeof(struct ieee80211_ht_cap) + /* HT */
                        2 + sizeof(struct ieee80211_vht_cap) + /* VHT */
                        assoc_data->ie_len + /* extra IEs */
+                       (assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) +
                        9, /* WMM */
                        GFP_KERNEL);
        if (!skb)
@@ -875,6 +877,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                memcpy(pos, assoc_data->ie + offset, noffset - offset);
        }
 
+       if (assoc_data->fils_kek_len &&
+           fils_encrypt_assoc_req(skb, assoc_data) < 0) {
+               dev_kfree_skb(skb);
+               return;
+       }
+
        drv_mgd_prepare_tx(local, sdata);
 
        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
@@ -2618,6 +2626,9 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
        case WLAN_AUTH_LEAP:
        case WLAN_AUTH_FT:
        case WLAN_AUTH_SAE:
+       case WLAN_AUTH_FILS_SK:
+       case WLAN_AUTH_FILS_SK_PFS:
+       case WLAN_AUTH_FILS_PK:
                break;
        case WLAN_AUTH_SHARED_KEY:
                if (ifmgd->auth_data->expected_transaction != 4) {
@@ -3143,6 +3154,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                   reassoc ? "Rea" : "A", mgmt->sa,
                   capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
 
+       if (assoc_data->fils_kek_len &&
+           fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0)
+               return;
+
        pos = mgmt->u.assoc_resp.variable;
        ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
 
@@ -3193,7 +3208,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                uapsd_queues = 0;
                for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
                        if (sdata->tx_conf[ac].uapsd)
-                               uapsd_queues |= BIT(ac);
+                               uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
        }
 
        cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len, uapsd_queues);
@@ -4479,24 +4494,36 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        case NL80211_AUTHTYPE_SAE:
                auth_alg = WLAN_AUTH_SAE;
                break;
+       case NL80211_AUTHTYPE_FILS_SK:
+               auth_alg = WLAN_AUTH_FILS_SK;
+               break;
+       case NL80211_AUTHTYPE_FILS_SK_PFS:
+               auth_alg = WLAN_AUTH_FILS_SK_PFS;
+               break;
+       case NL80211_AUTHTYPE_FILS_PK:
+               auth_alg = WLAN_AUTH_FILS_PK;
+               break;
        default:
                return -EOPNOTSUPP;
        }
 
-       auth_data = kzalloc(sizeof(*auth_data) + req->sae_data_len +
+       auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
                            req->ie_len, GFP_KERNEL);
        if (!auth_data)
                return -ENOMEM;
 
        auth_data->bss = req->bss;
 
-       if (req->sae_data_len >= 4) {
-               __le16 *pos = (__le16 *) req->sae_data;
-               auth_data->sae_trans = le16_to_cpu(pos[0]);
-               auth_data->sae_status = le16_to_cpu(pos[1]);
-               memcpy(auth_data->data, req->sae_data + 4,
-                      req->sae_data_len - 4);
-               auth_data->data_len += req->sae_data_len - 4;
+       if (req->auth_data_len >= 4) {
+               if (req->auth_type == NL80211_AUTHTYPE_SAE) {
+                       __le16 *pos = (__le16 *) req->auth_data;
+
+                       auth_data->sae_trans = le16_to_cpu(pos[0]);
+                       auth_data->sae_status = le16_to_cpu(pos[1]);
+               }
+               memcpy(auth_data->data, req->auth_data + 4,
+                      req->auth_data_len - 4);
+               auth_data->data_len += req->auth_data_len - 4;
        }
 
        if (req->ie && req->ie_len) {
@@ -4692,6 +4719,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
                assoc_data->ie_len = req->ie_len;
        }
 
+       if (req->fils_kek) {
+               /* should already be checked in cfg80211 - so warn */
+               if (WARN_ON(req->fils_kek_len > FILS_MAX_KEK_LEN)) {
+                       err = -EINVAL;
+                       goto err_free;
+               }
+               memcpy(assoc_data->fils_kek, req->fils_kek,
+                      req->fils_kek_len);
+               assoc_data->fils_kek_len = req->fils_kek_len;
+       }
+
+       if (req->fils_nonces)
+               memcpy(assoc_data->fils_nonces, req->fils_nonces,
+                      2 * FILS_NONCE_LEN);
+
        assoc_data->bss = req->bss;
 
        if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
index a47bbc973f2dbc629aa8ab6ed91c928784cd26c6..eeab7250f4b978bd2af2b320ae8f430ab00cc81d 100644 (file)
@@ -1394,13 +1394,15 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid)
        u8 ac = ieee802_1d_to_ac[tid & 7];
 
        /*
-        * If this AC is not trigger-enabled do nothing.
+        * If this AC is not trigger-enabled do nothing unless the
+        * driver is calling us after it already checked.
         *
         * NB: This could/should check a separate bitmap of trigger-
         * enabled queues, but for now we only implement uAPSD w/o
         * TSPEC changes to the ACs, so they're always the same.
         */
-       if (!(sta->sta.uapsd_queues & BIT(ac)))
+       if (!(sta->sta.uapsd_queues & ieee80211_ac_to_qos_mask[ac]) &&
+           tid != IEEE80211_NUM_TIDS)
                return;
 
        /* if we are in a service period, do nothing */
@@ -2215,7 +2217,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
             sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
            !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
            (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
-               if (is_multicast_ether_addr(ehdr->h_dest)) {
+               if (is_multicast_ether_addr(ehdr->h_dest) &&
+                   ieee80211_vif_get_num_mcast_if(sdata) != 0) {
                        /*
                         * send multicast frames both to higher layers in
                         * local net stack and back to the wireless medium
@@ -2224,7 +2227,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
                        if (!xmit_skb)
                                net_info_ratelimited("%s: failed to clone multicast frame\n",
                                                    dev->name);
-               } else {
+               } else if (!is_multicast_ether_addr(ehdr->h_dest)) {
                        dsta = sta_info_get(sdata, skb->data);
                        if (dsta) {
                                /*
index 78e9ecbc96e616d0f90228abb5bcda59147ea73f..236d47e76ced4f625039f063258deee20f6536ca 100644 (file)
@@ -709,7 +709,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                unsigned long tids;
 
-               if (ignore_for_tim & BIT(ac))
+               if (ignore_for_tim & ieee80211_ac_to_qos_mask[ac])
                        continue;
 
                indicate_tim |= !skb_queue_empty(&sta->tx_filtered[ac]) ||
@@ -1389,7 +1389,7 @@ ieee80211_sta_ps_more_data(struct sta_info *sta, u8 ignored_acs,
                return true;
 
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-               if (ignored_acs & BIT(ac))
+               if (ignored_acs & ieee80211_ac_to_qos_mask[ac])
                        continue;
 
                if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
@@ -1414,7 +1414,7 @@ ieee80211_sta_ps_get_frames(struct sta_info *sta, int n_frames, u8 ignored_acs,
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                unsigned long tids;
 
-               if (ignored_acs & BIT(ac))
+               if (ignored_acs & ieee80211_ac_to_qos_mask[ac])
                        continue;
 
                tids = ieee80211_tids_for_ac(ac);
@@ -1482,7 +1482,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
                        BIT(find_highest_prio_tid(driver_release_tids));
 
        if (skb_queue_empty(&frames) && !driver_release_tids) {
-               int tid;
+               int tid, ac;
 
                /*
                 * For PS-Poll, this can only happen due to a race condition
@@ -1500,7 +1500,10 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
                 */
 
                /* This will evaluate to 1, 3, 5 or 7. */
-               tid = 7 - ((ffs(~ignored_acs) - 1) << 1);
+               for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++)
+                       if (ignored_acs & BIT(ac))
+                               continue;
+               tid = 7 - 2 * ac;
 
                ieee80211_send_null_response(sta, tid, reason, true, false);
        } else if (!driver_release_tids) {
@@ -1871,10 +1874,7 @@ int sta_info_move_state(struct sta_info *sta,
                        if (!sta->sta.support_p2p_ps)
                                ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
                } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
-                       if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
-                           (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-                            !sta->sdata->u.vlan.sta))
-                               atomic_dec(&sta->sdata->bss->num_mcast_sta);
+                       ieee80211_vif_dec_num_mcast(sta->sdata);
                        clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
                        ieee80211_clear_fast_xmit(sta);
                        ieee80211_clear_fast_rx(sta);
@@ -1882,10 +1882,7 @@ int sta_info_move_state(struct sta_info *sta,
                break;
        case IEEE80211_STA_AUTHORIZED:
                if (sta->sta_state == IEEE80211_STA_ASSOC) {
-                       if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
-                           (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-                            !sta->sdata->u.vlan.sta))
-                               atomic_inc(&sta->sdata->bss->num_mcast_sta);
+                       ieee80211_vif_inc_num_mcast(sta->sdata);
                        set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
                        ieee80211_check_fast_xmit(sta);
                        ieee80211_check_fast_rx(sta);
index ed5fcb984a01a51ce08caa32101b50265509eb3f..dd06ef0b88614566ea4eb751a314856d38fb0e39 100644 (file)
@@ -184,7 +184,6 @@ struct tid_ampdu_tx {
  * @ssn: Starting Sequence Number expected to be aggregated.
  * @buf_size: buffer size for incoming A-MPDUs
  * @timeout: reset timer value (in TUs).
- * @dialog_token: dialog token for aggregation session
  * @rcu_head: RCU head used for freeing this struct
  * @reorder_lock: serializes access to reorder buffer, see below.
  * @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and
@@ -213,7 +212,6 @@ struct tid_ampdu_rx {
        u16 ssn;
        u16 buf_size;
        u16 timeout;
-       u8 dialog_token;
        bool auto_seq;
        bool removed;
 };
@@ -225,6 +223,7 @@ struct tid_ampdu_rx {
  *     to tid_tx[idx], which are protected by the sta spinlock)
  *     tid_start_tx is also protected by sta->lock.
  * @tid_rx: aggregation info for Rx per TID -- RCU protected
+ * @tid_rx_token: dialog tokens for valid aggregation sessions
  * @tid_rx_timer_expired: bitmap indicating on which TIDs the
  *     RX timer expired until the work for it runs
  * @tid_rx_stop_requested:  bitmap indicating which BA sessions per TID the
@@ -243,6 +242,7 @@ struct sta_ampdu_mlme {
        struct mutex mtx;
        /* rx */
        struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS];
+       u8 tid_rx_token[IEEE80211_NUM_TIDS];
        unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
        unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
        unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
index 1c56abc496272bb58d71639975e4706c266f2066..62ccaf6f585d02198b997411dc622fc433b8a242 100644 (file)
@@ -331,9 +331,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
                        I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
                        return TX_DROP;
                }
-       } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP &&
-                           ieee80211_is_data(hdr->frame_control) &&
-                           !atomic_read(&tx->sdata->u.ap.num_mcast_sta))) {
+       } else if (unlikely(ieee80211_is_data(hdr->frame_control) &&
+                           ieee80211_vif_get_num_mcast_if(tx->sdata) == 0)) {
                /*
                 * No associated STAs - no need to send multicast
                 * frames.
@@ -935,7 +934,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
        if (info->flags & IEEE80211_TX_CTL_DONTFRAG)
                return TX_CONTINUE;
 
-       if (tx->local->ops->set_frag_threshold)
+       if (ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG))
                return TX_CONTINUE;
 
        /*
@@ -2801,7 +2800,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
 
        /* fast-xmit doesn't handle fragmentation at all */
        if (local->hw.wiphy->frag_threshold != (u32)-1 &&
-           !local->ops->set_frag_threshold)
+           !ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG))
                goto out;
 
        rcu_read_lock();
@@ -3060,11 +3059,12 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_hdr *hdr;
-       struct ethhdr amsdu_hdr;
+       struct ethhdr *amsdu_hdr;
        int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
        int subframe_len = skb->len - hdr_len;
        void *data;
-       u8 *qc;
+       u8 *qc, *h_80211_src, *h_80211_dst;
+       const u8 *bssid;
 
        if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
                return false;
@@ -3072,19 +3072,44 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
        if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
                return true;
 
-       if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(amsdu_hdr),
+       if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr),
                                         &subframe_len))
                return false;
 
-       amsdu_hdr.h_proto = cpu_to_be16(subframe_len);
-       memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN);
-       memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN);
+       data = skb_push(skb, sizeof(*amsdu_hdr));
+       memmove(data, data + sizeof(*amsdu_hdr), hdr_len);
+       hdr = data;
+       amsdu_hdr = data + hdr_len;
+       /* h_80211_src/dst is addr* field within hdr */
+       h_80211_src = data + fast_tx->sa_offs;
+       h_80211_dst = data + fast_tx->da_offs;
+
+       amsdu_hdr->h_proto = cpu_to_be16(subframe_len);
+       ether_addr_copy(amsdu_hdr->h_source, h_80211_src);
+       ether_addr_copy(amsdu_hdr->h_dest, h_80211_dst);
+
+       /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA
+        * fields needs to be changed to BSSID for A-MSDU frames depending
+        * on FromDS/ToDS values.
+        */
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_STATION:
+               bssid = sdata->u.mgd.bssid;
+               break;
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_AP_VLAN:
+               bssid = sdata->vif.addr;
+               break;
+       default:
+               bssid = NULL;
+       }
 
-       data = skb_push(skb, sizeof(amsdu_hdr));
-       memmove(data, data + sizeof(amsdu_hdr), hdr_len);
-       memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr));
+       if (bssid && ieee80211_has_fromds(hdr->frame_control))
+               ether_addr_copy(h_80211_src, bssid);
+
+       if (bssid && ieee80211_has_tods(hdr->frame_control))
+               ether_addr_copy(h_80211_dst, bssid);
 
-       hdr = data;
        qc = ieee80211_get_qos_ctl(hdr);
        *qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
 
index 545c79a42a779b949fe4cd62afee7e36685d358c..ac59fbd280dff8f712fb9dbc841147e4642ec607 100644 (file)
@@ -3308,10 +3308,11 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_sub_if_data *sdata_iter;
        enum nl80211_iftype iftype = sdata->wdev.iftype;
-       int num[NUM_NL80211_IFTYPES];
        struct ieee80211_chanctx *ctx;
-       int num_different_channels = 0;
        int total = 1;
+       struct iface_combination_params params = {
+               .radar_detect = radar_detect,
+       };
 
        lockdep_assert_held(&local->chanctx_mtx);
 
@@ -3322,12 +3323,19 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
                    !chandef->chan))
                return -EINVAL;
 
-       if (chandef)
-               num_different_channels = 1;
-
        if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
                return -EINVAL;
 
+       if (sdata->vif.type == NL80211_IFTYPE_AP ||
+           sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
+               /*
+                * always passing this is harmless, since it'll be the
+                * same value that cfg80211 finds if it finds the same
+                * interface ... and that's always allowed
+                */
+               params.new_beacon_int = sdata->vif.bss_conf.beacon_int;
+       }
+
        /* Always allow software iftypes */
        if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
                if (radar_detect)
@@ -3335,24 +3343,26 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
                return 0;
        }
 
-       memset(num, 0, sizeof(num));
+       if (chandef)
+               params.num_different_channels = 1;
 
        if (iftype != NL80211_IFTYPE_UNSPECIFIED)
-               num[iftype] = 1;
+               params.iftype_num[iftype] = 1;
 
        list_for_each_entry(ctx, &local->chanctx_list, list) {
                if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
                        continue;
-               radar_detect |= ieee80211_chanctx_radar_detect(local, ctx);
+               params.radar_detect |=
+                       ieee80211_chanctx_radar_detect(local, ctx);
                if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
-                       num_different_channels++;
+                       params.num_different_channels++;
                        continue;
                }
                if (chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
                    cfg80211_chandef_compatible(chandef,
                                                &ctx->conf.def))
                        continue;
-               num_different_channels++;
+               params.num_different_channels++;
        }
 
        list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) {
@@ -3365,16 +3375,14 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
                    local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
                        continue;
 
-               num[wdev_iter->iftype]++;
+               params.iftype_num[wdev_iter->iftype]++;
                total++;
        }
 
-       if (total == 1 && !radar_detect)
+       if (total == 1 && !params.radar_detect)
                return 0;
 
-       return cfg80211_check_combinations(local->hw.wiphy,
-                                          num_different_channels,
-                                          radar_detect, num);
+       return cfg80211_check_combinations(local->hw.wiphy, &params);
 }
 
 static void
@@ -3390,12 +3398,10 @@ ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c,
 int ieee80211_max_num_channels(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
-       int num[NUM_NL80211_IFTYPES] = {};
        struct ieee80211_chanctx *ctx;
-       int num_different_channels = 0;
-       u8 radar_detect = 0;
        u32 max_num_different_channels = 1;
        int err;
+       struct iface_combination_params params = {0};
 
        lockdep_assert_held(&local->chanctx_mtx);
 
@@ -3403,17 +3409,17 @@ int ieee80211_max_num_channels(struct ieee80211_local *local)
                if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
                        continue;
 
-               num_different_channels++;
+               params.num_different_channels++;
 
-               radar_detect |= ieee80211_chanctx_radar_detect(local, ctx);
+               params.radar_detect |=
+                       ieee80211_chanctx_radar_detect(local, ctx);
        }
 
        list_for_each_entry_rcu(sdata, &local->interfaces, list)
-               num[sdata->wdev.iftype]++;
+               params.iftype_num[sdata->wdev.iftype]++;
 
-       err = cfg80211_iter_combinations(local->hw.wiphy,
-                                        num_different_channels, radar_detect,
-                                        num, ieee80211_iter_max_chans,
+       err = cfg80211_iter_combinations(local->hw.wiphy, &params,
+                                        ieee80211_iter_max_chans,
                                         &max_num_different_channels);
        if (err < 0)
                return err;
@@ -3456,3 +3462,10 @@ void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
                *byte_cnt = txqi->tin.backlog_bytes + frag_bytes;
 }
 EXPORT_SYMBOL(ieee80211_txq_get_depth);
+
+const u8 ieee80211_ac_to_qos_mask[IEEE80211_NUM_ACS] = {
+       IEEE80211_WMM_IE_STA_QOSINFO_AC_VO,
+       IEEE80211_WMM_IE_STA_QOSINFO_AC_VI,
+       IEEE80211_WMM_IE_STA_QOSINFO_AC_BE,
+       IEEE80211_WMM_IE_STA_QOSINFO_AC_BK
+};
index 9eb0aee9105b398b442380315ec758a430a103b1..3e3d3014e9ab6d026a13232ce6cb930b9fc87093 100644 (file)
@@ -236,26 +236,35 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_hdr *hdr = (void *)skb->data;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+       u8 flags;
        u8 *p;
-       u8 ack_policy, tid;
 
        if (!ieee80211_is_data_qos(hdr->frame_control))
                return;
 
        p = ieee80211_get_qos_ctl(hdr);
-       tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
 
-       /* preserve EOSP bit */
-       ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
+       /* set up the first byte */
+
+       /*
+        * preserve everything but the TID and ACK policy
+        * (which we both write here)
+        */
+       flags = *p & ~(IEEE80211_QOS_CTL_TID_MASK |
+                      IEEE80211_QOS_CTL_ACK_POLICY_MASK);
 
        if (is_multicast_ether_addr(hdr->addr1) ||
            sdata->noack_map & BIT(tid)) {
-               ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
+               flags |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
                info->flags |= IEEE80211_TX_CTL_NO_ACK;
        }
 
-       /* qos header is 2 bytes */
-       *p++ = ack_policy | tid;
+       *p = flags | tid;
+
+       /* set up the second byte */
+       p++;
+
        if (ieee80211_vif_is_mesh(&sdata->vif)) {
                /* preserve RSPI and Mesh PS Level bit */
                *p &= ((IEEE80211_QOS_CTL_RSPI |
index 42ce9bd4426f17aed0b6b50d6298cc01a950b05f..8af6dd388d1195540fdaf66f7ac55a452620ad5f 100644 (file)
@@ -57,7 +57,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
 
        if (info->control.hw_key &&
            (info->flags & IEEE80211_TX_CTL_DONTFRAG ||
-            tx->local->ops->set_frag_threshold) &&
+            ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG)) &&
            !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
                /* hwaccel - with no need for SW-generated MMIC */
                return TX_CONTINUE;
index cf52cf30ac4b505bf1b10545de2fb9d588943731..2f7ccd93441671d6aac3fd690cfc61283848579a 100644 (file)
@@ -133,7 +133,6 @@ static int mpls_build_state(struct net_device *dev, struct nlattr *nla,
        struct mpls_iptunnel_encap *tun_encap_info;
        struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1];
        struct lwtunnel_state *newts;
-       int tun_encap_info_len;
        int ret;
 
        ret = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla,
@@ -144,13 +143,11 @@ static int mpls_build_state(struct net_device *dev, struct nlattr *nla,
        if (!tb[MPLS_IPTUNNEL_DST])
                return -EINVAL;
 
-       tun_encap_info_len = sizeof(*tun_encap_info);
 
-       newts = lwtunnel_state_alloc(tun_encap_info_len);
+       newts = lwtunnel_state_alloc(sizeof(*tun_encap_info));
        if (!newts)
                return -ENOMEM;
 
-       newts->len = tun_encap_info_len;
        tun_encap_info = mpls_lwtunnel_encap(newts);
        ret = nla_get_labels(tb[MPLS_IPTUNNEL_DST], MAX_NEW_LABELS,
                             &tun_encap_info->labels, tun_encap_info->label);
index c3c809b2e7122daabac5b45ffed67979e0fecb28..6b85ded4f91d44abf0917cb74f259015fd8394c1 100644 (file)
@@ -2840,14 +2840,7 @@ static struct nf_sockopt_ops ip_vs_sockopts = {
  */
 
 /* IPVS genetlink family */
-static struct genl_family ip_vs_genl_family = {
-       .id             = GENL_ID_GENERATE,
-       .hdrsize        = 0,
-       .name           = IPVS_GENL_NAME,
-       .version        = IPVS_GENL_VERSION,
-       .maxattr        = IPVS_CMD_MAX,
-       .netnsok        = true,         /* Make ipvsadm to work on netns */
-};
+static struct genl_family ip_vs_genl_family;
 
 /* Policy used for first-level command attributes */
 static const struct nla_policy ip_vs_cmd_policy[IPVS_CMD_ATTR_MAX + 1] = {
@@ -3872,10 +3865,20 @@ static const struct genl_ops ip_vs_genl_ops[] = {
        },
 };
 
+static struct genl_family ip_vs_genl_family __ro_after_init = {
+       .hdrsize        = 0,
+       .name           = IPVS_GENL_NAME,
+       .version        = IPVS_GENL_VERSION,
+       .maxattr        = IPVS_CMD_MAX,
+       .netnsok        = true,         /* Make ipvsadm to work on netns */
+       .module         = THIS_MODULE,
+       .ops            = ip_vs_genl_ops,
+       .n_ops          = ARRAY_SIZE(ip_vs_genl_ops),
+};
+
 static int __init ip_vs_genl_register(void)
 {
-       return genl_register_family_with_ops(&ip_vs_genl_family,
-                                            ip_vs_genl_ops);
+       return genl_register_family(&ip_vs_genl_family);
 }
 
 static void ip_vs_genl_unregister(void)
index 2ec93c5e77bb07ce82ccb4d1ff8418660960d06c..d177dd0665043652c199605479959ea408145a4b 100644 (file)
@@ -60,13 +60,7 @@ struct netlbl_domhsh_walk_arg {
 };
 
 /* NetLabel Generic NETLINK CALIPSO family */
-static struct genl_family netlbl_calipso_gnl_family = {
-       .id = GENL_ID_GENERATE,
-       .hdrsize = 0,
-       .name = NETLBL_NLTYPE_CALIPSO_NAME,
-       .version = NETLBL_PROTO_VERSION,
-       .maxattr = NLBL_CALIPSO_A_MAX,
-};
+static struct genl_family netlbl_calipso_gnl_family;
 
 /* NetLabel Netlink attribute policy */
 static const struct nla_policy calipso_genl_policy[NLBL_CALIPSO_A_MAX + 1] = {
@@ -355,6 +349,16 @@ static const struct genl_ops netlbl_calipso_ops[] = {
        },
 };
 
+static struct genl_family netlbl_calipso_gnl_family __ro_after_init = {
+       .hdrsize = 0,
+       .name = NETLBL_NLTYPE_CALIPSO_NAME,
+       .version = NETLBL_PROTO_VERSION,
+       .maxattr = NLBL_CALIPSO_A_MAX,
+       .module = THIS_MODULE,
+       .ops = netlbl_calipso_ops,
+       .n_ops = ARRAY_SIZE(netlbl_calipso_ops),
+};
+
 /* NetLabel Generic NETLINK Protocol Functions
  */
 
@@ -368,8 +372,7 @@ static const struct genl_ops netlbl_calipso_ops[] = {
  */
 int __init netlbl_calipso_genl_init(void)
 {
-       return genl_register_family_with_ops(&netlbl_calipso_gnl_family,
-                                            netlbl_calipso_ops);
+       return genl_register_family(&netlbl_calipso_gnl_family);
 }
 
 static const struct netlbl_calipso_ops *calipso_ops;
index 7fd1104ba9007ec0d731d97d0a245eb3da7b4436..4149d3e6358976f093dbcb25dee79d10f6275231 100644 (file)
@@ -59,14 +59,7 @@ struct netlbl_domhsh_walk_arg {
 };
 
 /* NetLabel Generic NETLINK CIPSOv4 family */
-static struct genl_family netlbl_cipsov4_gnl_family = {
-       .id = GENL_ID_GENERATE,
-       .hdrsize = 0,
-       .name = NETLBL_NLTYPE_CIPSOV4_NAME,
-       .version = NETLBL_PROTO_VERSION,
-       .maxattr = NLBL_CIPSOV4_A_MAX,
-};
-
+static struct genl_family netlbl_cipsov4_gnl_family;
 /* NetLabel Netlink attribute policy */
 static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
        [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
@@ -767,6 +760,16 @@ static const struct genl_ops netlbl_cipsov4_ops[] = {
        },
 };
 
+static struct genl_family netlbl_cipsov4_gnl_family __ro_after_init = {
+       .hdrsize = 0,
+       .name = NETLBL_NLTYPE_CIPSOV4_NAME,
+       .version = NETLBL_PROTO_VERSION,
+       .maxattr = NLBL_CIPSOV4_A_MAX,
+       .module = THIS_MODULE,
+       .ops = netlbl_cipsov4_ops,
+       .n_ops = ARRAY_SIZE(netlbl_cipsov4_ops),
+};
+
 /*
  * NetLabel Generic NETLINK Protocol Functions
  */
@@ -781,6 +784,5 @@ static const struct genl_ops netlbl_cipsov4_ops[] = {
  */
 int __init netlbl_cipsov4_genl_init(void)
 {
-       return genl_register_family_with_ops(&netlbl_cipsov4_gnl_family,
-                                            netlbl_cipsov4_ops);
+       return genl_register_family(&netlbl_cipsov4_gnl_family);
 }
index f85d0e07af2dd9c7f4f4fb2f6b05fcf99b21c8eb..21e0095b1d1422aff42e068490819fd3ac540c58 100644 (file)
@@ -60,13 +60,7 @@ struct netlbl_domhsh_walk_arg {
 };
 
 /* NetLabel Generic NETLINK CIPSOv4 family */
-static struct genl_family netlbl_mgmt_gnl_family = {
-       .id = GENL_ID_GENERATE,
-       .hdrsize = 0,
-       .name = NETLBL_NLTYPE_MGMT_NAME,
-       .version = NETLBL_PROTO_VERSION,
-       .maxattr = NLBL_MGMT_A_MAX,
-};
+static struct genl_family netlbl_mgmt_gnl_family;
 
 /* NetLabel Netlink attribute policy */
 static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
@@ -834,6 +828,16 @@ static const struct genl_ops netlbl_mgmt_genl_ops[] = {
        },
 };
 
+static struct genl_family netlbl_mgmt_gnl_family __ro_after_init = {
+       .hdrsize = 0,
+       .name = NETLBL_NLTYPE_MGMT_NAME,
+       .version = NETLBL_PROTO_VERSION,
+       .maxattr = NLBL_MGMT_A_MAX,
+       .module = THIS_MODULE,
+       .ops = netlbl_mgmt_genl_ops,
+       .n_ops = ARRAY_SIZE(netlbl_mgmt_genl_ops),
+};
+
 /*
  * NetLabel Generic NETLINK Protocol Functions
  */
@@ -848,6 +852,5 @@ static const struct genl_ops netlbl_mgmt_genl_ops[] = {
  */
 int __init netlbl_mgmt_genl_init(void)
 {
-       return genl_register_family_with_ops(&netlbl_mgmt_gnl_family,
-                                            netlbl_mgmt_genl_ops);
+       return genl_register_family(&netlbl_mgmt_gnl_family);
 }
index 4528cff9138b5499f7577bf2801dac8f85e0fcda..22dc1b9d63625e76c72bdb80b97b1d07540fac32 100644 (file)
@@ -123,13 +123,7 @@ static struct netlbl_unlhsh_iface __rcu *netlbl_unlhsh_def;
 static u8 netlabel_unlabel_acceptflg;
 
 /* NetLabel Generic NETLINK unlabeled family */
-static struct genl_family netlbl_unlabel_gnl_family = {
-       .id = GENL_ID_GENERATE,
-       .hdrsize = 0,
-       .name = NETLBL_NLTYPE_UNLABELED_NAME,
-       .version = NETLBL_PROTO_VERSION,
-       .maxattr = NLBL_UNLABEL_A_MAX,
-};
+static struct genl_family netlbl_unlabel_gnl_family;
 
 /* NetLabel Netlink attribute policy */
 static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
@@ -1378,6 +1372,16 @@ static const struct genl_ops netlbl_unlabel_genl_ops[] = {
        },
 };
 
+static struct genl_family netlbl_unlabel_gnl_family __ro_after_init = {
+       .hdrsize = 0,
+       .name = NETLBL_NLTYPE_UNLABELED_NAME,
+       .version = NETLBL_PROTO_VERSION,
+       .maxattr = NLBL_UNLABEL_A_MAX,
+       .module = THIS_MODULE,
+       .ops = netlbl_unlabel_genl_ops,
+       .n_ops = ARRAY_SIZE(netlbl_unlabel_genl_ops),
+};
+
 /*
  * NetLabel Generic NETLINK Protocol Functions
  */
@@ -1392,8 +1396,7 @@ static const struct genl_ops netlbl_unlabel_genl_ops[] = {
  */
 int __init netlbl_unlabel_genl_init(void)
 {
-       return genl_register_family_with_ops(&netlbl_unlabel_gnl_family,
-                                            netlbl_unlabel_genl_ops);
+       return genl_register_family(&netlbl_unlabel_gnl_family);
 }
 
 /*
index 23cc12639ba769ac67714f5e5f5f9549a4417c38..caf04d70ba71941ab8309caf6efeca5c8f41e55e 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/mutex.h>
 #include <linux/bitmap.h>
 #include <linux/rwsem.h>
+#include <linux/idr.h>
 #include <net/sock.h>
 #include <net/genetlink.h>
 
@@ -58,10 +59,8 @@ static void genl_unlock_all(void)
        up_write(&cb_lock);
 }
 
-#define GENL_FAM_TAB_SIZE      16
-#define GENL_FAM_TAB_MASK      (GENL_FAM_TAB_SIZE - 1)
+static DEFINE_IDR(genl_fam_idr);
 
-static struct list_head family_ht[GENL_FAM_TAB_SIZE];
 /*
  * Bitmap of multicast groups that are currently in use.
  *
@@ -86,45 +85,29 @@ static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
 static unsigned long *mc_groups = &mc_group_start;
 static unsigned long mc_groups_longs = 1;
 
-static int genl_ctrl_event(int event, struct genl_family *family,
+static int genl_ctrl_event(int event, const struct genl_family *family,
                           const struct genl_multicast_group *grp,
                           int grp_id);
 
-static inline unsigned int genl_family_hash(unsigned int id)
+static const struct genl_family *genl_family_find_byid(unsigned int id)
 {
-       return id & GENL_FAM_TAB_MASK;
+       return idr_find(&genl_fam_idr, id);
 }
 
-static inline struct list_head *genl_family_chain(unsigned int id)
+static const struct genl_family *genl_family_find_byname(char *name)
 {
-       return &family_ht[genl_family_hash(id)];
-}
-
-static struct genl_family *genl_family_find_byid(unsigned int id)
-{
-       struct genl_family *f;
+       const struct genl_family *family;
+       unsigned int id;
 
-       list_for_each_entry(f, genl_family_chain(id), family_list)
-               if (f->id == id)
-                       return f;
+       idr_for_each_entry(&genl_fam_idr, family, id)
+               if (strcmp(family->name, name) == 0)
+                       return family;
 
        return NULL;
 }
 
-static struct genl_family *genl_family_find_byname(char *name)
-{
-       struct genl_family *f;
-       int i;
-
-       for (i = 0; i < GENL_FAM_TAB_SIZE; i++)
-               list_for_each_entry(f, genl_family_chain(i), family_list)
-                       if (strcmp(f->name, name) == 0)
-                               return f;
-
-       return NULL;
-}
-
-static const struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family)
+static const struct genl_ops *genl_get_cmd(u8 cmd,
+                                          const struct genl_family *family)
 {
        int i;
 
@@ -135,26 +118,6 @@ static const struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family)
        return NULL;
 }
 
-/* Of course we are going to have problems once we hit
- * 2^16 alive types, but that can only happen by year 2K
-*/
-static u16 genl_generate_id(void)
-{
-       static u16 id_gen_idx = GENL_MIN_ID;
-       int i;
-
-       for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
-               if (id_gen_idx != GENL_ID_VFS_DQUOT &&
-                   id_gen_idx != GENL_ID_PMCRAID &&
-                   !genl_family_find_byid(id_gen_idx))
-                       return id_gen_idx;
-               if (++id_gen_idx > GENL_MAX_ID)
-                       id_gen_idx = GENL_MIN_ID;
-       }
-
-       return 0;
-}
-
 static int genl_allocate_reserve_groups(int n_groups, int *first_id)
 {
        unsigned long *new_groups;
@@ -295,7 +258,7 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
        return err;
 }
 
-static void genl_unregister_mc_groups(struct genl_family *family)
+static void genl_unregister_mc_groups(const struct genl_family *family)
 {
        struct net *net;
        int i;
@@ -344,28 +307,21 @@ static int genl_validate_ops(const struct genl_family *family)
 }
 
 /**
- * __genl_register_family - register a generic netlink family
+ * genl_register_family - register a generic netlink family
  * @family: generic netlink family
  *
  * Registers the specified family after validating it first. Only one
  * family may be registered with the same family name or identifier.
- * The family id may equal GENL_ID_GENERATE causing an unique id to
- * be automatically generated and assigned.
  *
- * The family's ops array must already be assigned, you can use the
- * genl_register_family_with_ops() helper function.
+ * The family's ops, multicast groups and module pointer must already
+ * be assigned.
  *
  * Return 0 on success or a negative error code.
  */
-int __genl_register_family(struct genl_family *family)
+int genl_register_family(struct genl_family *family)
 {
-       int err = -EINVAL, i;
-
-       if (family->id && family->id < GENL_MIN_ID)
-               goto errout;
-
-       if (family->id > GENL_MAX_ID)
-               goto errout;
+       int err, i;
+       int start = GENL_START_ALLOC, end = GENL_MAX_ID;
 
        err = genl_validate_ops(family);
        if (err)
@@ -378,18 +334,20 @@ int __genl_register_family(struct genl_family *family)
                goto errout_locked;
        }
 
-       if (family->id == GENL_ID_GENERATE) {
-               u16 newid = genl_generate_id();
-
-               if (!newid) {
-                       err = -ENOMEM;
-                       goto errout_locked;
-               }
-
-               family->id = newid;
-       } else if (genl_family_find_byid(family->id)) {
-               err = -EEXIST;
-               goto errout_locked;
+       /*
+        * Sadly, a few cases need to be special-cased
+        * due to them having previously abused the API
+        * and having used their family ID also as their
+        * multicast group ID, so we use reserved IDs
+        * for both to be sure we can do that mapping.
+        */
+       if (family == &genl_ctrl) {
+               /* and this needs to be special for initial family lookups */
+               start = end = GENL_ID_CTRL;
+       } else if (strcmp(family->name, "pmcraid") == 0) {
+               start = end = GENL_ID_PMCRAID;
+       } else if (strcmp(family->name, "VFS_DQUOT") == 0) {
+               start = end = GENL_ID_VFS_DQUOT;
        }
 
        if (family->maxattr && !family->parallel_ops) {
@@ -402,11 +360,15 @@ int __genl_register_family(struct genl_family *family)
        } else
                family->attrbuf = NULL;
 
+       family->id = idr_alloc(&genl_fam_idr, family,
+                              start, end + 1, GFP_KERNEL);
+       if (!family->id)
+               goto errout_locked;
+
        err = genl_validate_assign_mc_groups(family);
        if (err)
-               goto errout_locked;
+               goto errout_remove;
 
-       list_add_tail(&family->family_list, genl_family_chain(family->id));
        genl_unlock_all();
 
        /* send all events */
@@ -417,12 +379,13 @@ int __genl_register_family(struct genl_family *family)
 
        return 0;
 
+errout_remove:
+       idr_remove(&genl_fam_idr, family->id);
 errout_locked:
        genl_unlock_all();
-errout:
        return err;
 }
-EXPORT_SYMBOL(__genl_register_family);
+EXPORT_SYMBOL(genl_register_family);
 
 /**
  * genl_unregister_family - unregister generic netlink family
@@ -432,33 +395,29 @@ EXPORT_SYMBOL(__genl_register_family);
  *
  * Returns 0 on success or a negative error code.
  */
-int genl_unregister_family(struct genl_family *family)
+int genl_unregister_family(const struct genl_family *family)
 {
-       struct genl_family *rc;
-
        genl_lock_all();
 
-       list_for_each_entry(rc, genl_family_chain(family->id), family_list) {
-               if (family->id != rc->id || strcmp(rc->name, family->name))
-                       continue;
+       if (!genl_family_find_byid(family->id)) {
+               genl_unlock_all();
+               return -ENOENT;
+       }
 
-               genl_unregister_mc_groups(family);
+       genl_unregister_mc_groups(family);
 
-               list_del(&rc->family_list);
-               family->n_ops = 0;
-               up_write(&cb_lock);
-               wait_event(genl_sk_destructing_waitq,
-                          atomic_read(&genl_sk_destructing_cnt) == 0);
-               genl_unlock();
+       idr_remove(&genl_fam_idr, family->id);
 
-               kfree(family->attrbuf);
-               genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
-               return 0;
-       }
+       up_write(&cb_lock);
+       wait_event(genl_sk_destructing_waitq,
+                  atomic_read(&genl_sk_destructing_cnt) == 0);
+       genl_unlock();
 
-       genl_unlock_all();
+       kfree(family->attrbuf);
+
+       genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
 
-       return -ENOENT;
+       return 0;
 }
 EXPORT_SYMBOL(genl_unregister_family);
 
@@ -474,7 +433,7 @@ EXPORT_SYMBOL(genl_unregister_family);
  * Returns pointer to user specific header
  */
 void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
-                               struct genl_family *family, int flags, u8 cmd)
+                 const struct genl_family *family, int flags, u8 cmd)
 {
        struct nlmsghdr *nlh;
        struct genlmsghdr *hdr;
@@ -533,7 +492,7 @@ static int genl_lock_done(struct netlink_callback *cb)
        return rc;
 }
 
-static int genl_family_rcv_msg(struct genl_family *family,
+static int genl_family_rcv_msg(const struct genl_family *family,
                               struct sk_buff *skb,
                               struct nlmsghdr *nlh)
 {
@@ -645,7 +604,7 @@ out:
 
 static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
-       struct genl_family *family;
+       const struct genl_family *family;
        int err;
 
        family = genl_family_find_byid(nlh->nlmsg_type);
@@ -674,15 +633,9 @@ static void genl_rcv(struct sk_buff *skb)
  * Controller
  **************************************************************************/
 
-static struct genl_family genl_ctrl = {
-       .id = GENL_ID_CTRL,
-       .name = "nlctrl",
-       .version = 0x2,
-       .maxattr = CTRL_ATTR_MAX,
-       .netnsok = true,
-};
+static struct genl_family genl_ctrl;
 
-static int ctrl_fill_info(struct genl_family *family, u32 portid, u32 seq,
+static int ctrl_fill_info(const struct genl_family *family, u32 portid, u32 seq,
                          u32 flags, struct sk_buff *skb, u8 cmd)
 {
        void *hdr;
@@ -769,7 +722,7 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static int ctrl_fill_mcgrp_info(struct genl_family *family,
+static int ctrl_fill_mcgrp_info(const struct genl_family *family,
                                const struct genl_multicast_group *grp,
                                int grp_id, u32 portid, u32 seq, u32 flags,
                                struct sk_buff *skb, u8 cmd)
@@ -812,37 +765,30 @@ nla_put_failure:
 
 static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
 {
-
-       int i, n = 0;
+       int n = 0;
        struct genl_family *rt;
        struct net *net = sock_net(skb->sk);
-       int chains_to_skip = cb->args[0];
-       int fams_to_skip = cb->args[1];
-
-       for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) {
-               n = 0;
-               list_for_each_entry(rt, genl_family_chain(i), family_list) {
-                       if (!rt->netnsok && !net_eq(net, &init_net))
-                               continue;
-                       if (++n < fams_to_skip)
-                               continue;
-                       if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
-                                          cb->nlh->nlmsg_seq, NLM_F_MULTI,
-                                          skb, CTRL_CMD_NEWFAMILY) < 0)
-                               goto errout;
-               }
+       int fams_to_skip = cb->args[0];
+       unsigned int id;
 
-               fams_to_skip = 0;
-       }
+       idr_for_each_entry(&genl_fam_idr, rt, id) {
+               if (!rt->netnsok && !net_eq(net, &init_net))
+                       continue;
+
+               if (n++ < fams_to_skip)
+                       continue;
 
-errout:
-       cb->args[0] = i;
-       cb->args[1] = n;
+               if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
+                                  cb->nlh->nlmsg_seq, NLM_F_MULTI,
+                                  skb, CTRL_CMD_NEWFAMILY) < 0)
+                       break;
+       }
 
+       cb->args[0] = n;
        return skb->len;
 }
 
-static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,
+static struct sk_buff *ctrl_build_family_msg(const struct genl_family *family,
                                             u32 portid, int seq, u8 cmd)
 {
        struct sk_buff *skb;
@@ -862,7 +808,7 @@ static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,
 }
 
 static struct sk_buff *
-ctrl_build_mcgrp_msg(struct genl_family *family,
+ctrl_build_mcgrp_msg(const struct genl_family *family,
                     const struct genl_multicast_group *grp,
                     int grp_id, u32 portid, int seq, u8 cmd)
 {
@@ -892,7 +838,7 @@ static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
 static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
 {
        struct sk_buff *msg;
-       struct genl_family *res = NULL;
+       const struct genl_family *res = NULL;
        int err = -EINVAL;
 
        if (info->attrs[CTRL_ATTR_FAMILY_ID]) {
@@ -936,7 +882,7 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
        return genlmsg_reply(msg, info);
 }
 
-static int genl_ctrl_event(int event, struct genl_family *family,
+static int genl_ctrl_event(int event, const struct genl_family *family,
                           const struct genl_multicast_group *grp,
                           int grp_id)
 {
@@ -990,27 +936,39 @@ static const struct genl_multicast_group genl_ctrl_groups[] = {
        { .name = "notify", },
 };
 
+static struct genl_family genl_ctrl __ro_after_init = {
+       .module = THIS_MODULE,
+       .ops = genl_ctrl_ops,
+       .n_ops = ARRAY_SIZE(genl_ctrl_ops),
+       .mcgrps = genl_ctrl_groups,
+       .n_mcgrps = ARRAY_SIZE(genl_ctrl_groups),
+       .id = GENL_ID_CTRL,
+       .name = "nlctrl",
+       .version = 0x2,
+       .maxattr = CTRL_ATTR_MAX,
+       .netnsok = true,
+};
+
 static int genl_bind(struct net *net, int group)
 {
-       int i, err = -ENOENT;
+       struct genl_family *f;
+       int err = -ENOENT;
+       unsigned int id;
 
        down_read(&cb_lock);
-       for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
-               struct genl_family *f;
-
-               list_for_each_entry(f, genl_family_chain(i), family_list) {
-                       if (group >= f->mcgrp_offset &&
-                           group < f->mcgrp_offset + f->n_mcgrps) {
-                               int fam_grp = group - f->mcgrp_offset;
-
-                               if (!f->netnsok && net != &init_net)
-                                       err = -ENOENT;
-                               else if (f->mcast_bind)
-                                       err = f->mcast_bind(net, fam_grp);
-                               else
-                                       err = 0;
-                               break;
-                       }
+
+       idr_for_each_entry(&genl_fam_idr, f, id) {
+               if (group >= f->mcgrp_offset &&
+                   group < f->mcgrp_offset + f->n_mcgrps) {
+                       int fam_grp = group - f->mcgrp_offset;
+
+                       if (!f->netnsok && net != &init_net)
+                               err = -ENOENT;
+                       else if (f->mcast_bind)
+                               err = f->mcast_bind(net, fam_grp);
+                       else
+                               err = 0;
+                       break;
                }
        }
        up_read(&cb_lock);
@@ -1020,21 +978,19 @@ static int genl_bind(struct net *net, int group)
 
 static void genl_unbind(struct net *net, int group)
 {
-       int i;
+       struct genl_family *f;
+       unsigned int id;
 
        down_read(&cb_lock);
-       for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
-               struct genl_family *f;
 
-               list_for_each_entry(f, genl_family_chain(i), family_list) {
-                       if (group >= f->mcgrp_offset &&
-                           group < f->mcgrp_offset + f->n_mcgrps) {
-                               int fam_grp = group - f->mcgrp_offset;
+       idr_for_each_entry(&genl_fam_idr, f, id) {
+               if (group >= f->mcgrp_offset &&
+                   group < f->mcgrp_offset + f->n_mcgrps) {
+                       int fam_grp = group - f->mcgrp_offset;
 
-                               if (f->mcast_unbind)
-                                       f->mcast_unbind(net, fam_grp);
-                               break;
-                       }
+                       if (f->mcast_unbind)
+                               f->mcast_unbind(net, fam_grp);
+                       break;
                }
        }
        up_read(&cb_lock);
@@ -1074,13 +1030,9 @@ static struct pernet_operations genl_pernet_ops = {
 
 static int __init genl_init(void)
 {
-       int i, err;
-
-       for (i = 0; i < GENL_FAM_TAB_SIZE; i++)
-               INIT_LIST_HEAD(&family_ht[i]);
+       int err;
 
-       err = genl_register_family_with_ops_groups(&genl_ctrl, genl_ctrl_ops,
-                                                  genl_ctrl_groups);
+       err = genl_register_family(&genl_ctrl);
        if (err < 0)
                goto problem;
 
@@ -1096,6 +1048,25 @@ problem:
 
 subsys_initcall(genl_init);
 
+/**
+ * genl_family_attrbuf - return family's attrbuf
+ * @family: the family
+ *
+ * Return the family's attrbuf, while validating that it's
+ * actually valid to access it.
+ *
+ * You cannot use this function with a family that has parallel_ops
+ * and you can only use it within (pre/post) doit/dumpit callbacks.
+ */
+struct nlattr **genl_family_attrbuf(const struct genl_family *family)
+{
+       if (!WARN_ON(family->parallel_ops))
+               lockdep_assert_held(&genl_mutex);
+
+       return family->attrbuf;
+}
+EXPORT_SYMBOL(genl_family_attrbuf);
+
 static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
                         gfp_t flags)
 {
@@ -1125,8 +1096,9 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
        return err;
 }
 
-int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb,
-                           u32 portid, unsigned int group, gfp_t flags)
+int genlmsg_multicast_allns(const struct genl_family *family,
+                           struct sk_buff *skb, u32 portid,
+                           unsigned int group, gfp_t flags)
 {
        if (WARN_ON_ONCE(group >= family->n_mcgrps))
                return -EINVAL;
@@ -1135,7 +1107,7 @@ int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb,
 }
 EXPORT_SYMBOL(genlmsg_multicast_allns);
 
-void genl_notify(struct genl_family *family, struct sk_buff *skb,
+void genl_notify(const struct genl_family *family, struct sk_buff *skb,
                 struct genl_info *info, u32 group, gfp_t flags)
 {
        struct net *net = genl_info_net(info);
index ea023b35f1c24b3069be02796b24bfad7805352e..03f3d5c7beb8d173fae25456b278ee9cf3e04c5e 100644 (file)
@@ -38,14 +38,7 @@ static const struct genl_multicast_group nfc_genl_mcgrps[] = {
        { .name = NFC_GENL_MCAST_EVENT_NAME, },
 };
 
-static struct genl_family nfc_genl_family = {
-       .id = GENL_ID_GENERATE,
-       .hdrsize = 0,
-       .name = NFC_GENL_NAME,
-       .version = NFC_GENL_VERSION,
-       .maxattr = NFC_ATTR_MAX,
-};
-
+static struct genl_family nfc_genl_family;
 static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
        [NFC_ATTR_DEVICE_INDEX] = { .type = NLA_U32 },
        [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING,
@@ -120,21 +113,20 @@ nla_put_failure:
 
 static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)
 {
+       struct nlattr **attrbuf = genl_family_attrbuf(&nfc_genl_family);
        struct nfc_dev *dev;
        int rc;
        u32 idx;
 
        rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize,
-                        nfc_genl_family.attrbuf,
-                        nfc_genl_family.maxattr,
-                        nfc_genl_policy);
+                        attrbuf, nfc_genl_family.maxattr, nfc_genl_policy);
        if (rc < 0)
                return ERR_PTR(rc);
 
-       if (!nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX])
+       if (!attrbuf[NFC_ATTR_DEVICE_INDEX])
                return ERR_PTR(-EINVAL);
 
-       idx = nla_get_u32(nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX]);
+       idx = nla_get_u32(attrbuf[NFC_ATTR_DEVICE_INDEX]);
 
        dev = nfc_get_device(idx);
        if (!dev)
@@ -1754,6 +1746,18 @@ static const struct genl_ops nfc_genl_ops[] = {
        },
 };
 
+static struct genl_family nfc_genl_family __ro_after_init = {
+       .hdrsize = 0,
+       .name = NFC_GENL_NAME,
+       .version = NFC_GENL_VERSION,
+       .maxattr = NFC_ATTR_MAX,
+       .module = THIS_MODULE,
+       .ops = nfc_genl_ops,
+       .n_ops = ARRAY_SIZE(nfc_genl_ops),
+       .mcgrps = nfc_genl_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(nfc_genl_mcgrps),
+};
+
 
 struct urelease_work {
        struct  work_struct w;
@@ -1839,9 +1843,7 @@ int __init nfc_genl_init(void)
 {
        int rc;
 
-       rc = genl_register_family_with_ops_groups(&nfc_genl_family,
-                                                 nfc_genl_ops,
-                                                 nfc_genl_mcgrps);
+       rc = genl_register_family(&nfc_genl_family);
        if (rc)
                return rc;
 
index 4e03f64709bc023374865b4a3b5839232b71b26f..1105c4e29c6275a002fac3bd9b26ab28bf1565b9 100644 (file)
@@ -62,7 +62,8 @@ struct ovs_frag_data {
        struct vport *vport;
        struct ovs_skb_cb cb;
        __be16 inner_protocol;
-       __u16 vlan_tci;
+       u16 network_offset;     /* valid only for MPLS */
+       u16 vlan_tci;
        __be16 vlan_proto;
        unsigned int l2_len;
        u8 l2_data[MAX_L2_LEN];
@@ -666,6 +667,12 @@ static int ovs_vport_output(struct net *net, struct sock *sk, struct sk_buff *sk
        skb_postpush_rcsum(skb, skb->data, data->l2_len);
        skb_reset_mac_header(skb);
 
+       if (eth_p_mpls(skb->protocol)) {
+               skb->inner_network_header = skb->network_header;
+               skb_set_network_header(skb, data->network_offset);
+               skb_reset_mac_len(skb);
+       }
+
        ovs_vport_send(vport, skb);
        return 0;
 }
@@ -684,7 +691,8 @@ static struct dst_ops ovs_dst_ops = {
 /* prepare_frag() is called once per (larger-than-MTU) frame; its inverse is
  * ovs_vport_output(), which is called once per fragmented packet.
  */
-static void prepare_frag(struct vport *vport, struct sk_buff *skb)
+static void prepare_frag(struct vport *vport, struct sk_buff *skb,
+                        u16 orig_network_offset)
 {
        unsigned int hlen = skb_network_offset(skb);
        struct ovs_frag_data *data;
@@ -694,6 +702,7 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb)
        data->vport = vport;
        data->cb = *OVS_CB(skb);
        data->inner_protocol = skb->inner_protocol;
+       data->network_offset = orig_network_offset;
        data->vlan_tci = skb->vlan_tci;
        data->vlan_proto = skb->vlan_proto;
        data->l2_len = hlen;
@@ -706,6 +715,13 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb)
 static void ovs_fragment(struct net *net, struct vport *vport,
                         struct sk_buff *skb, u16 mru, __be16 ethertype)
 {
+       u16 orig_network_offset = 0;
+
+       if (eth_p_mpls(skb->protocol)) {
+               orig_network_offset = skb_network_offset(skb);
+               skb->network_header = skb->inner_network_header;
+       }
+
        if (skb_network_offset(skb) > MAX_L2_LEN) {
                OVS_NLERR(1, "L2 header too long to fragment");
                goto err;
@@ -715,7 +731,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
                struct dst_entry ovs_dst;
                unsigned long orig_dst;
 
-               prepare_frag(vport, skb);
+               prepare_frag(vport, skb, orig_network_offset);
                dst_init(&ovs_dst, &ovs_dst_ops, NULL, 1,
                         DST_OBSOLETE_NONE, DST_NOCOUNT);
                ovs_dst.dev = vport->dev;
@@ -735,7 +751,7 @@ static void ovs_fragment(struct net *net, struct vport *vport,
                        goto err;
                }
 
-               prepare_frag(vport, skb);
+               prepare_frag(vport, skb, orig_network_offset);
                memset(&ovs_rt, 0, sizeof(ovs_rt));
                dst_init(&ovs_rt.dst, &ovs_dst_ops, NULL, 1,
                         DST_OBSOLETE_NONE, DST_NOCOUNT);
index 4d67ea856067829ab3d7d6395fc52f2ae89d3f79..fa8760176b7d59106ef699c397e1eae432cfc1c0 100644 (file)
@@ -59,7 +59,6 @@
 #include "vport-netdev.h"
 
 int ovs_net_id __read_mostly;
-EXPORT_SYMBOL_GPL(ovs_net_id);
 
 static struct genl_family dp_packet_genl_family;
 static struct genl_family dp_flow_genl_family;
@@ -131,7 +130,6 @@ int lockdep_ovsl_is_held(void)
        else
                return 1;
 }
-EXPORT_SYMBOL_GPL(lockdep_ovsl_is_held);
 #endif
 
 static struct vport *new_vport(const struct vport_parms *);
@@ -672,8 +670,7 @@ static const struct genl_ops dp_packet_genl_ops[] = {
        }
 };
 
-static struct genl_family dp_packet_genl_family = {
-       .id = GENL_ID_GENERATE,
+static struct genl_family dp_packet_genl_family __ro_after_init = {
        .hdrsize = sizeof(struct ovs_header),
        .name = OVS_PACKET_FAMILY,
        .version = OVS_PACKET_VERSION,
@@ -682,6 +679,7 @@ static struct genl_family dp_packet_genl_family = {
        .parallel_ops = true,
        .ops = dp_packet_genl_ops,
        .n_ops = ARRAY_SIZE(dp_packet_genl_ops),
+       .module = THIS_MODULE,
 };
 
 static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats,
@@ -1437,8 +1435,7 @@ static const struct genl_ops dp_flow_genl_ops[] = {
        },
 };
 
-static struct genl_family dp_flow_genl_family = {
-       .id = GENL_ID_GENERATE,
+static struct genl_family dp_flow_genl_family __ro_after_init = {
        .hdrsize = sizeof(struct ovs_header),
        .name = OVS_FLOW_FAMILY,
        .version = OVS_FLOW_VERSION,
@@ -1449,6 +1446,7 @@ static struct genl_family dp_flow_genl_family = {
        .n_ops = ARRAY_SIZE(dp_flow_genl_ops),
        .mcgrps = &ovs_dp_flow_multicast_group,
        .n_mcgrps = 1,
+       .module = THIS_MODULE,
 };
 
 static size_t ovs_dp_cmd_msg_size(void)
@@ -1823,8 +1821,7 @@ static const struct genl_ops dp_datapath_genl_ops[] = {
        },
 };
 
-static struct genl_family dp_datapath_genl_family = {
-       .id = GENL_ID_GENERATE,
+static struct genl_family dp_datapath_genl_family __ro_after_init = {
        .hdrsize = sizeof(struct ovs_header),
        .name = OVS_DATAPATH_FAMILY,
        .version = OVS_DATAPATH_VERSION,
@@ -1835,6 +1832,7 @@ static struct genl_family dp_datapath_genl_family = {
        .n_ops = ARRAY_SIZE(dp_datapath_genl_ops),
        .mcgrps = &ovs_dp_datapath_multicast_group,
        .n_mcgrps = 1,
+       .module = THIS_MODULE,
 };
 
 /* Called with ovs_mutex or RCU read lock. */
@@ -2245,8 +2243,7 @@ static const struct genl_ops dp_vport_genl_ops[] = {
        },
 };
 
-struct genl_family dp_vport_genl_family = {
-       .id = GENL_ID_GENERATE,
+struct genl_family dp_vport_genl_family __ro_after_init = {
        .hdrsize = sizeof(struct ovs_header),
        .name = OVS_VPORT_FAMILY,
        .version = OVS_VPORT_VERSION,
@@ -2257,6 +2254,7 @@ struct genl_family dp_vport_genl_family = {
        .n_ops = ARRAY_SIZE(dp_vport_genl_ops),
        .mcgrps = &ovs_dp_vport_multicast_group,
        .n_mcgrps = 1,
+       .module = THIS_MODULE,
 };
 
 static struct genl_family * const dp_genl_families[] = {
@@ -2274,7 +2272,7 @@ static void dp_unregister_genl(int n_families)
                genl_unregister_family(dp_genl_families[i]);
 }
 
-static int dp_register_genl(void)
+static int __init dp_register_genl(void)
 {
        int err;
        int i;
index e7da29021b38b7a81555d784473f88b7d6e3759d..d5d6caecd0726c1223f78031bbd7f8a00b9ce0f9 100644 (file)
@@ -89,15 +89,6 @@ static const struct ethtool_ops internal_dev_ethtool_ops = {
        .get_link       = ethtool_op_get_link,
 };
 
-static int internal_dev_change_mtu(struct net_device *netdev, int new_mtu)
-{
-       if (new_mtu < 68)
-               return -EINVAL;
-
-       netdev->mtu = new_mtu;
-       return 0;
-}
-
 static void internal_dev_destructor(struct net_device *dev)
 {
        struct vport *vport = ovs_internal_dev_get_vport(dev);
@@ -148,7 +139,6 @@ static const struct net_device_ops internal_dev_netdev_ops = {
        .ndo_stop = internal_dev_stop,
        .ndo_start_xmit = internal_dev_xmit,
        .ndo_set_mac_address = eth_mac_addr,
-       .ndo_change_mtu = internal_dev_change_mtu,
        .ndo_get_stats64 = internal_get_stats,
        .ndo_set_rx_headroom = internal_set_rx_headroom,
 };
index 4e3972344aa6442986f457c12ed6e23fc92f844d..e825753de1e0065944a1e555872efe2198e4f3b0 100644 (file)
@@ -162,7 +162,6 @@ void ovs_netdev_detach_dev(struct vport *vport)
                                netdev_master_upper_dev_get(vport->dev));
        dev_set_promiscuity(vport->dev, -1);
 }
-EXPORT_SYMBOL_GPL(ovs_netdev_detach_dev);
 
 static void netdev_destroy(struct vport *vport)
 {
index 7387418ac514ae0ab679aa1b0d677ddbc9363f7b..9bb85b35a1fbff2f6558417afbb9b2203dabb212 100644 (file)
@@ -463,23 +463,6 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
        ovs_dp_process_packet(skb, &key);
        return 0;
 }
-EXPORT_SYMBOL_GPL(ovs_vport_receive);
-
-static void free_vport_rcu(struct rcu_head *rcu)
-{
-       struct vport *vport = container_of(rcu, struct vport, rcu);
-
-       ovs_vport_free(vport);
-}
-
-void ovs_vport_deferred_free(struct vport *vport)
-{
-       if (!vport)
-               return;
-
-       call_rcu(&vport->rcu, free_vport_rcu);
-}
-EXPORT_SYMBOL_GPL(ovs_vport_deferred_free);
 
 static unsigned int packet_length(const struct sk_buff *skb)
 {
index f01f28a567adb50db4c0a270a50980be39185a43..46e5b69927c72f9cec5c5d32034120ad87439961 100644 (file)
@@ -149,7 +149,6 @@ struct vport_ops {
 struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *,
                              const struct vport_parms *);
 void ovs_vport_free(struct vport *);
-void ovs_vport_deferred_free(struct vport *vport);
 
 #define VPORT_ALIGN 8
 
index fa8237fdc57b26dfc0bbc2253f69e6f6df731afb..21c28b51be9439b20369b48077ac8392db7c3150 100644 (file)
@@ -217,20 +217,10 @@ static netdev_tx_t gprs_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static int gprs_set_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 576) || (new_mtu > (PHONET_MAX_MTU - 11)))
-               return -EINVAL;
-
-       dev->mtu = new_mtu;
-       return 0;
-}
-
 static const struct net_device_ops gprs_netdev_ops = {
        .ndo_open       = gprs_open,
        .ndo_stop       = gprs_close,
        .ndo_start_xmit = gprs_xmit,
-       .ndo_change_mtu = gprs_set_mtu,
 };
 
 static void gprs_setup(struct net_device *dev)
@@ -239,6 +229,8 @@ static void gprs_setup(struct net_device *dev)
        dev->type               = ARPHRD_PHONET_PIPE;
        dev->flags              = IFF_POINTOPOINT | IFF_NOARP;
        dev->mtu                = GPRS_DEFAULT_MTU;
+       dev->min_mtu            = 576;
+       dev->max_mtu            = (PHONET_MAX_MTU - 11);
        dev->hard_header_len    = 0;
        dev->addr_len           = 0;
        dev->tx_queue_len       = 10;
index f5058559bb08c5d7426cc7d5c664478e901ff5d6..13f459dad4ef3c7d34bd1ea38a699e49c25f4534 100644 (file)
@@ -689,21 +689,6 @@ void rds_conn_connect_if_down(struct rds_connection *conn)
 }
 EXPORT_SYMBOL_GPL(rds_conn_connect_if_down);
 
-/*
- * An error occurred on the connection
- */
-void
-__rds_conn_error(struct rds_connection *conn, const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       vprintk(fmt, ap);
-       va_end(ap);
-
-       rds_conn_drop(conn);
-}
-
 void
 __rds_conn_path_error(struct rds_conn_path *cp, const char *fmt, ...)
 {
index 67ba67c058b1b6b8e02631d664c41cac4deaadcc..4121e18624444472f8f3923a888e54405a272954 100644 (file)
@@ -683,10 +683,6 @@ void rds_for_each_conn_info(struct socket *sock, unsigned int len,
                          struct rds_info_lengths *lens,
                          int (*visitor)(struct rds_connection *, void *),
                          size_t item_len);
-__printf(2, 3)
-void __rds_conn_error(struct rds_connection *conn, const char *, ...);
-#define rds_conn_error(conn, fmt...) \
-       __rds_conn_error(conn, KERN_WARNING "RDS: " fmt)
 
 __printf(2, 3)
 void __rds_conn_path_error(struct rds_conn_path *cp, const char *, ...);
index e42df11bf30a63870f509c69656176091ec8aa66..e36e333a0aa0d7430c852ce419ac7ed85094bbec 100644 (file)
@@ -171,8 +171,7 @@ void rds_connect_worker(struct work_struct *work)
                                                     RDS_CONN_DOWN))
                                rds_queue_reconnect(cp);
                        else
-                               rds_conn_path_error(cp,
-                                                   "RDS: connect failed\n");
+                               rds_conn_path_error(cp, "connect failed\n");
                }
        }
 }
index 1d3960033f61d0f72d5039ba31ff1c8dc91d7cba..9ff06cfbcdec9756a42d8076710405c586b21f48 100644 (file)
@@ -226,9 +226,7 @@ static int tcf_bpf_init_from_efd(struct nlattr **tb, struct tcf_bpf_cfg *cfg)
                return PTR_ERR(fp);
 
        if (tb[TCA_ACT_BPF_NAME]) {
-               name = kmemdup(nla_data(tb[TCA_ACT_BPF_NAME]),
-                              nla_len(tb[TCA_ACT_BPF_NAME]),
-                              GFP_KERNEL);
+               name = nla_memdup(tb[TCA_ACT_BPF_NAME], GFP_KERNEL);
                if (!name) {
                        bpf_prog_put(fp);
                        return -ENOMEM;
index 6b07fba5770b2fd0997eef25be5ea2e2803b54ca..6073a11327251cb2baa312ff8a9bab3f94f47e5a 100644 (file)
 static LIST_HEAD(mirred_list);
 static DEFINE_SPINLOCK(mirred_list_lock);
 
+static bool tcf_mirred_is_act_redirect(int action)
+{
+       return action == TCA_EGRESS_REDIR || action == TCA_INGRESS_REDIR;
+}
+
+static u32 tcf_mirred_act_direction(int action)
+{
+       switch (action) {
+       case TCA_EGRESS_REDIR:
+       case TCA_EGRESS_MIRROR:
+               return AT_EGRESS;
+       case TCA_INGRESS_REDIR:
+       case TCA_INGRESS_MIRROR:
+               return AT_INGRESS;
+       default:
+               BUG();
+       }
+}
+
 static void tcf_mirred_release(struct tc_action *a, int bind)
 {
        struct tcf_mirred *m = to_mirred(a);
@@ -54,17 +73,32 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
 static int mirred_net_id;
 static struct tc_action_ops act_mirred_ops;
 
+static bool dev_is_mac_header_xmit(const struct net_device *dev)
+{
+       switch (dev->type) {
+       case ARPHRD_TUNNEL:
+       case ARPHRD_TUNNEL6:
+       case ARPHRD_SIT:
+       case ARPHRD_IPGRE:
+       case ARPHRD_VOID:
+       case ARPHRD_NONE:
+               return false;
+       }
+       return true;
+}
+
 static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                           struct nlattr *est, struct tc_action **a, int ovr,
                           int bind)
 {
        struct tc_action_net *tn = net_generic(net, mirred_net_id);
        struct nlattr *tb[TCA_MIRRED_MAX + 1];
+       bool mac_header_xmit = false;
        struct tc_mirred *parm;
        struct tcf_mirred *m;
        struct net_device *dev;
-       int ret, ok_push = 0;
        bool exists = false;
+       int ret;
 
        if (nla == NULL)
                return -EINVAL;
@@ -82,6 +116,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
        switch (parm->eaction) {
        case TCA_EGRESS_MIRROR:
        case TCA_EGRESS_REDIR:
+       case TCA_INGRESS_REDIR:
+       case TCA_INGRESS_MIRROR:
                break;
        default:
                if (exists)
@@ -95,19 +131,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                                tcf_hash_release(*a, bind);
                        return -ENODEV;
                }
-               switch (dev->type) {
-               case ARPHRD_TUNNEL:
-               case ARPHRD_TUNNEL6:
-               case ARPHRD_SIT:
-               case ARPHRD_IPGRE:
-               case ARPHRD_VOID:
-               case ARPHRD_NONE:
-                       ok_push = 0;
-                       break;
-               default:
-                       ok_push = 1;
-                       break;
-               }
+               mac_header_xmit = dev_is_mac_header_xmit(dev);
        } else {
                dev = NULL;
        }
@@ -136,7 +160,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                        dev_put(rcu_dereference_protected(m->tcfm_dev, 1));
                dev_hold(dev);
                rcu_assign_pointer(m->tcfm_dev, dev);
-               m->tcfm_ok_push = ok_push;
+               m->tcfm_mac_header_xmit = mac_header_xmit;
        }
 
        if (ret == ACT_P_CREATED) {
@@ -153,15 +177,20 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
                      struct tcf_result *res)
 {
        struct tcf_mirred *m = to_mirred(a);
+       bool m_mac_header_xmit;
        struct net_device *dev;
        struct sk_buff *skb2;
-       int retval, err;
+       int retval, err = 0;
+       int m_eaction;
+       int mac_len;
        u32 at;
 
        tcf_lastuse_update(&m->tcf_tm);
        bstats_cpu_update(this_cpu_ptr(m->common.cpu_bstats), skb);
 
        rcu_read_lock();
+       m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
+       m_eaction = READ_ONCE(m->tcfm_eaction);
        retval = READ_ONCE(m->tcf_action);
        dev = rcu_dereference(m->tcfm_dev);
        if (unlikely(!dev)) {
@@ -180,23 +209,36 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
        if (!skb2)
                goto out;
 
-       if (!(at & AT_EGRESS)) {
-               if (m->tcfm_ok_push)
+       /* If action's target direction differs than filter's direction,
+        * and devices expect a mac header on xmit, then mac push/pull is
+        * needed.
+        */
+       if (at != tcf_mirred_act_direction(m_eaction) && m_mac_header_xmit) {
+               if (at & AT_EGRESS) {
+                       /* caught at egress, act ingress: pull mac */
+                       mac_len = skb_network_header(skb) - skb_mac_header(skb);
+                       skb_pull_rcsum(skb2, mac_len);
+               } else {
+                       /* caught at ingress, act egress: push mac */
                        skb_push_rcsum(skb2, skb->mac_len);
+               }
        }
 
        /* mirror is always swallowed */
-       if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
+       if (tcf_mirred_is_act_redirect(m_eaction))
                skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
 
        skb2->skb_iif = skb->dev->ifindex;
        skb2->dev = dev;
-       err = dev_queue_xmit(skb2);
+       if (tcf_mirred_act_direction(m_eaction) & AT_EGRESS)
+               err = dev_queue_xmit(skb2);
+       else
+               err = netif_receive_skb(skb2);
 
        if (err) {
 out:
                qstats_overlimit_inc(this_cpu_ptr(m->common.cpu_qstats));
-               if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
+               if (tcf_mirred_is_act_redirect(m_eaction))
                        retval = TC_ACT_SHOT;
        }
        rcu_read_unlock();
index a133dcb821323c45e03360b26977f292c5d50d09..024f3a3afeff62e9edb625f45a83f5b2f61a7e54 100644 (file)
@@ -46,8 +46,10 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
        if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
            skb->dev->real_num_tx_queues > d->queue_mapping)
                skb_set_queue_mapping(skb, d->queue_mapping);
-       if (d->flags & SKBEDIT_F_MARK)
-               skb->mark = d->mark;
+       if (d->flags & SKBEDIT_F_MARK) {
+               skb->mark &= ~d->mask;
+               skb->mark |= d->mark & d->mask;
+       }
        if (d->flags & SKBEDIT_F_PTYPE)
                skb->pkt_type = d->ptype;
 
@@ -61,6 +63,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
        [TCA_SKBEDIT_QUEUE_MAPPING]     = { .len = sizeof(u16) },
        [TCA_SKBEDIT_MARK]              = { .len = sizeof(u32) },
        [TCA_SKBEDIT_PTYPE]             = { .len = sizeof(u16) },
+       [TCA_SKBEDIT_MASK]              = { .len = sizeof(u32) },
 };
 
 static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
@@ -71,7 +74,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
        struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
        struct tc_skbedit *parm;
        struct tcf_skbedit *d;
-       u32 flags = 0, *priority = NULL, *mark = NULL;
+       u32 flags = 0, *priority = NULL, *mark = NULL, *mask = NULL;
        u16 *queue_mapping = NULL, *ptype = NULL;
        bool exists = false;
        int ret = 0, err;
@@ -108,6 +111,11 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                mark = nla_data(tb[TCA_SKBEDIT_MARK]);
        }
 
+       if (tb[TCA_SKBEDIT_MASK] != NULL) {
+               flags |= SKBEDIT_F_MASK;
+               mask = nla_data(tb[TCA_SKBEDIT_MASK]);
+       }
+
        parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
 
        exists = tcf_hash_check(tn, parm->index, a, bind);
@@ -145,6 +153,10 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                d->mark = *mark;
        if (flags & SKBEDIT_F_PTYPE)
                d->ptype = *ptype;
+       /* default behaviour is to use all the bits */
+       d->mask = 0xffffffff;
+       if (flags & SKBEDIT_F_MASK)
+               d->mask = *mask;
 
        d->tcf_action = parm->action;
 
@@ -182,6 +194,9 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
        if ((d->flags & SKBEDIT_F_PTYPE) &&
            nla_put_u16(skb, TCA_SKBEDIT_PTYPE, d->ptype))
                goto nla_put_failure;
+       if ((d->flags & SKBEDIT_F_MASK) &&
+           nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask))
+               goto nla_put_failure;
 
        tcf_tm_dump(&t, &d->tcf_tm);
        if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD))
index bb1d5a487081f21f80a3042cd424cf7caedf6b37..52dc85acca7d3ba2acb8a0c9213595da7d2a7aab 100644 (file)
@@ -369,9 +369,7 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
                return PTR_ERR(fp);
 
        if (tb[TCA_BPF_NAME]) {
-               name = kmemdup(nla_data(tb[TCA_BPF_NAME]),
-                              nla_len(tb[TCA_BPF_NAME]),
-                              GFP_KERNEL);
+               name = nla_memdup(tb[TCA_BPF_NAME], GFP_KERNEL);
                if (!name) {
                        bpf_prog_put(fp);
                        return -ENOMEM;
index a309a07ccb3535453ce3235d3e6a91933282fc3f..41c80b6c39063afb726dac0b6f52022f82b25fa9 100644 (file)
@@ -176,11 +176,12 @@ META_COLLECTOR(int_vlan_tag)
 {
        unsigned short tag;
 
-       tag = skb_vlan_tag_get(skb);
-       if (!tag && __vlan_get_tag(skb, &tag))
-               *err = -1;
-       else
+       if (skb_vlan_tag_present(skb))
+               dst->value = skb_vlan_tag_get(skb);
+       else if (!__vlan_get_tag(skb, &tag))
                dst->value = tag;
+       else
+               *err = -1;
 }
 
 
index c798d0de8a9daf067cae2485ad6bfeeac039efb0..9926fe4f3b6f7db9aeba22fbbfae3d47c4e2af60 100644 (file)
@@ -1145,7 +1145,7 @@ htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
 
        if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
                                  d, NULL, &cl->bstats) < 0 ||
-           gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 ||
+           gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
            gnet_stats_copy_queue(d, NULL, &qs, qlen) < 0)
                return -1;
 
index 2cd9b4478b92f40f922a2aad2c9b58b891527194..b0196366d58dd751972d65baf32b071745826088 100644 (file)
@@ -418,9 +418,6 @@ static int teql_master_mtu(struct net_device *dev, int new_mtu)
        struct teql_master *m = netdev_priv(dev);
        struct Qdisc *q;
 
-       if (new_mtu < 68)
-               return -EINVAL;
-
        q = m->slaves;
        if (q) {
                do {
@@ -460,6 +457,8 @@ static __init void teql_master_setup(struct net_device *dev)
        dev->netdev_ops =       &teql_netdev_ops;
        dev->type               = ARPHRD_VOID;
        dev->mtu                = 1500;
+       dev->min_mtu            = 68;
+       dev->max_mtu            = 65535;
        dev->tx_queue_len       = 100;
        dev->flags              = IFF_NOARP;
        dev->hard_header_len    = LL_MAX_HEADER;
index 7a1cdf43e49d26b3b12ff35a903a4389753ee3fc..615f0ddd41dfb1ff46a9d4e564716de8e7b60ea6 100644 (file)
@@ -52,7 +52,6 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg)
        atomic_set(&msg->refcnt, 1);
        msg->send_failed = 0;
        msg->send_error = 0;
-       msg->can_abandon = 0;
        msg->can_delay = 1;
        msg->expires_at = 0;
        INIT_LIST_HEAD(&msg->chunks);
@@ -182,20 +181,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
        /* Note: Calculate this outside of the loop, so that all fragments
         * have the same expiration.
         */
-       if (sinfo->sinfo_timetolive) {
-               /* sinfo_timetolive is in milliseconds */
+       if (asoc->peer.prsctp_capable && sinfo->sinfo_timetolive &&
+           (SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags) ||
+            !SCTP_PR_POLICY(sinfo->sinfo_flags)))
                msg->expires_at = jiffies +
                                    msecs_to_jiffies(sinfo->sinfo_timetolive);
-               msg->can_abandon = 1;
-
-               pr_debug("%s: msg:%p expires_at:%ld jiffies:%ld\n", __func__,
-                        msg, msg->expires_at, jiffies);
-       }
-
-       if (asoc->peer.prsctp_capable &&
-           SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags))
-               msg->expires_at =
-                       jiffies + msecs_to_jiffies(sinfo->sinfo_timetolive);
 
        /* This is the biggest possible DATA chunk that can fit into
         * the packet
@@ -354,18 +344,8 @@ errout:
 /* Check whether this message has expired. */
 int sctp_chunk_abandoned(struct sctp_chunk *chunk)
 {
-       if (!chunk->asoc->peer.prsctp_capable ||
-           !SCTP_PR_POLICY(chunk->sinfo.sinfo_flags)) {
-               struct sctp_datamsg *msg = chunk->msg;
-
-               if (!msg->can_abandon)
-                       return 0;
-
-               if (time_after(jiffies, msg->expires_at))
-                       return 1;
-
+       if (!chunk->asoc->peer.prsctp_capable)
                return 0;
-       }
 
        if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
            time_after(jiffies, chunk->msg->expires_at)) {
@@ -378,6 +358,10 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
                   chunk->sent_count > chunk->sinfo.sinfo_timetolive) {
                chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
                return 1;
+       } else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) &&
+                  chunk->msg->expires_at &&
+                  time_after(jiffies, chunk->msg->expires_at)) {
+               return 1;
        }
        /* PRIO policy is processed by sendmsg, not here */
 
index 6cb0df859195ecea93105e396e43f181e53f2e79..7b50e430748576cc64754b4a89aeb4cd1ba73960 100644 (file)
@@ -558,7 +558,8 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
                                 * for a given destination transport address.
                                 */
 
-                               if (!chunk->resent && !tp->rto_pending) {
+                               if (!sctp_chunk_retransmitted(chunk) &&
+                                   !tp->rto_pending) {
                                        chunk->rtt_in_progress = 1;
                                        tp->rto_pending = 1;
                                }
@@ -871,9 +872,6 @@ static void sctp_packet_append_data(struct sctp_packet *packet,
                rwnd = 0;
 
        asoc->peer.rwnd = rwnd;
-       /* Has been accepted for transmission. */
-       if (!asoc->peer.prsctp_capable)
-               chunk->msg->can_abandon = 0;
        sctp_chunk_assign_tsn(chunk);
        sctp_chunk_assign_ssn(chunk);
 }
index 582585393d35ea43d69a85f836d5d6d864ccad4e..e54082699520ae40d8ab4c282c230f3b3787db92 100644 (file)
@@ -507,8 +507,6 @@ void sctp_retransmit_mark(struct sctp_outq *q,
                                transport->rto_pending = 0;
                        }
 
-                       chunk->resent = 1;
-
                        /* Move the chunk to the retransmit queue. The chunks
                         * on the retransmit queue are always kept in order.
                         */
@@ -1439,7 +1437,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                                 * instance).
                                 */
                                if (!tchunk->tsn_gap_acked &&
-                                   !tchunk->resent &&
+                                   !sctp_chunk_retransmitted(tchunk) &&
                                    tchunk->rtt_in_progress) {
                                        tchunk->rtt_in_progress = 0;
                                        rtt = jiffies - tchunk->sent_at;
index 57625f64efd56edaa65fe0940aaa7979fe65ef87..e2a55dc787e641144fcf4613a3e6abfb55909b50 100644 (file)
@@ -39,6 +39,7 @@
 #include <net/checksum.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
+#include <net/udp.h>
 #include <net/tcp.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
@@ -129,6 +130,18 @@ static void svc_release_skb(struct svc_rqst *rqstp)
        }
 }
 
+static void svc_release_udp_skb(struct svc_rqst *rqstp)
+{
+       struct sk_buff *skb = rqstp->rq_xprt_ctxt;
+
+       if (skb) {
+               rqstp->rq_xprt_ctxt = NULL;
+
+               dprintk("svc: service %p, releasing skb %p\n", rqstp, skb);
+               consume_skb(skb);
+       }
+}
+
 union svc_pktinfo_u {
        struct in_pktinfo pkti;
        struct in6_pktinfo pkti6;
@@ -575,7 +588,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
                        goto out_free;
                }
                local_bh_enable();
-               skb_free_datagram_locked(svsk->sk_sk, skb);
+               consume_skb(skb);
        } else {
                /* we can use it in-place */
                rqstp->rq_arg.head[0].iov_base = skb->data;
@@ -602,8 +615,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
 
        return len;
 out_free:
-       trace_kfree_skb(skb, svc_udp_recvfrom);
-       skb_free_datagram_locked(svsk->sk_sk, skb);
+       kfree_skb(skb);
        return 0;
 }
 
@@ -660,7 +672,7 @@ static struct svc_xprt_ops svc_udp_ops = {
        .xpo_create = svc_udp_create,
        .xpo_recvfrom = svc_udp_recvfrom,
        .xpo_sendto = svc_udp_sendto,
-       .xpo_release_rqst = svc_release_skb,
+       .xpo_release_rqst = svc_release_udp_skb,
        .xpo_detach = svc_sock_detach,
        .xpo_free = svc_sock_free,
        .xpo_prep_reply_hdr = svc_udp_prep_reply_hdr,
index 0137af1c0916cdf25547f89ed20b62588fc5c0b2..1758665d609caec0763ff6898e11dea4ed9cf963 100644 (file)
@@ -1083,7 +1083,7 @@ static void xs_udp_data_receive(struct sock_xprt *transport)
                skb = skb_recv_datagram(sk, 0, 1, &err);
                if (skb != NULL) {
                        xs_udp_data_read_skb(&transport->xprt, sk, skb);
-                       skb_free_datagram_locked(sk, skb);
+                       consume_skb(skb);
                        continue;
                }
                if (!test_and_clear_bit(XPRT_SOCK_DATA_READY, &transport->sock_state))
index 3b95fe980fa27e8cf97bedac9b7b46e7f8fe4e2d..017801f9dbaae28ff3bd411af3fce3a84da6c90d 100644 (file)
@@ -624,13 +624,10 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
 int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
                             struct switchdev_notifier_info *info)
 {
-       int err;
-
        ASSERT_RTNL();
 
        info->dev = dev;
-       err = raw_notifier_call_chain(&switchdev_notif_chain, val, info);
-       return err;
+       return raw_notifier_call_chain(&switchdev_notif_chain, val, info);
 }
 EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
 
index 3200059d14b2b60b1e5728bc2f5bd00c59d35f4b..26ca8dd64ded64407db8ef885f8dbb6edd30e4b8 100644 (file)
@@ -135,15 +135,6 @@ const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = {
 /* Users of the legacy API (tipc-config) can't handle that we add operations,
  * so we have a separate genl handling for the new API.
  */
-struct genl_family tipc_genl_family = {
-       .id             = GENL_ID_GENERATE,
-       .name           = TIPC_GENL_V2_NAME,
-       .version        = TIPC_GENL_V2_VERSION,
-       .hdrsize        = 0,
-       .maxattr        = TIPC_NLA_MAX,
-       .netnsok        = true,
-};
-
 static const struct genl_ops tipc_genl_v2_ops[] = {
        {
                .cmd    = TIPC_NL_BEARER_DISABLE,
@@ -258,23 +249,33 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
 #endif
 };
 
+struct genl_family tipc_genl_family __ro_after_init = {
+       .name           = TIPC_GENL_V2_NAME,
+       .version        = TIPC_GENL_V2_VERSION,
+       .hdrsize        = 0,
+       .maxattr        = TIPC_NLA_MAX,
+       .netnsok        = true,
+       .module         = THIS_MODULE,
+       .ops            = tipc_genl_v2_ops,
+       .n_ops          = ARRAY_SIZE(tipc_genl_v2_ops),
+};
+
 int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr)
 {
        u32 maxattr = tipc_genl_family.maxattr;
 
-       *attr = tipc_genl_family.attrbuf;
+       *attr = genl_family_attrbuf(&tipc_genl_family);
        if (!*attr)
                return -EOPNOTSUPP;
 
        return nlmsg_parse(nlh, GENL_HDRLEN, *attr, maxattr, tipc_nl_policy);
 }
 
-int tipc_netlink_start(void)
+int __init tipc_netlink_start(void)
 {
        int res;
 
-       res = genl_register_family_with_ops(&tipc_genl_family,
-                                           tipc_genl_v2_ops);
+       res = genl_register_family(&tipc_genl_family);
        if (res) {
                pr_err("Failed to register netlink interface\n");
                return res;
index 1fd4647647650b75f17f41d19d288be7abe436a3..e1ae8a8a2b8eacf93224cc332fff4a537d8d1ab0 100644 (file)
@@ -1215,15 +1215,6 @@ send:
        return err;
 }
 
-static struct genl_family tipc_genl_compat_family = {
-       .id             = GENL_ID_GENERATE,
-       .name           = TIPC_GENL_NAME,
-       .version        = TIPC_GENL_VERSION,
-       .hdrsize        = TIPC_GENL_HDRLEN,
-       .maxattr        = 0,
-       .netnsok        = true,
-};
-
 static struct genl_ops tipc_genl_compat_ops[] = {
        {
                .cmd            = TIPC_GENL_CMD,
@@ -1231,12 +1222,22 @@ static struct genl_ops tipc_genl_compat_ops[] = {
        },
 };
 
-int tipc_netlink_compat_start(void)
+static struct genl_family tipc_genl_compat_family __ro_after_init = {
+       .name           = TIPC_GENL_NAME,
+       .version        = TIPC_GENL_VERSION,
+       .hdrsize        = TIPC_GENL_HDRLEN,
+       .maxattr        = 0,
+       .netnsok        = true,
+       .module         = THIS_MODULE,
+       .ops            = tipc_genl_compat_ops,
+       .n_ops          = ARRAY_SIZE(tipc_genl_compat_ops),
+};
+
+int __init tipc_netlink_compat_start(void)
 {
        int res;
 
-       res = genl_register_family_with_ops(&tipc_genl_compat_family,
-                                           tipc_genl_compat_ops);
+       res = genl_register_family(&tipc_genl_compat_family);
        if (res) {
                pr_err("Failed to register legacy compat interface\n");
                return res;
index 3f816e2971ee26d97bfb4cd12976d6f67980fce6..5db731512014b3bddaf6f6553a646b7f8204a562 100644 (file)
@@ -572,16 +572,20 @@ struct d_level D_LEVEL[] = {
 size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
 
 
-struct genl_family wimax_gnl_family = {
-       .id = GENL_ID_GENERATE,
+static const struct genl_multicast_group wimax_gnl_mcgrps[] = {
+       { .name = "msg", },
+};
+
+struct genl_family wimax_gnl_family __ro_after_init = {
        .name = "WiMAX",
        .version = WIMAX_GNL_VERSION,
        .hdrsize = 0,
        .maxattr = WIMAX_GNL_ATTR_MAX,
-};
-
-static const struct genl_multicast_group wimax_gnl_mcgrps[] = {
-       { .name = "msg", },
+       .module = THIS_MODULE,
+       .ops = wimax_gnl_ops,
+       .n_ops = ARRAY_SIZE(wimax_gnl_ops),
+       .mcgrps = wimax_gnl_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(wimax_gnl_mcgrps),
 };
 
 
@@ -596,11 +600,7 @@ int __init wimax_subsys_init(void)
        d_parse_params(D_LEVEL, D_LEVEL_SIZE, wimax_debug_params,
                       "wimax.debug");
 
-       snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name),
-                "WiMAX");
-       result = genl_register_family_with_ops_groups(&wimax_gnl_family,
-                                                     wimax_gnl_ops,
-                                                     wimax_gnl_mcgrps);
+       result = genl_register_family(&wimax_gnl_family);
        if (unlikely(result < 0)) {
                pr_err("cannot register generic netlink family: %d\n", result);
                goto error_register_family;
index 8201e6d7449e969182152fcc2641a7e0247b7770..158c59ecf90a35a6af8ca353c7583e0bd0cda807 100644 (file)
@@ -210,11 +210,11 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
                return;
 
-       if (!wdev->p2p_started)
+       if (!wdev_running(wdev))
                return;
 
        rdev_stop_p2p_device(rdev, wdev);
-       wdev->p2p_started = false;
+       wdev->is_running = false;
 
        rdev->opencount--;
 
@@ -233,11 +233,11 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN))
                return;
 
-       if (!wdev->nan_started)
+       if (!wdev_running(wdev))
                return;
 
        rdev_stop_nan(rdev, wdev);
-       wdev->nan_started = false;
+       wdev->is_running = false;
 
        rdev->opencount--;
 }
@@ -562,6 +562,21 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
                                    c->limits[j].max > 1))
                                return -EINVAL;
 
+                       /*
+                        * This isn't well-defined right now. If you have an
+                        * IBSS interface, then its beacon interval may change
+                        * by joining other networks, and nothing prevents it
+                        * from doing that.
+                        * So technically we probably shouldn't even allow AP
+                        * and IBSS in the same interface, but it seems that
+                        * some drivers support that, possibly only with fixed
+                        * beacon intervals for IBSS.
+                        */
+                       if (WARN_ON(types & BIT(NL80211_IFTYPE_ADHOC) &&
+                                   c->beacon_int_min_gcd)) {
+                               return -EINVAL;
+                       }
+
                        cnt += c->limits[j].max;
                        /*
                         * Don't advertise an unsupported type
@@ -571,6 +586,11 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
                                return -EINVAL;
                }
 
+#ifndef CONFIG_WIRELESS_WDS
+               if (WARN_ON(all_iftypes & BIT(NL80211_IFTYPE_WDS)))
+                       return -EINVAL;
+#endif
+
                /* You can't even choose that many! */
                if (WARN_ON(cnt < c->max_interfaces))
                        return -EINVAL;
@@ -609,6 +629,11 @@ int wiphy_register(struct wiphy *wiphy)
                     !rdev->ops->add_nan_func || !rdev->ops->del_nan_func)))
                return -EINVAL;
 
+#ifndef CONFIG_WIRELESS_WDS
+       if (WARN_ON(wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS)))
+               return -EINVAL;
+#endif
+
        /*
         * if a wiphy has unsupported modes for regulatory channel enforcement,
         * opt-out of enforcement checking
index 08d2e948c9ad306a0ed40531efc4103877b9f4ae..fb2fcd5581fed69599e96fe9b02e52ceb8aef6d4 100644 (file)
@@ -345,7 +345,7 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
                       const u8 *ssid, int ssid_len,
                       const u8 *ie, int ie_len,
                       const u8 *key, int key_len, int key_idx,
-                      const u8 *sae_data, int sae_data_len);
+                      const u8 *auth_data, int auth_data_len);
 int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
                        struct net_device *dev,
                        struct ieee80211_channel *chan,
@@ -475,7 +475,7 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
                           u32 *mask);
 
 int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
-                                u32 beacon_int);
+                                enum nl80211_iftype iftype, u32 beacon_int);
 
 void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
                               enum nl80211_iftype iftype, int num);
index fa2066b56f36c469e5686b7bea36a33d58bc13d3..2d8518a37eabc4795e97f7f600f14cdf0f63d7ff 100644 (file)
@@ -183,6 +183,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
                memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
                wdev->mesh_id_len = setup->mesh_id_len;
                wdev->chandef = setup->chandef;
+               wdev->beacon_interval = setup->beacon_interval;
        }
 
        return err;
@@ -258,6 +259,7 @@ int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
        err = rdev_leave_mesh(rdev, dev);
        if (!err) {
                wdev->mesh_id_len = 0;
+               wdev->beacon_interval = 0;
                memset(&wdev->chandef, 0, sizeof(wdev->chandef));
                rdev_set_qos_map(rdev, dev, NULL);
        }
index cbb48e26a8715b8964333bf9b69c52010289bafb..bd1f7a159d6a3e5f29e0a36516144277124cabf1 100644 (file)
@@ -204,14 +204,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
                       const u8 *ssid, int ssid_len,
                       const u8 *ie, int ie_len,
                       const u8 *key, int key_len, int key_idx,
-                      const u8 *sae_data, int sae_data_len)
+                      const u8 *auth_data, int auth_data_len)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_auth_request req = {
                .ie = ie,
                .ie_len = ie_len,
-               .sae_data = sae_data,
-               .sae_data_len = sae_data_len,
+               .auth_data = auth_data,
+               .auth_data_len = auth_data_len,
                .auth_type = auth_type,
                .key = key,
                .key_len = key_len,
index c510810f0b7c14909fc3b83ec31ce6c4ac45dfc2..24ab199ef2fcdcf641f07aaee25bec9e17e43f8e 100644 (file)
@@ -32,22 +32,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
                                   struct cfg80211_crypto_settings *settings,
                                   int cipher_limit);
 
-static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
-                           struct genl_info *info);
-static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
-                             struct genl_info *info);
-
 /* the netlink family */
-static struct genl_family nl80211_fam = {
-       .id = GENL_ID_GENERATE,         /* don't bother with a hardcoded ID */
-       .name = NL80211_GENL_NAME,      /* have users key off the name instead */
-       .hdrsize = 0,                   /* no private header */
-       .version = 1,                   /* no particular meaning now */
-       .maxattr = NL80211_ATTR_MAX,
-       .netnsok = true,
-       .pre_doit = nl80211_pre_doit,
-       .post_doit = nl80211_post_doit,
-};
+static struct genl_family nl80211_fam;
 
 /* multicast groups */
 enum nl80211_multicast_groups {
@@ -357,7 +343,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
        [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
        [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
-       [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
+       [NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, },
        [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
        [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
        [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
@@ -414,6 +400,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_NAN_MASTER_PREF] = { .type = NLA_U8 },
        [NL80211_ATTR_NAN_DUAL] = { .type = NLA_U8 },
        [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
+       [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
+                                   .len = FILS_MAX_KEK_LEN },
+       [NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN },
+       [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
 };
 
 /* policy for the key attributes */
@@ -435,6 +425,7 @@ nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
        [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
 };
 
+#ifdef CONFIG_PM
 /* policy for WoWLAN attributes */
 static const struct nla_policy
 nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
@@ -468,6 +459,7 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
        [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .len = 1 },
        [NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
 };
+#endif /* CONFIG_PM */
 
 /* policy for coalesce rule attributes */
 static const struct nla_policy
@@ -551,13 +543,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
 
        if (!cb->args[0]) {
                err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
-                                 nl80211_fam.attrbuf, nl80211_fam.maxattr,
-                                 nl80211_policy);
+                                 genl_family_attrbuf(&nl80211_fam),
+                                 nl80211_fam.maxattr, nl80211_policy);
                if (err)
                        goto out_unlock;
 
-               *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
-                                                  nl80211_fam.attrbuf);
+               *wdev = __cfg80211_wdev_from_attrs(
+                                       sock_net(skb->sk),
+                                       genl_family_attrbuf(&nl80211_fam));
                if (IS_ERR(*wdev)) {
                        err = PTR_ERR(*wdev);
                        goto out_unlock;
@@ -1075,6 +1068,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
                     nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
                                c->radar_detect_regions)))
                        goto nla_put_failure;
+               if (c->beacon_int_min_gcd &&
+                   nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
+                               c->beacon_int_min_gcd))
+                       goto nla_put_failure;
 
                nla_nest_end(msg, nl_combi);
        }
@@ -1322,6 +1319,95 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg,
        return 0;
 }
 
+#define CMD(op, n)                                                     \
+        do {                                                           \
+               if (rdev->ops->op) {                                    \
+                       i++;                                            \
+                       if (nla_put_u32(msg, i, NL80211_CMD_ ## n))     \
+                               goto nla_put_failure;                   \
+               }                                                       \
+       } while (0)
+
+static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
+                                       struct sk_buff *msg)
+{
+       int i = 0;
+
+       /*
+        * do *NOT* add anything into this function, new things need to be
+        * advertised only to new versions of userspace that can deal with
+        * the split (and they can't possibly care about new features...
+        */
+       CMD(add_virtual_intf, NEW_INTERFACE);
+       CMD(change_virtual_intf, SET_INTERFACE);
+       CMD(add_key, NEW_KEY);
+       CMD(start_ap, START_AP);
+       CMD(add_station, NEW_STATION);
+       CMD(add_mpath, NEW_MPATH);
+       CMD(update_mesh_config, SET_MESH_CONFIG);
+       CMD(change_bss, SET_BSS);
+       CMD(auth, AUTHENTICATE);
+       CMD(assoc, ASSOCIATE);
+       CMD(deauth, DEAUTHENTICATE);
+       CMD(disassoc, DISASSOCIATE);
+       CMD(join_ibss, JOIN_IBSS);
+       CMD(join_mesh, JOIN_MESH);
+       CMD(set_pmksa, SET_PMKSA);
+       CMD(del_pmksa, DEL_PMKSA);
+       CMD(flush_pmksa, FLUSH_PMKSA);
+       if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
+               CMD(remain_on_channel, REMAIN_ON_CHANNEL);
+       CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
+       CMD(mgmt_tx, FRAME);
+       CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
+       if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
+               i++;
+               if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
+                       goto nla_put_failure;
+       }
+       if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
+           rdev->ops->join_mesh) {
+               i++;
+               if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
+                       goto nla_put_failure;
+       }
+       CMD(set_wds_peer, SET_WDS_PEER);
+       if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
+               CMD(tdls_mgmt, TDLS_MGMT);
+               CMD(tdls_oper, TDLS_OPER);
+       }
+       if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
+               CMD(sched_scan_start, START_SCHED_SCAN);
+       CMD(probe_client, PROBE_CLIENT);
+       CMD(set_noack_map, SET_NOACK_MAP);
+       if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
+               i++;
+               if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
+                       goto nla_put_failure;
+       }
+       CMD(start_p2p_device, START_P2P_DEVICE);
+       CMD(set_mcast_rate, SET_MCAST_RATE);
+#ifdef CONFIG_NL80211_TESTMODE
+       CMD(testmode_cmd, TESTMODE);
+#endif
+
+       if (rdev->ops->connect || rdev->ops->auth) {
+               i++;
+               if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
+                       goto nla_put_failure;
+       }
+
+       if (rdev->ops->disconnect || rdev->ops->deauth) {
+               i++;
+               if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
+                       goto nla_put_failure;
+       }
+
+       return i;
+ nla_put_failure:
+       return -ENOBUFS;
+}
+
 struct nl80211_dump_wiphy_state {
        s64 filter_wiphy;
        long start;
@@ -1549,68 +1635,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
                if (!nl_cmds)
                        goto nla_put_failure;
 
-               i = 0;
-#define CMD(op, n)                                                     \
-                do {                                                   \
-                       if (rdev->ops->op) {                            \
-                               i++;                                    \
-                               if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \
-                                       goto nla_put_failure;           \
-                       }                                               \
-               } while (0)
-
-               CMD(add_virtual_intf, NEW_INTERFACE);
-               CMD(change_virtual_intf, SET_INTERFACE);
-               CMD(add_key, NEW_KEY);
-               CMD(start_ap, START_AP);
-               CMD(add_station, NEW_STATION);
-               CMD(add_mpath, NEW_MPATH);
-               CMD(update_mesh_config, SET_MESH_CONFIG);
-               CMD(change_bss, SET_BSS);
-               CMD(auth, AUTHENTICATE);
-               CMD(assoc, ASSOCIATE);
-               CMD(deauth, DEAUTHENTICATE);
-               CMD(disassoc, DISASSOCIATE);
-               CMD(join_ibss, JOIN_IBSS);
-               CMD(join_mesh, JOIN_MESH);
-               CMD(set_pmksa, SET_PMKSA);
-               CMD(del_pmksa, DEL_PMKSA);
-               CMD(flush_pmksa, FLUSH_PMKSA);
-               if (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
-                       CMD(remain_on_channel, REMAIN_ON_CHANNEL);
-               CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
-               CMD(mgmt_tx, FRAME);
-               CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
-               if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
-                       i++;
-                       if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
-                               goto nla_put_failure;
-               }
-               if (rdev->ops->set_monitor_channel || rdev->ops->start_ap ||
-                   rdev->ops->join_mesh) {
-                       i++;
-                       if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
-                               goto nla_put_failure;
-               }
-               CMD(set_wds_peer, SET_WDS_PEER);
-               if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
-                       CMD(tdls_mgmt, TDLS_MGMT);
-                       CMD(tdls_oper, TDLS_OPER);
-               }
-               if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
-                       CMD(sched_scan_start, START_SCHED_SCAN);
-               CMD(probe_client, PROBE_CLIENT);
-               CMD(set_noack_map, SET_NOACK_MAP);
-               if (rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
-                       i++;
-                       if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
-                               goto nla_put_failure;
-               }
-               CMD(start_p2p_device, START_P2P_DEVICE);
-               CMD(set_mcast_rate, SET_MCAST_RATE);
-#ifdef CONFIG_NL80211_TESTMODE
-               CMD(testmode_cmd, TESTMODE);
-#endif
+               i = nl80211_add_commands_unsplit(rdev, msg);
+               if (i < 0)
+                       goto nla_put_failure;
                if (state->split) {
                        CMD(crit_proto_start, CRIT_PROTOCOL_START);
                        CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
@@ -1620,22 +1647,11 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
                        if (rdev->wiphy.features &
                                        NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
                                CMD(add_tx_ts, ADD_TX_TS);
+                       CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
+                       CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
                }
-               /* add into the if now */
 #undef CMD
 
-               if (rdev->ops->connect || rdev->ops->auth) {
-                       i++;
-                       if (nla_put_u32(msg, i, NL80211_CMD_CONNECT))
-                               goto nla_put_failure;
-               }
-
-               if (rdev->ops->disconnect || rdev->ops->deauth) {
-                       i++;
-                       if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT))
-                               goto nla_put_failure;
-               }
-
                nla_nest_end(msg, nl_cmds);
                state->split_start++;
                if (state->split)
@@ -1881,7 +1897,7 @@ static int nl80211_dump_wiphy_parse(struct sk_buff *skb,
                                    struct netlink_callback *cb,
                                    struct nl80211_dump_wiphy_state *state)
 {
-       struct nlattr **tb = nl80211_fam.attrbuf;
+       struct nlattr **tb = genl_family_attrbuf(&nl80211_fam);
        int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
                              tb, nl80211_fam.maxattr, nl80211_policy);
        /* ignore parse errors for backward compatibility */
@@ -2296,10 +2312,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                nla_for_each_nested(nl_txq_params,
                                    info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
                                    rem_txq_params) {
-                       result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
-                                          nla_data(nl_txq_params),
-                                          nla_len(nl_txq_params),
-                                          txq_params_policy);
+                       result = nla_parse_nested(tb, NL80211_TXQ_ATTR_MAX,
+                                                 nl_txq_params,
+                                                 txq_params_policy);
                        if (result)
                                return result;
                        result = parse_txq_params(tb, &txq_params);
@@ -3549,8 +3564,8 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
                sband = rdev->wiphy.bands[band];
                if (sband == NULL)
                        return -EINVAL;
-               err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
-                               nla_len(tx_rates), nl80211_txattr_policy);
+               err = nla_parse_nested(tb, NL80211_TXRATE_MAX, tx_rates,
+                                      nl80211_txattr_policy);
                if (err)
                        return err;
                if (tb[NL80211_TXRATE_LEGACY]) {
@@ -3756,12 +3771,23 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
                if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
                    auth_type == NL80211_AUTHTYPE_SAE)
                        return false;
+               if (!wiphy_ext_feature_isset(&rdev->wiphy,
+                                            NL80211_EXT_FEATURE_FILS_STA) &&
+                   (auth_type == NL80211_AUTHTYPE_FILS_SK ||
+                    auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+                    auth_type == NL80211_AUTHTYPE_FILS_PK))
+                       return false;
                return true;
        case NL80211_CMD_CONNECT:
        case NL80211_CMD_START_AP:
                /* SAE not supported yet */
                if (auth_type == NL80211_AUTHTYPE_SAE)
                        return false;
+               /* FILS not supported yet */
+               if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
+                   auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+                   auth_type == NL80211_AUTHTYPE_FILS_PK)
+                       return false;
                return true;
        default:
                return false;
@@ -3803,7 +3829,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
        params.dtim_period =
                nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
 
-       err = cfg80211_validate_beacon_int(rdev, params.beacon_interval);
+       err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
+                                          params.beacon_interval);
        if (err)
                return err;
 
@@ -6305,9 +6332,8 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
 
        nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
                            rem_reg_rules) {
-               r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
-                             nla_data(nl_reg_rule), nla_len(nl_reg_rule),
-                             reg_rule_policy);
+               r = nla_parse_nested(tb, NL80211_REG_RULE_ATTR_MAX,
+                                    nl_reg_rule, reg_rule_policy);
                if (r)
                        goto bad_reg;
                r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
@@ -6374,8 +6400,8 @@ static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
        if (!nla_ok(nest, nla_len(nest)))
                return -EINVAL;
 
-       err = nla_parse(attr, NL80211_BSS_SELECT_ATTR_MAX, nla_data(nest),
-                       nla_len(nest), nl80211_bss_select_policy);
+       err = nla_parse_nested(attr, NL80211_BSS_SELECT_ATTR_MAX, nest,
+                              nl80211_bss_select_policy);
        if (err)
                return err;
 
@@ -6765,9 +6791,8 @@ nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
                if (WARN_ON(i >= n_plans))
                        return -EINVAL;
 
-               err = nla_parse(plan, NL80211_SCHED_SCAN_PLAN_MAX,
-                               nla_data(attr), nla_len(attr),
-                               nl80211_plan_policy);
+               err = nla_parse_nested(plan, NL80211_SCHED_SCAN_PLAN_MAX,
+                                      attr, nl80211_plan_policy);
                if (err)
                        return err;
 
@@ -6856,9 +6881,9 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
                                    tmp) {
                        struct nlattr *rssi;
 
-                       err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
-                                       nla_data(attr), nla_len(attr),
-                                       nl80211_match_policy);
+                       err = nla_parse_nested(tb,
+                                              NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
+                                              attr, nl80211_match_policy);
                        if (err)
                                return ERR_PTR(err);
                        /* add other standalone attributes here */
@@ -7029,9 +7054,9 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
                                    tmp) {
                        struct nlattr *ssid, *rssi;
 
-                       err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
-                                       nla_data(attr), nla_len(attr),
-                                       nl80211_match_policy);
+                       err = nla_parse_nested(tb,
+                                              NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
+                                              attr, nl80211_match_policy);
                        if (err)
                                goto out_free;
                        ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
@@ -7643,6 +7668,7 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
 
 static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
 {
+       struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
        struct survey_info survey;
        struct cfg80211_registered_device *rdev;
        struct wireless_dev *wdev;
@@ -7655,7 +7681,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
                return res;
 
        /* prepare_wdev_dump parsed the attributes */
-       radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
+       radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
 
        if (!wdev->netdev) {
                res = -EINVAL;
@@ -7708,8 +7734,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct net_device *dev = info->user_ptr[1];
        struct ieee80211_channel *chan;
-       const u8 *bssid, *ssid, *ie = NULL, *sae_data = NULL;
-       int err, ssid_len, ie_len = 0, sae_data_len = 0;
+       const u8 *bssid, *ssid, *ie = NULL, *auth_data = NULL;
+       int err, ssid_len, ie_len = 0, auth_data_len = 0;
        enum nl80211_auth_type auth_type;
        struct key_parse key;
        bool local_state_change;
@@ -7789,17 +7815,23 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
        if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE))
                return -EINVAL;
 
-       if (auth_type == NL80211_AUTHTYPE_SAE &&
-           !info->attrs[NL80211_ATTR_SAE_DATA])
+       if ((auth_type == NL80211_AUTHTYPE_SAE ||
+            auth_type == NL80211_AUTHTYPE_FILS_SK ||
+            auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
+            auth_type == NL80211_AUTHTYPE_FILS_PK) &&
+           !info->attrs[NL80211_ATTR_AUTH_DATA])
                return -EINVAL;
 
-       if (info->attrs[NL80211_ATTR_SAE_DATA]) {
-               if (auth_type != NL80211_AUTHTYPE_SAE)
+       if (info->attrs[NL80211_ATTR_AUTH_DATA]) {
+               if (auth_type != NL80211_AUTHTYPE_SAE &&
+                   auth_type != NL80211_AUTHTYPE_FILS_SK &&
+                   auth_type != NL80211_AUTHTYPE_FILS_SK_PFS &&
+                   auth_type != NL80211_AUTHTYPE_FILS_PK)
                        return -EINVAL;
-               sae_data = nla_data(info->attrs[NL80211_ATTR_SAE_DATA]);
-               sae_data_len = nla_len(info->attrs[NL80211_ATTR_SAE_DATA]);
+               auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
+               auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
                /* need to include at least Auth Transaction and Status Code */
-               if (sae_data_len < 4)
+               if (auth_data_len < 4)
                        return -EINVAL;
        }
 
@@ -7816,7 +7848,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
        err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
                                 ssid, ssid_len, ie, ie_len,
                                 key.p.key, key.p.key_len, key.idx,
-                                sae_data, sae_data_len);
+                                auth_data, auth_data_len);
        wdev_unlock(dev->ieee80211_ptr);
        return err;
 }
@@ -7995,6 +8027,15 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
                req.flags |= ASSOC_REQ_USE_RRM;
        }
 
+       if (info->attrs[NL80211_ATTR_FILS_KEK]) {
+               req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
+               req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
+               if (!info->attrs[NL80211_ATTR_FILS_NONCES])
+                       return -EINVAL;
+               req.fils_nonces =
+                       nla_data(info->attrs[NL80211_ATTR_FILS_NONCES]);
+       }
+
        err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
        if (!err) {
                wdev_lock(dev->ieee80211_ptr);
@@ -8152,7 +8193,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
                ibss.beacon_interval =
                        nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
 
-       err = cfg80211_validate_beacon_int(rdev, ibss.beacon_interval);
+       err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
+                                          ibss.beacon_interval);
        if (err)
                return err;
 
@@ -8478,14 +8520,14 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
                 */
                phy_idx = cb->args[0] - 1;
        } else {
+               struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
+
                err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
-                                 nl80211_fam.attrbuf, nl80211_fam.maxattr,
-                                 nl80211_policy);
+                                 attrbuf, nl80211_fam.maxattr, nl80211_policy);
                if (err)
                        goto out_err;
 
-               rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
-                                                 nl80211_fam.attrbuf);
+               rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
                if (IS_ERR(rdev)) {
                        err = PTR_ERR(rdev);
                        goto out_err;
@@ -8493,9 +8535,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
                phy_idx = rdev->wiphy_idx;
                rdev = NULL;
 
-               if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
-                       cb->args[1] =
-                               (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
+               if (attrbuf[NL80211_ATTR_TESTDATA])
+                       cb->args[1] = (long)attrbuf[NL80211_ATTR_TESTDATA];
        }
 
        if (cb->args[1]) {
@@ -8726,6 +8767,37 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
        return err;
 }
 
+static int nl80211_update_connect_params(struct sk_buff *skb,
+                                        struct genl_info *info)
+{
+       struct cfg80211_connect_params connect = {};
+       struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       u32 changed = 0;
+       int ret;
+
+       if (!rdev->ops->update_connect_params)
+               return -EOPNOTSUPP;
+
+       if (info->attrs[NL80211_ATTR_IE]) {
+               if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+                       return -EINVAL;
+               connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+               connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+               changed |= UPDATE_ASSOC_IES;
+       }
+
+       wdev_lock(dev->ieee80211_ptr);
+       if (!wdev->current_bss)
+               ret = -ENOLINK;
+       else
+               ret = rdev_update_connect_params(rdev, dev, &connect, changed);
+       wdev_unlock(dev->ieee80211_ptr);
+
+       return ret;
+}
+
 static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9417,7 +9489,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
                setup.beacon_interval =
                        nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
 
-               err = cfg80211_validate_beacon_int(rdev, setup.beacon_interval);
+               err = cfg80211_validate_beacon_int(rdev,
+                                                  NL80211_IFTYPE_MESH_POINT,
+                                                  setup.beacon_interval);
                if (err)
                        return err;
        }
@@ -9728,9 +9802,8 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev,
        if (!rdev->wiphy.wowlan->tcp)
                return -EINVAL;
 
-       err = nla_parse(tb, MAX_NL80211_WOWLAN_TCP,
-                       nla_data(attr), nla_len(attr),
-                       nl80211_wowlan_tcp_policy);
+       err = nla_parse_nested(tb, MAX_NL80211_WOWLAN_TCP, attr,
+                              nl80211_wowlan_tcp_policy);
        if (err)
                return err;
 
@@ -9875,9 +9948,7 @@ static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
                goto out;
        }
 
-       err = nla_parse(tb, NL80211_ATTR_MAX,
-                       nla_data(attr), nla_len(attr),
-                       nl80211_policy);
+       err = nla_parse_nested(tb, NL80211_ATTR_MAX, attr, nl80211_policy);
        if (err)
                goto out;
 
@@ -9911,10 +9982,9 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
                goto set_wakeup;
        }
 
-       err = nla_parse(tb, MAX_NL80211_WOWLAN_TRIG,
-                       nla_data(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
-                       nla_len(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
-                       nl80211_wowlan_policy);
+       err = nla_parse_nested(tb, MAX_NL80211_WOWLAN_TRIG,
+                              info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS],
+                              nl80211_wowlan_policy);
        if (err)
                return err;
 
@@ -9996,8 +10066,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
                                    rem) {
                        u8 *mask_pat;
 
-                       nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
-                                 nla_len(pat), NULL);
+                       nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat,
+                                        NULL);
                        err = -EINVAL;
                        if (!pat_tb[NL80211_PKTPAT_MASK] ||
                            !pat_tb[NL80211_PKTPAT_PATTERN])
@@ -10207,8 +10277,8 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
        int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
        struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
 
-       err = nla_parse(tb, NL80211_ATTR_COALESCE_RULE_MAX, nla_data(rule),
-                       nla_len(rule), nl80211_coalesce_policy);
+       err = nla_parse_nested(tb, NL80211_ATTR_COALESCE_RULE_MAX, rule,
+                              nl80211_coalesce_policy);
        if (err)
                return err;
 
@@ -10246,8 +10316,7 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
                            rem) {
                u8 *mask_pat;
 
-               nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
-                         nla_len(pat), NULL);
+               nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat, NULL);
                if (!pat_tb[NL80211_PKTPAT_MASK] ||
                    !pat_tb[NL80211_PKTPAT_PATTERN])
                        return -EINVAL;
@@ -10366,10 +10435,9 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
        if (!info->attrs[NL80211_ATTR_REKEY_DATA])
                return -EINVAL;
 
-       err = nla_parse(tb, MAX_NL80211_REKEY_DATA,
-                       nla_data(info->attrs[NL80211_ATTR_REKEY_DATA]),
-                       nla_len(info->attrs[NL80211_ATTR_REKEY_DATA]),
-                       nl80211_rekey_policy);
+       err = nla_parse_nested(tb, MAX_NL80211_REKEY_DATA,
+                              info->attrs[NL80211_ATTR_REKEY_DATA],
+                              nl80211_rekey_policy);
        if (err)
                return err;
 
@@ -10518,7 +10586,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
        if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
                return -EOPNOTSUPP;
 
-       if (wdev->p2p_started)
+       if (wdev_running(wdev))
                return 0;
 
        if (rfkill_blocked(rdev->rfkill))
@@ -10528,7 +10596,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
-       wdev->p2p_started = true;
+       wdev->is_running = true;
        rdev->opencount++;
 
        return 0;
@@ -10560,7 +10628,7 @@ static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
        if (wdev->iftype != NL80211_IFTYPE_NAN)
                return -EOPNOTSUPP;
 
-       if (wdev->nan_started)
+       if (!wdev_running(wdev))
                return -EEXIST;
 
        if (rfkill_blocked(rdev->rfkill))
@@ -10583,7 +10651,7 @@ static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
-       wdev->nan_started = true;
+       wdev->is_running = true;
        rdev->opencount++;
 
        return 0;
@@ -10638,8 +10706,7 @@ static int handle_nan_filter(struct nlattr *attr_filter,
 
        i = 0;
        nla_for_each_nested(attr, attr_filter, rem) {
-               filter[i].filter = kmemdup(nla_data(attr), nla_len(attr),
-                                          GFP_KERNEL);
+               filter[i].filter = nla_memdup(attr, GFP_KERNEL);
                filter[i].len = nla_len(attr);
                i++;
        }
@@ -10668,7 +10735,7 @@ static int nl80211_nan_add_func(struct sk_buff *skb,
        if (wdev->iftype != NL80211_IFTYPE_NAN)
                return -EOPNOTSUPP;
 
-       if (!wdev->nan_started)
+       if (!wdev_running(wdev))
                return -ENOTCONN;
 
        if (!info->attrs[NL80211_ATTR_NAN_FUNC])
@@ -10678,10 +10745,9 @@ static int nl80211_nan_add_func(struct sk_buff *skb,
            wdev->owner_nlportid != info->snd_portid)
                return -ENOTCONN;
 
-       err = nla_parse(tb, NL80211_NAN_FUNC_ATTR_MAX,
-                       nla_data(info->attrs[NL80211_ATTR_NAN_FUNC]),
-                       nla_len(info->attrs[NL80211_ATTR_NAN_FUNC]),
-                       nl80211_nan_func_policy);
+       err = nla_parse_nested(tb, NL80211_NAN_FUNC_ATTR_MAX,
+                              info->attrs[NL80211_ATTR_NAN_FUNC],
+                              nl80211_nan_func_policy);
        if (err)
                return err;
 
@@ -10776,9 +10842,9 @@ static int nl80211_nan_add_func(struct sk_buff *skb,
        if (tb[NL80211_NAN_FUNC_SRF]) {
                struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
 
-               err = nla_parse(srf_tb, NL80211_NAN_SRF_ATTR_MAX,
-                               nla_data(tb[NL80211_NAN_FUNC_SRF]),
-                               nla_len(tb[NL80211_NAN_FUNC_SRF]), NULL);
+               err = nla_parse_nested(srf_tb, NL80211_NAN_SRF_ATTR_MAX,
+                                      tb[NL80211_NAN_FUNC_SRF],
+                                      nl80211_nan_srf_policy);
                if (err)
                        goto out;
 
@@ -10904,7 +10970,7 @@ static int nl80211_nan_del_func(struct sk_buff *skb,
        if (wdev->iftype != NL80211_IFTYPE_NAN)
                return -EOPNOTSUPP;
 
-       if (!wdev->nan_started)
+       if (!wdev_running(wdev))
                return -ENOTCONN;
 
        if (!info->attrs[NL80211_ATTR_COOKIE])
@@ -10932,7 +10998,7 @@ static int nl80211_nan_change_config(struct sk_buff *skb,
        if (wdev->iftype != NL80211_IFTYPE_NAN)
                return -EOPNOTSUPP;
 
-       if (!wdev->nan_started)
+       if (!wdev_running(wdev))
                return -ENOTCONN;
 
        if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
@@ -11244,10 +11310,7 @@ static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
                                return -EINVAL;
 
                        if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
-                               if (wdev->netdev &&
-                                   !netif_running(wdev->netdev))
-                                       return -ENETDOWN;
-                               if (!wdev->netdev && !wdev->p2p_started)
+                               if (!wdev_running(wdev))
                                        return -ENETDOWN;
                        }
 
@@ -11277,6 +11340,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
                                       struct cfg80211_registered_device **rdev,
                                       struct wireless_dev **wdev)
 {
+       struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
        u32 vid, subcmd;
        unsigned int i;
        int vcmd_idx = -1;
@@ -11312,31 +11376,28 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
        }
 
        err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
-                         nl80211_fam.attrbuf, nl80211_fam.maxattr,
-                         nl80211_policy);
+                         attrbuf, nl80211_fam.maxattr, nl80211_policy);
        if (err)
                goto out_unlock;
 
-       if (!nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID] ||
-           !nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
+       if (!attrbuf[NL80211_ATTR_VENDOR_ID] ||
+           !attrbuf[NL80211_ATTR_VENDOR_SUBCMD]) {
                err = -EINVAL;
                goto out_unlock;
        }
 
-       *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
-                                          nl80211_fam.attrbuf);
+       *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf);
        if (IS_ERR(*wdev))
                *wdev = NULL;
 
-       *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
-                                          nl80211_fam.attrbuf);
+       *rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), attrbuf);
        if (IS_ERR(*rdev)) {
                err = PTR_ERR(*rdev);
                goto out_unlock;
        }
 
-       vid = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_ID]);
-       subcmd = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
+       vid = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_ID]);
+       subcmd = nla_get_u32(attrbuf[NL80211_ATTR_VENDOR_SUBCMD]);
 
        for (i = 0; i < (*rdev)->wiphy.n_vendor_commands; i++) {
                const struct wiphy_vendor_command *vcmd;
@@ -11360,9 +11421,9 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
                goto out_unlock;
        }
 
-       if (nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]) {
-               data = nla_data(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]);
-               data_len = nla_len(nl80211_fam.attrbuf[NL80211_ATTR_VENDOR_DATA]);
+       if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {
+               data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);
+               data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]);
        }
 
        /* 0 is the first index - add 1 to parse only once */
@@ -11410,10 +11471,7 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
                        return -EINVAL;
 
                if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
-                       if (wdev->netdev &&
-                           !netif_running(wdev->netdev))
-                               return -ENETDOWN;
-                       if (!wdev->netdev && !wdev->p2p_started)
+                       if (!wdev_running(wdev))
                                return -ENETDOWN;
                }
        }
@@ -11726,6 +11784,31 @@ static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
        return 0;
 }
 
+static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
+                                           struct genl_info *info)
+{
+       struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       const struct nlattr *nla;
+       bool enabled;
+
+       if (netif_running(dev))
+               return -EBUSY;
+
+       if (!rdev->ops->set_multicast_to_unicast)
+               return -EOPNOTSUPP;
+
+       if (wdev->iftype != NL80211_IFTYPE_AP &&
+           wdev->iftype != NL80211_IFTYPE_P2P_GO)
+               return -EOPNOTSUPP;
+
+       nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
+       enabled = nla_get_flag(nla);
+
+       return rdev_set_multicast_to_unicast(rdev, dev, enabled);
+}
+
 #define NL80211_FLAG_NEED_WIPHY                0x01
 #define NL80211_FLAG_NEED_NETDEV       0x02
 #define NL80211_FLAG_NEED_RTNL         0x04
@@ -11784,29 +11867,15 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
                        info->user_ptr[1] = wdev;
                }
 
-               if (dev) {
-                       if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
-                           !netif_running(dev)) {
-                               if (rtnl)
-                                       rtnl_unlock();
-                               return -ENETDOWN;
-                       }
+               if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
+                   !wdev_running(wdev)) {
+                       if (rtnl)
+                               rtnl_unlock();
+                       return -ENETDOWN;
+               }
 
+               if (dev)
                        dev_hold(dev);
-               } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
-                       if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
-                           !wdev->p2p_started) {
-                               if (rtnl)
-                                       rtnl_unlock();
-                               return -ENETDOWN;
-                       }
-                       if (wdev->iftype == NL80211_IFTYPE_NAN &&
-                           !wdev->nan_started) {
-                               if (rtnl)
-                                       rtnl_unlock();
-                               return -ENETDOWN;
-                       }
-               }
 
                info->user_ptr[0] = rdev;
        }
@@ -12178,6 +12247,14 @@ static const struct genl_ops nl80211_ops[] = {
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
+       {
+               .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
+               .doit = nl80211_update_connect_params,
+               .policy = nl80211_policy,
+               .flags = GENL_ADMIN_PERM,
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+                                 NL80211_FLAG_NEED_RTNL,
+       },
        {
                .cmd = NL80211_CMD_DISCONNECT,
                .doit = nl80211_disconnect,
@@ -12599,6 +12676,29 @@ static const struct genl_ops nl80211_ops[] = {
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
+       {
+               .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
+               .doit = nl80211_set_multicast_to_unicast,
+               .policy = nl80211_policy,
+               .flags = GENL_UNS_ADMIN_PERM,
+               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+                                 NL80211_FLAG_NEED_RTNL,
+       },
+};
+
+static struct genl_family nl80211_fam __ro_after_init = {
+       .name = NL80211_GENL_NAME,      /* have users key off the name instead */
+       .hdrsize = 0,                   /* no private header */
+       .version = 1,                   /* no particular meaning now */
+       .maxattr = NL80211_ATTR_MAX,
+       .netnsok = true,
+       .pre_doit = nl80211_pre_doit,
+       .post_doit = nl80211_post_doit,
+       .module = THIS_MODULE,
+       .ops = nl80211_ops,
+       .n_ops = ARRAY_SIZE(nl80211_ops),
+       .mcgrps = nl80211_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
 };
 
 /* notification functions */
@@ -14563,12 +14663,11 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev)
 
 /* initialisation/exit functions */
 
-int nl80211_init(void)
+int __init nl80211_init(void)
 {
        int err;
 
-       err = genl_register_family_with_ops_groups(&nl80211_fam, nl80211_ops,
-                                                  nl80211_mcgrps);
+       err = genl_register_family(&nl80211_fam);
        if (err)
                return err;
 
index 11cf83c8ad4f5008abb3f1cf8f59058027f2bb2d..2f425075ada8eae81c8ecb04d975d0c9f0d36578 100644 (file)
@@ -490,6 +490,18 @@ static inline int rdev_connect(struct cfg80211_registered_device *rdev,
        return ret;
 }
 
+static inline int
+rdev_update_connect_params(struct cfg80211_registered_device *rdev,
+                          struct net_device *dev,
+                          struct cfg80211_connect_params *sme, u32 changed)
+{
+       int ret;
+       trace_rdev_update_connect_params(&rdev->wiphy, dev, sme, changed);
+       ret = rdev->ops->update_connect_params(&rdev->wiphy, dev, sme, changed);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
 static inline int rdev_disconnect(struct cfg80211_registered_device *rdev,
                                  struct net_device *dev, u16 reason_code)
 {
@@ -562,6 +574,18 @@ static inline int rdev_set_wds_peer(struct cfg80211_registered_device *rdev,
        return ret;
 }
 
+static inline int
+rdev_set_multicast_to_unicast(struct cfg80211_registered_device *rdev,
+                             struct net_device *dev,
+                             const bool enabled)
+{
+       int ret;
+       trace_rdev_set_multicast_to_unicast(&rdev->wiphy, dev, enabled);
+       ret = rdev->ops->set_multicast_to_unicast(&rdev->wiphy, dev, enabled);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
 static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev)
 {
        trace_rdev_rfkill_poll(&rdev->wiphy);
index a77db333927ec1bc8ab6efa4ee26b9fc7e711f5e..2b5bb380414b6c05eb15d3467a16e9be7f108cbd 100644 (file)
@@ -1088,7 +1088,7 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                err = cfg80211_sme_disconnect(wdev, reason);
        else if (!rdev->ops->disconnect)
                cfg80211_mlme_down(rdev, dev);
-       else if (wdev->current_bss)
+       else if (wdev->ssid_len)
                err = rdev_disconnect(rdev, dev, reason);
 
        return err;
index a3d0a91b1e0957766bd77d8cc9a712ce335598ec..ea1b47e04fa474b601bd34a77d1e6cc05cf0e176 100644 (file)
@@ -1281,6 +1281,24 @@ TRACE_EVENT(rdev_connect,
                  __entry->wpa_versions, __entry->flags, MAC_PR_ARG(prev_bssid))
 );
 
+TRACE_EVENT(rdev_update_connect_params,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_connect_params *sme, u32 changed),
+       TP_ARGS(wiphy, netdev, sme, changed),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(u32, changed)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->changed = changed;
+       ),
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", parameters changed: %u",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG,  __entry->changed)
+);
+
 TRACE_EVENT(rdev_set_cqm_rssi_config,
        TP_PROTO(struct wiphy *wiphy,
                 struct net_device *netdev, s32 rssi_thold,
@@ -3030,6 +3048,25 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan,
        TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
        TP_ARGS(wiphy, wdev)
 );
+
+TRACE_EVENT(rdev_set_multicast_to_unicast,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                const bool enabled),
+       TP_ARGS(wiphy, netdev, enabled),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __field(bool, enabled)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               __entry->enabled = enabled;
+       ),
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", unicast: %s",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG,
+                 BOOL_TO_STR(__entry->enabled))
+);
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
index 5ea12afc770610e88a2b8ad870d08676fa2a71c9..88725f8eefad4fb35b8c04b03d2b968ed30aedc9 100644 (file)
@@ -13,6 +13,7 @@
 #include <net/dsfield.h>
 #include <linux/if_vlan.h>
 #include <linux/mpls.h>
+#include <linux/gcd.h>
 #include "core.h"
 #include "rdev-ops.h"
 
@@ -1377,6 +1378,25 @@ static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
        return false;
 }
 
+static size_t skip_ie(const u8 *ies, size_t ielen, size_t pos)
+{
+       /* we assume a validly formed IEs buffer */
+       u8 len = ies[pos + 1];
+
+       pos += 2 + len;
+
+       /* the IE itself must have 255 bytes for fragments to follow */
+       if (len < 255)
+               return pos;
+
+       while (pos < ielen && ies[pos] == WLAN_EID_FRAGMENT) {
+               len = ies[pos + 1];
+               pos += 2 + len;
+       }
+
+       return pos;
+}
+
 size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
                              const u8 *ids, int n_ids,
                              const u8 *after_ric, int n_after_ric,
@@ -1386,14 +1406,14 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
 
        while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
                if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
-                       pos += 2 + ies[pos + 1];
+                       pos = skip_ie(ies, ielen, pos);
 
                        while (pos < ielen &&
                               !ieee80211_id_in_list(after_ric, n_after_ric,
                                                     ies[pos]))
-                               pos += 2 + ies[pos + 1];
+                               pos = skip_ie(ies, ielen, pos);
                } else {
-                       pos += 2 + ies[pos + 1];
+                       pos = skip_ie(ies, ielen, pos);
                }
        }
 
@@ -1554,31 +1574,57 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
 }
 EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
 
-int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
-                                u32 beacon_int)
+static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
+                                      u32 *beacon_int_gcd,
+                                      bool *beacon_int_different)
 {
        struct wireless_dev *wdev;
-       int res = 0;
 
-       if (beacon_int < 10 || beacon_int > 10000)
-               return -EINVAL;
+       *beacon_int_gcd = 0;
+       *beacon_int_different = false;
 
-       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+       list_for_each_entry(wdev, &wiphy->wdev_list, list) {
                if (!wdev->beacon_interval)
                        continue;
-               if (wdev->beacon_interval != beacon_int) {
-                       res = -EINVAL;
-                       break;
+
+               if (!*beacon_int_gcd) {
+                       *beacon_int_gcd = wdev->beacon_interval;
+                       continue;
                }
+
+               if (wdev->beacon_interval == *beacon_int_gcd)
+                       continue;
+
+               *beacon_int_different = true;
+               *beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval);
        }
 
-       return res;
+       if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
+               if (*beacon_int_gcd)
+                       *beacon_int_different = true;
+               *beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
+       }
+}
+
+int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
+                                enum nl80211_iftype iftype, u32 beacon_int)
+{
+       /*
+        * This is just a basic pre-condition check; if interface combinations
+        * are possible the driver must already be checking those with a call
+        * to cfg80211_check_combinations(), in which case we'll validate more
+        * through the cfg80211_calculate_bi_data() call and code in
+        * cfg80211_iter_combinations().
+        */
+
+       if (beacon_int < 10 || beacon_int > 10000)
+               return -EINVAL;
+
+       return 0;
 }
 
 int cfg80211_iter_combinations(struct wiphy *wiphy,
-                              const int num_different_channels,
-                              const u8 radar_detect,
-                              const int iftype_num[NUM_NL80211_IFTYPES],
+                              struct iface_combination_params *params,
                               void (*iter)(const struct ieee80211_iface_combination *c,
                                            void *data),
                               void *data)
@@ -1588,8 +1634,23 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
        int i, j, iftype;
        int num_interfaces = 0;
        u32 used_iftypes = 0;
+       u32 beacon_int_gcd;
+       bool beacon_int_different;
+
+       /*
+        * This is a bit strange, since the iteration used to rely only on
+        * the data given by the driver, but here it now relies on context,
+        * in form of the currently operating interfaces.
+        * This is OK for all current users, and saves us from having to
+        * push the GCD calculations into all the drivers.
+        * In the future, this should probably rely more on data that's in
+        * cfg80211 already - the only thing not would appear to be any new
+        * interfaces (while being brought up) and channel/radar data.
+        */
+       cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
+                                  &beacon_int_gcd, &beacon_int_different);
 
-       if (radar_detect) {
+       if (params->radar_detect) {
                rcu_read_lock();
                regdom = rcu_dereference(cfg80211_regdomain);
                if (regdom)
@@ -1598,8 +1659,8 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
        }
 
        for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
-               num_interfaces += iftype_num[iftype];
-               if (iftype_num[iftype] > 0 &&
+               num_interfaces += params->iftype_num[iftype];
+               if (params->iftype_num[iftype] > 0 &&
                    !(wiphy->software_iftypes & BIT(iftype)))
                        used_iftypes |= BIT(iftype);
        }
@@ -1613,7 +1674,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
 
                if (num_interfaces > c->max_interfaces)
                        continue;
-               if (num_different_channels > c->num_different_channels)
+               if (params->num_different_channels > c->num_different_channels)
                        continue;
 
                limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
@@ -1628,16 +1689,17 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
                                all_iftypes |= limits[j].types;
                                if (!(limits[j].types & BIT(iftype)))
                                        continue;
-                               if (limits[j].max < iftype_num[iftype])
+                               if (limits[j].max < params->iftype_num[iftype])
                                        goto cont;
-                               limits[j].max -= iftype_num[iftype];
+                               limits[j].max -= params->iftype_num[iftype];
                        }
                }
 
-               if (radar_detect != (c->radar_detect_widths & radar_detect))
+               if (params->radar_detect !=
+                       (c->radar_detect_widths & params->radar_detect))
                        goto cont;
 
-               if (radar_detect && c->radar_detect_regions &&
+               if (params->radar_detect && c->radar_detect_regions &&
                    !(c->radar_detect_regions & BIT(region)))
                        goto cont;
 
@@ -1649,6 +1711,14 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
                if ((all_iftypes & used_iftypes) != used_iftypes)
                        goto cont;
 
+               if (beacon_int_gcd) {
+                       if (c->beacon_int_min_gcd &&
+                           beacon_int_gcd < c->beacon_int_min_gcd)
+                               goto cont;
+                       if (!c->beacon_int_min_gcd && beacon_int_different)
+                               goto cont;
+               }
+
                /* This combination covered all interface types and
                 * supported the requested numbers, so we're good.
                 */
@@ -1671,14 +1741,11 @@ cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c,
 }
 
 int cfg80211_check_combinations(struct wiphy *wiphy,
-                               const int num_different_channels,
-                               const u8 radar_detect,
-                               const int iftype_num[NUM_NL80211_IFTYPES])
+                               struct iface_combination_params *params)
 {
        int err, num = 0;
 
-       err = cfg80211_iter_combinations(wiphy, num_different_channels,
-                                        radar_detect, iftype_num,
+       err = cfg80211_iter_combinations(wiphy, params,
                                         cfg80211_iter_sum_ifcombs, &num);
        if (err)
                return err;
index 419bf5d463bde118274e9f4dc1fffba08f75f258..45cb7c699b65ba4e1c928e94c1a65d8ee7a8ef96 100644 (file)
@@ -388,14 +388,6 @@ static void xfrm_state_gc_task(struct work_struct *work)
                xfrm_state_gc_destroy(x);
 }
 
-static inline unsigned long make_jiffies(long secs)
-{
-       if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
-               return MAX_SCHEDULE_TIMEOUT-1;
-       else
-               return secs*HZ;
-}
-
 static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
 {
        struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
index 12b7304d55dcd2e64515c6a0af7c777a44f3e645..5c53fdb67ca75a920089e8b3b3a3e983f246463e 100644 (file)
@@ -2,7 +2,6 @@
 obj- := dummy.o
 
 # List of programs to build
-hostprogs-y := test_verifier test_maps
 hostprogs-y += sock_example
 hostprogs-y += fds_example
 hostprogs-y += sockex1
@@ -28,8 +27,6 @@ hostprogs-y += test_current_task_under_cgroup
 hostprogs-y += trace_event
 hostprogs-y += sampleip
 
-test_verifier-objs := test_verifier.o libbpf.o
-test_maps-objs := test_maps.o libbpf.o
 sock_example-objs := sock_example.o libbpf.o
 fds_example-objs := bpf_load.o libbpf.o fds_example.o
 sockex1-objs := bpf_load.o libbpf.o sockex1_user.o
diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c
deleted file mode 100644 (file)
index cce2b59..0000000
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Testsuite for eBPF maps
- *
- * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
- * Copyright (c) 2016 Facebook
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <linux/bpf.h>
-#include <errno.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-#include "libbpf.h"
-
-static int map_flags;
-
-/* sanity tests for map API */
-static void test_hashmap_sanity(int i, void *data)
-{
-       long long key, next_key, value;
-       int map_fd;
-
-       map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
-                               2, map_flags);
-       if (map_fd < 0) {
-               printf("failed to create hashmap '%s'\n", strerror(errno));
-               exit(1);
-       }
-
-       key = 1;
-       value = 1234;
-       /* insert key=1 element */
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
-
-       value = 0;
-       /* BPF_NOEXIST means: add new element if it doesn't exist */
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
-              /* key=1 already exists */
-              errno == EEXIST);
-
-       assert(bpf_update_elem(map_fd, &key, &value, -1) == -1 && errno == EINVAL);
-
-       /* check that key=1 can be found */
-       assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);
-
-       key = 2;
-       /* check that key=2 is not found */
-       assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
-
-       /* BPF_EXIST means: update existing element */
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
-              /* key=2 is not there */
-              errno == ENOENT);
-
-       /* insert key=2 element */
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
-
-       /* key=1 and key=2 were inserted, check that key=0 cannot be inserted
-        * due to max_entries limit
-        */
-       key = 0;
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
-              errno == E2BIG);
-
-       /* update existing element, thought the map is full */
-       key = 1;
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == 0);
-       key = 2;
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
-       key = 1;
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
-
-       /* check that key = 0 doesn't exist */
-       key = 0;
-       assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
-
-       /* iterate over two elements */
-       assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
-              (next_key == 1 || next_key == 2));
-       assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
-              (next_key == 1 || next_key == 2));
-       assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
-              errno == ENOENT);
-
-       /* delete both elements */
-       key = 1;
-       assert(bpf_delete_elem(map_fd, &key) == 0);
-       key = 2;
-       assert(bpf_delete_elem(map_fd, &key) == 0);
-       assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
-
-       key = 0;
-       /* check that map is empty */
-       assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 &&
-              errno == ENOENT);
-       close(map_fd);
-}
-
-/* sanity tests for percpu map API */
-static void test_percpu_hashmap_sanity(int task, void *data)
-{
-       long long key, next_key;
-       int expected_key_mask = 0;
-       unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
-       long long value[nr_cpus];
-       int map_fd, i;
-
-       map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
-                               sizeof(value[0]), 2, map_flags);
-       if (map_fd < 0) {
-               printf("failed to create hashmap '%s'\n", strerror(errno));
-               exit(1);
-       }
-
-       for (i = 0; i < nr_cpus; i++)
-               value[i] = i + 100;
-       key = 1;
-       /* insert key=1 element */
-       assert(!(expected_key_mask & key));
-       assert(bpf_update_elem(map_fd, &key, value, BPF_ANY) == 0);
-       expected_key_mask |= key;
-
-       /* BPF_NOEXIST means: add new element if it doesn't exist */
-       assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 &&
-              /* key=1 already exists */
-              errno == EEXIST);
-
-       /* -1 is an invalid flag */
-       assert(bpf_update_elem(map_fd, &key, value, -1) == -1 &&
-              errno == EINVAL);
-
-       /* check that key=1 can be found. value could be 0 if the lookup
-        * was run from a different cpu.
-        */
-       value[0] = 1;
-       assert(bpf_lookup_elem(map_fd, &key, value) == 0 && value[0] == 100);
-
-       key = 2;
-       /* check that key=2 is not found */
-       assert(bpf_lookup_elem(map_fd, &key, value) == -1 && errno == ENOENT);
-
-       /* BPF_EXIST means: update existing element */
-       assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == -1 &&
-              /* key=2 is not there */
-              errno == ENOENT);
-
-       /* insert key=2 element */
-       assert(!(expected_key_mask & key));
-       assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0);
-       expected_key_mask |= key;
-
-       /* key=1 and key=2 were inserted, check that key=0 cannot be inserted
-        * due to max_entries limit
-        */
-       key = 0;
-       assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 &&
-              errno == E2BIG);
-
-       /* check that key = 0 doesn't exist */
-       assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
-
-       /* iterate over two elements */
-       while (!bpf_get_next_key(map_fd, &key, &next_key)) {
-               assert((expected_key_mask & next_key) == next_key);
-               expected_key_mask &= ~next_key;
-
-               assert(bpf_lookup_elem(map_fd, &next_key, value) == 0);
-               for (i = 0; i < nr_cpus; i++)
-                       assert(value[i] == i + 100);
-
-               key = next_key;
-       }
-       assert(errno == ENOENT);
-
-       /* Update with BPF_EXIST */
-       key = 1;
-       assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == 0);
-
-       /* delete both elements */
-       key = 1;
-       assert(bpf_delete_elem(map_fd, &key) == 0);
-       key = 2;
-       assert(bpf_delete_elem(map_fd, &key) == 0);
-       assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);
-
-       key = 0;
-       /* check that map is empty */
-       assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 &&
-              errno == ENOENT);
-       close(map_fd);
-}
-
-static void test_arraymap_sanity(int i, void *data)
-{
-       int key, next_key, map_fd;
-       long long value;
-
-       map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
-                               2, 0);
-       if (map_fd < 0) {
-               printf("failed to create arraymap '%s'\n", strerror(errno));
-               exit(1);
-       }
-
-       key = 1;
-       value = 1234;
-       /* insert key=1 element */
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
-
-       value = 0;
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
-              errno == EEXIST);
-
-       /* check that key=1 can be found */
-       assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);
-
-       key = 0;
-       /* check that key=0 is also found and zero initialized */
-       assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0);
-
-
-       /* key=0 and key=1 were inserted, check that key=2 cannot be inserted
-        * due to max_entries limit
-        */
-       key = 2;
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
-              errno == E2BIG);
-
-       /* check that key = 2 doesn't exist */
-       assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
-
-       /* iterate over two elements */
-       assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
-              next_key == 0);
-       assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
-              next_key == 1);
-       assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
-              errno == ENOENT);
-
-       /* delete shouldn't succeed */
-       key = 1;
-       assert(bpf_delete_elem(map_fd, &key) == -1 && errno == EINVAL);
-
-       close(map_fd);
-}
-
-static void test_percpu_arraymap_many_keys(void)
-{
-       unsigned nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
-       unsigned nr_keys = 20000;
-       long values[nr_cpus];
-       int key, map_fd, i;
-
-       map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
-                               sizeof(values[0]), nr_keys, 0);
-       if (map_fd < 0) {
-               printf("failed to create per-cpu arraymap '%s'\n",
-                      strerror(errno));
-               exit(1);
-       }
-
-       for (i = 0; i < nr_cpus; i++)
-               values[i] = i + 10;
-
-       for (key = 0; key < nr_keys; key++)
-               assert(bpf_update_elem(map_fd, &key, values, BPF_ANY) == 0);
-
-       for (key = 0; key < nr_keys; key++) {
-               for (i = 0; i < nr_cpus; i++)
-                       values[i] = 0;
-               assert(bpf_lookup_elem(map_fd, &key, values) == 0);
-               for (i = 0; i < nr_cpus; i++)
-                       assert(values[i] == i + 10);
-       }
-
-       close(map_fd);
-}
-
-static void test_percpu_arraymap_sanity(int i, void *data)
-{
-       unsigned nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
-       long values[nr_cpus];
-       int key, next_key, map_fd;
-
-       map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
-                               sizeof(values[0]), 2, 0);
-       if (map_fd < 0) {
-               printf("failed to create arraymap '%s'\n", strerror(errno));
-               exit(1);
-       }
-
-       for (i = 0; i < nr_cpus; i++)
-               values[i] = i + 100;
-
-       key = 1;
-       /* insert key=1 element */
-       assert(bpf_update_elem(map_fd, &key, values, BPF_ANY) == 0);
-
-       values[0] = 0;
-       assert(bpf_update_elem(map_fd, &key, values, BPF_NOEXIST) == -1 &&
-              errno == EEXIST);
-
-       /* check that key=1 can be found */
-       assert(bpf_lookup_elem(map_fd, &key, values) == 0 && values[0] == 100);
-
-       key = 0;
-       /* check that key=0 is also found and zero initialized */
-       assert(bpf_lookup_elem(map_fd, &key, values) == 0 &&
-              values[0] == 0 && values[nr_cpus - 1] == 0);
-
-
-       /* check that key=2 cannot be inserted due to max_entries limit */
-       key = 2;
-       assert(bpf_update_elem(map_fd, &key, values, BPF_EXIST) == -1 &&
-              errno == E2BIG);
-
-       /* check that key = 2 doesn't exist */
-       assert(bpf_lookup_elem(map_fd, &key, values) == -1 && errno == ENOENT);
-
-       /* iterate over two elements */
-       assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
-              next_key == 0);
-       assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
-              next_key == 1);
-       assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
-              errno == ENOENT);
-
-       /* delete shouldn't succeed */
-       key = 1;
-       assert(bpf_delete_elem(map_fd, &key) == -1 && errno == EINVAL);
-
-       close(map_fd);
-}
-
-#define MAP_SIZE (32 * 1024)
-static void test_map_large(void)
-{
-       struct bigkey {
-               int a;
-               char b[116];
-               long long c;
-       } key;
-       int map_fd, i, value;
-
-       /* allocate 4Mbyte of memory */
-       map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
-                               MAP_SIZE, map_flags);
-       if (map_fd < 0) {
-               printf("failed to create large map '%s'\n", strerror(errno));
-               exit(1);
-       }
-
-       for (i = 0; i < MAP_SIZE; i++) {
-               key = (struct bigkey) {.c = i};
-               value = i;
-               assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
-       }
-       key.c = -1;
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
-              errno == E2BIG);
-
-       /* iterate through all elements */
-       for (i = 0; i < MAP_SIZE; i++)
-               assert(bpf_get_next_key(map_fd, &key, &key) == 0);
-       assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
-
-       key.c = 0;
-       assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0);
-       key.a = 1;
-       assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);
-
-       close(map_fd);
-}
-
-/* fork N children and wait for them to complete */
-static void run_parallel(int tasks, void (*fn)(int i, void *data), void *data)
-{
-       pid_t pid[tasks];
-       int i;
-
-       for (i = 0; i < tasks; i++) {
-               pid[i] = fork();
-               if (pid[i] == 0) {
-                       fn(i, data);
-                       exit(0);
-               } else if (pid[i] == -1) {
-                       printf("couldn't spawn #%d process\n", i);
-                       exit(1);
-               }
-       }
-       for (i = 0; i < tasks; i++) {
-               int status;
-
-               assert(waitpid(pid[i], &status, 0) == pid[i]);
-               assert(status == 0);
-       }
-}
-
-static void test_map_stress(void)
-{
-       run_parallel(100, test_hashmap_sanity, NULL);
-       run_parallel(100, test_percpu_hashmap_sanity, NULL);
-       run_parallel(100, test_arraymap_sanity, NULL);
-       run_parallel(100, test_percpu_arraymap_sanity, NULL);
-}
-
-#define TASKS 1024
-#define DO_UPDATE 1
-#define DO_DELETE 0
-static void do_work(int fn, void *data)
-{
-       int map_fd = ((int *)data)[0];
-       int do_update = ((int *)data)[1];
-       int i;
-       int key, value;
-
-       for (i = fn; i < MAP_SIZE; i += TASKS) {
-               key = value = i;
-               if (do_update) {
-                       assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
-                       assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == 0);
-               } else {
-                       assert(bpf_delete_elem(map_fd, &key) == 0);
-               }
-       }
-}
-
-static void test_map_parallel(void)
-{
-       int i, map_fd, key = 0, value = 0;
-       int data[2];
-
-       map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
-                               MAP_SIZE, map_flags);
-       if (map_fd < 0) {
-               printf("failed to create map for parallel test '%s'\n",
-                      strerror(errno));
-               exit(1);
-       }
-
-       data[0] = map_fd;
-       data[1] = DO_UPDATE;
-       /* use the same map_fd in children to add elements to this map
-        * child_0 adds key=0, key=1024, key=2048, ...
-        * child_1 adds key=1, key=1025, key=2049, ...
-        * child_1023 adds key=1023, ...
-        */
-       run_parallel(TASKS, do_work, data);
-
-       /* check that key=0 is already there */
-       assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
-              errno == EEXIST);
-
-       /* check that all elements were inserted */
-       key = -1;
-       for (i = 0; i < MAP_SIZE; i++)
-               assert(bpf_get_next_key(map_fd, &key, &key) == 0);
-       assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
-
-       /* another check for all elements */
-       for (i = 0; i < MAP_SIZE; i++) {
-               key = MAP_SIZE - i - 1;
-               assert(bpf_lookup_elem(map_fd, &key, &value) == 0 &&
-                      value == key);
-       }
-
-       /* now let's delete all elemenets in parallel */
-       data[1] = DO_DELETE;
-       run_parallel(TASKS, do_work, data);
-
-       /* nothing should be left */
-       key = -1;
-       assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
-}
-
-static void run_all_tests(void)
-{
-       test_hashmap_sanity(0, NULL);
-       test_percpu_hashmap_sanity(0, NULL);
-       test_arraymap_sanity(0, NULL);
-       test_percpu_arraymap_sanity(0, NULL);
-       test_percpu_arraymap_many_keys();
-
-       test_map_large();
-       test_map_parallel();
-       test_map_stress();
-}
-
-int main(void)
-{
-       map_flags = 0;
-       run_all_tests();
-       map_flags = BPF_F_NO_PREALLOC;
-       run_all_tests();
-       printf("test_maps: OK\n");
-       return 0;
-}
index 3276625595b2b79748f84633bf3081160614cfb5..122153b16ea4eeba1e84bf30a71a3dda199ae534 100644 (file)
                .off   = OFF,                                   \
                .imm   = IMM })
 
+/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */
+
+#define BPF_LD_IMM64(DST, IMM)                                 \
+       BPF_LD_IMM64_RAW(DST, 0, IMM)
+
+#define BPF_LD_IMM64_RAW(DST, SRC, IMM)                                \
+       ((struct bpf_insn) {                                    \
+               .code  = BPF_LD | BPF_DW | BPF_IMM,             \
+               .dst_reg = DST,                                 \
+               .src_reg = SRC,                                 \
+               .off   = 0,                                     \
+               .imm   = (__u32) (IMM) }),                      \
+       ((struct bpf_insn) {                                    \
+               .code  = 0, /* zero is reserved opcode */       \
+               .dst_reg = 0,                                   \
+               .src_reg = 0,                                   \
+               .off   = 0,                                     \
+               .imm   = ((__u64) (IMM)) >> 32 })
+
+/* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */
+
+#define BPF_LD_MAP_FD(DST, MAP_FD)                             \
+       BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
+
 /* Program exit */
 
 #define BPF_EXIT_INSN()                                                \
index f770dba2a6f636024c5254b5f9a6d747e8abff3a..a3144a3de3a8b581deb37e23e60c94d0035102af 100644 (file)
@@ -1,4 +1,5 @@
-TARGETS = breakpoints
+TARGETS =  bpf
+TARGETS += breakpoints
 TARGETS += capabilities
 TARGETS += cpu-hotplug
 TARGETS += efivarfs
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
new file mode 100644 (file)
index 0000000..3c59f96
--- /dev/null
@@ -0,0 +1,2 @@
+test_verifier
+test_maps
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
new file mode 100644 (file)
index 0000000..4761e2d
--- /dev/null
@@ -0,0 +1,13 @@
+CFLAGS += -Wall -O2
+
+test_objs = test_verifier test_maps
+
+TEST_PROGS := test_verifier test_maps test_kmod.sh
+TEST_FILES := $(test_objs)
+
+all: $(test_objs)
+
+include ../lib.mk
+
+clean:
+       $(RM) $(test_objs)
diff --git a/tools/testing/selftests/bpf/bpf_sys.h b/tools/testing/selftests/bpf/bpf_sys.h
new file mode 100644 (file)
index 0000000..6b4565f
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef __BPF_SYS__
+#define __BPF_SYS__
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <sys/syscall.h>
+
+#include <linux/bpf.h>
+
+static inline __u64 bpf_ptr_to_u64(const void *ptr)
+{
+       return (__u64)(unsigned long) ptr;
+}
+
+static inline int bpf(int cmd, union bpf_attr *attr, unsigned int size)
+{
+#ifdef __NR_bpf
+       return syscall(__NR_bpf, cmd, attr, size);
+#else
+       fprintf(stderr, "No bpf syscall, kernel headers too old?\n");
+       errno = ENOSYS;
+       return -1;
+#endif
+}
+
+static inline int bpf_map_lookup(int fd, const void *key, void *value)
+{
+       union bpf_attr attr = {};
+
+       attr.map_fd = fd;
+       attr.key = bpf_ptr_to_u64(key);
+       attr.value = bpf_ptr_to_u64(value);
+
+       return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+}
+
+static inline int bpf_map_update(int fd, const void *key, const void *value,
+                                uint64_t flags)
+{
+       union bpf_attr attr = {};
+
+       attr.map_fd = fd;
+       attr.key = bpf_ptr_to_u64(key);
+       attr.value = bpf_ptr_to_u64(value);
+       attr.flags = flags;
+
+       return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
+}
+
+static inline int bpf_map_delete(int fd, const void *key)
+{
+       union bpf_attr attr = {};
+
+       attr.map_fd = fd;
+       attr.key = bpf_ptr_to_u64(key);
+
+       return bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
+}
+
+static inline int bpf_map_next_key(int fd, const void *key, void *next_key)
+{
+       union bpf_attr attr = {};
+
+       attr.map_fd = fd;
+       attr.key = bpf_ptr_to_u64(key);
+       attr.next_key = bpf_ptr_to_u64(next_key);
+
+       return bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
+}
+
+static inline int bpf_map_create(enum bpf_map_type type, uint32_t size_key,
+                                uint32_t size_value, uint32_t max_elem,
+                                uint32_t flags)
+{
+       union bpf_attr attr = {};
+
+       attr.map_type = type;
+       attr.key_size = size_key;
+       attr.value_size = size_value;
+       attr.max_entries = max_elem;
+       attr.map_flags = flags;
+
+       return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
+}
+
+static inline int bpf_prog_load(enum bpf_prog_type type,
+                               const struct bpf_insn *insns, size_t size_insns,
+                               const char *license, char *log, size_t size_log)
+{
+       union bpf_attr attr = {};
+
+       attr.prog_type = type;
+       attr.insns = bpf_ptr_to_u64(insns);
+       attr.insn_cnt = size_insns / sizeof(struct bpf_insn);
+       attr.license = bpf_ptr_to_u64(license);
+
+       if (size_log > 0) {
+               attr.log_buf = bpf_ptr_to_u64(log);
+               attr.log_size = size_log;
+               attr.log_level = 1;
+               log[0] = 0;
+       }
+
+       return bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+}
+
+#endif /* __BPF_SYS__ */
diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
new file mode 100644 (file)
index 0000000..52d53ed
--- /dev/null
@@ -0,0 +1,5 @@
+CONFIG_BPF=y
+CONFIG_BPF_SYSCALL=y
+CONFIG_NET_CLS_BPF=m
+CONFIG_BPF_EVENTS=y
+CONFIG_TEST_BPF=m
diff --git a/tools/testing/selftests/bpf/test_kmod.sh b/tools/testing/selftests/bpf/test_kmod.sh
new file mode 100755 (executable)
index 0000000..92e627a
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+SRC_TREE=../../../../
+
+test_run()
+{
+       sysctl -w net.core.bpf_jit_enable=$1 2>&1 > /dev/null
+       sysctl -w net.core.bpf_jit_harden=$2 2>&1 > /dev/null
+
+       echo "[ JIT enabled:$1 hardened:$2 ]"
+       dmesg -C
+       insmod $SRC_TREE/lib/test_bpf.ko 2> /dev/null
+       if [ $? -ne 0 ]; then
+               rc=1
+       fi
+       rmmod  test_bpf 2> /dev/null
+       dmesg | grep FAIL
+}
+
+test_save()
+{
+       JE=`sysctl -n net.core.bpf_jit_enable`
+       JH=`sysctl -n net.core.bpf_jit_harden`
+}
+
+test_restore()
+{
+       sysctl -w net.core.bpf_jit_enable=$JE 2>&1 > /dev/null
+       sysctl -w net.core.bpf_jit_harden=$JH 2>&1 > /dev/null
+}
+
+rc=0
+test_save
+test_run 0 0
+test_run 1 0
+test_run 1 1
+test_run 1 2
+test_restore
+exit $rc
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
new file mode 100644 (file)
index 0000000..ee384f0
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+ * Testsuite for eBPF maps
+ *
+ * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
+ * Copyright (c) 2016 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include <sys/wait.h>
+#include <sys/resource.h>
+
+#include <linux/bpf.h>
+
+#include "bpf_sys.h"
+
+static int map_flags;
+
+static void test_hashmap(int task, void *data)
+{
+       long long key, next_key, value;
+       int fd;
+
+       fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
+                           2, map_flags);
+       if (fd < 0) {
+               printf("Failed to create hashmap '%s'!\n", strerror(errno));
+               exit(1);
+       }
+
+       key = 1;
+       value = 1234;
+       /* Insert key=1 element. */
+       assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0);
+
+       value = 0;
+       /* BPF_NOEXIST means add new element if it doesn't exist. */
+       assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+              /* key=1 already exists. */
+              errno == EEXIST);
+
+       /* -1 is an invalid flag. */
+       assert(bpf_map_update(fd, &key, &value, -1) == -1 && errno == EINVAL);
+
+       /* Check that key=1 can be found. */
+       assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 1234);
+
+       key = 2;
+       /* Check that key=2 is not found. */
+       assert(bpf_map_lookup(fd, &key, &value) == -1 && errno == ENOENT);
+
+       /* BPF_EXIST means update existing element. */
+       assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == -1 &&
+              /* key=2 is not there. */
+              errno == ENOENT);
+
+       /* Insert key=2 element. */
+       assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == 0);
+
+       /* key=1 and key=2 were inserted, check that key=0 cannot be
+        * inserted due to max_entries limit.
+        */
+       key = 0;
+       assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+              errno == E2BIG);
+
+       /* Update existing element, though the map is full. */
+       key = 1;
+       assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == 0);
+       key = 2;
+       assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0);
+       key = 1;
+       assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0);
+
+       /* Check that key = 0 doesn't exist. */
+       key = 0;
+       assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT);
+
+       /* Iterate over two elements. */
+       assert(bpf_map_next_key(fd, &key, &next_key) == 0 &&
+              (next_key == 1 || next_key == 2));
+       assert(bpf_map_next_key(fd, &next_key, &next_key) == 0 &&
+              (next_key == 1 || next_key == 2));
+       assert(bpf_map_next_key(fd, &next_key, &next_key) == -1 &&
+              errno == ENOENT);
+
+       /* Delete both elements. */
+       key = 1;
+       assert(bpf_map_delete(fd, &key) == 0);
+       key = 2;
+       assert(bpf_map_delete(fd, &key) == 0);
+       assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT);
+
+       key = 0;
+       /* Check that map is empty. */
+       assert(bpf_map_next_key(fd, &key, &next_key) == -1 &&
+              errno == ENOENT);
+
+       close(fd);
+}
+
+static void test_hashmap_percpu(int task, void *data)
+{
+       unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+       long long value[nr_cpus];
+       long long key, next_key;
+       int expected_key_mask = 0;
+       int fd, i;
+
+       fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
+                           sizeof(value[0]), 2, map_flags);
+       if (fd < 0) {
+               printf("Failed to create hashmap '%s'!\n", strerror(errno));
+               exit(1);
+       }
+
+       for (i = 0; i < nr_cpus; i++)
+               value[i] = i + 100;
+
+       key = 1;
+       /* Insert key=1 element. */
+       assert(!(expected_key_mask & key));
+       assert(bpf_map_update(fd, &key, value, BPF_ANY) == 0);
+       expected_key_mask |= key;
+
+       /* BPF_NOEXIST means add new element if it doesn't exist. */
+       assert(bpf_map_update(fd, &key, value, BPF_NOEXIST) == -1 &&
+              /* key=1 already exists. */
+              errno == EEXIST);
+
+       /* -1 is an invalid flag. */
+       assert(bpf_map_update(fd, &key, value, -1) == -1 && errno == EINVAL);
+
+       /* Check that key=1 can be found. Value could be 0 if the lookup
+        * was run from a different CPU.
+        */
+       value[0] = 1;
+       assert(bpf_map_lookup(fd, &key, value) == 0 && value[0] == 100);
+
+       key = 2;
+       /* Check that key=2 is not found. */
+       assert(bpf_map_lookup(fd, &key, value) == -1 && errno == ENOENT);
+
+       /* BPF_EXIST means update existing element. */
+       assert(bpf_map_update(fd, &key, value, BPF_EXIST) == -1 &&
+              /* key=2 is not there. */
+              errno == ENOENT);
+
+       /* Insert key=2 element. */
+       assert(!(expected_key_mask & key));
+       assert(bpf_map_update(fd, &key, value, BPF_NOEXIST) == 0);
+       expected_key_mask |= key;
+
+       /* key=1 and key=2 were inserted, check that key=0 cannot be
+        * inserted due to max_entries limit.
+        */
+       key = 0;
+       assert(bpf_map_update(fd, &key, value, BPF_NOEXIST) == -1 &&
+              errno == E2BIG);
+
+       /* Check that key = 0 doesn't exist. */
+       assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT);
+
+       /* Iterate over two elements. */
+       while (!bpf_map_next_key(fd, &key, &next_key)) {
+               assert((expected_key_mask & next_key) == next_key);
+               expected_key_mask &= ~next_key;
+
+               assert(bpf_map_lookup(fd, &next_key, value) == 0);
+
+               for (i = 0; i < nr_cpus; i++)
+                       assert(value[i] == i + 100);
+
+               key = next_key;
+       }
+       assert(errno == ENOENT);
+
+       /* Update with BPF_EXIST. */
+       key = 1;
+       assert(bpf_map_update(fd, &key, value, BPF_EXIST) == 0);
+
+       /* Delete both elements. */
+       key = 1;
+       assert(bpf_map_delete(fd, &key) == 0);
+       key = 2;
+       assert(bpf_map_delete(fd, &key) == 0);
+       assert(bpf_map_delete(fd, &key) == -1 && errno == ENOENT);
+
+       key = 0;
+       /* Check that map is empty. */
+       assert(bpf_map_next_key(fd, &key, &next_key) == -1 &&
+              errno == ENOENT);
+
+       close(fd);
+}
+
+static void test_arraymap(int task, void *data)
+{
+       int key, next_key, fd;
+       long long value;
+
+       fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
+                           2, 0);
+       if (fd < 0) {
+               printf("Failed to create arraymap '%s'!\n", strerror(errno));
+               exit(1);
+       }
+
+       key = 1;
+       value = 1234;
+       /* Insert key=1 element. */
+       assert(bpf_map_update(fd, &key, &value, BPF_ANY) == 0);
+
+       value = 0;
+       assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+              errno == EEXIST);
+
+       /* Check that key=1 can be found. */
+       assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 1234);
+
+       key = 0;
+       /* Check that key=0 is also found and zero initialized. */
+       assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 0);
+
+       /* key=0 and key=1 were inserted, check that key=2 cannot be inserted
+        * due to max_entries limit.
+        */
+       key = 2;
+       assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == -1 &&
+              errno == E2BIG);
+
+       /* Check that key = 2 doesn't exist. */
+       assert(bpf_map_lookup(fd, &key, &value) == -1 && errno == ENOENT);
+
+       /* Iterate over two elements. */
+       assert(bpf_map_next_key(fd, &key, &next_key) == 0 &&
+              next_key == 0);
+       assert(bpf_map_next_key(fd, &next_key, &next_key) == 0 &&
+              next_key == 1);
+       assert(bpf_map_next_key(fd, &next_key, &next_key) == -1 &&
+              errno == ENOENT);
+
+       /* Delete shouldn't succeed. */
+       key = 1;
+       assert(bpf_map_delete(fd, &key) == -1 && errno == EINVAL);
+
+       close(fd);
+}
+
+static void test_arraymap_percpu(int task, void *data)
+{
+       unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+       int key, next_key, fd, i;
+       long values[nr_cpus];
+
+       fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
+                           sizeof(values[0]), 2, 0);
+       if (fd < 0) {
+               printf("Failed to create arraymap '%s'!\n", strerror(errno));
+               exit(1);
+       }
+
+       for (i = 0; i < nr_cpus; i++)
+               values[i] = i + 100;
+
+       key = 1;
+       /* Insert key=1 element. */
+       assert(bpf_map_update(fd, &key, values, BPF_ANY) == 0);
+
+       values[0] = 0;
+       assert(bpf_map_update(fd, &key, values, BPF_NOEXIST) == -1 &&
+              errno == EEXIST);
+
+       /* Check that key=1 can be found. */
+       assert(bpf_map_lookup(fd, &key, values) == 0 && values[0] == 100);
+
+       key = 0;
+       /* Check that key=0 is also found and zero initialized. */
+       assert(bpf_map_lookup(fd, &key, values) == 0 &&
+              values[0] == 0 && values[nr_cpus - 1] == 0);
+
+       /* Check that key=2 cannot be inserted due to max_entries limit. */
+       key = 2;
+       assert(bpf_map_update(fd, &key, values, BPF_EXIST) == -1 &&
+              errno == E2BIG);
+
+       /* Check that key = 2 doesn't exist. */
+       assert(bpf_map_lookup(fd, &key, values) == -1 && errno == ENOENT);
+
+       /* Iterate over two elements. */
+       assert(bpf_map_next_key(fd, &key, &next_key) == 0 &&
+              next_key == 0);
+       assert(bpf_map_next_key(fd, &next_key, &next_key) == 0 &&
+              next_key == 1);
+       assert(bpf_map_next_key(fd, &next_key, &next_key) == -1 &&
+              errno == ENOENT);
+
+       /* Delete shouldn't succeed. */
+       key = 1;
+       assert(bpf_map_delete(fd, &key) == -1 && errno == EINVAL);
+
+       close(fd);
+}
+
+static void test_arraymap_percpu_many_keys(void)
+{
+       unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+       unsigned int nr_keys = 20000;
+       long values[nr_cpus];
+       int key, fd, i;
+
+       fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
+                           sizeof(values[0]), nr_keys, 0);
+       if (fd < 0) {
+               printf("Failed to create per-cpu arraymap '%s'!\n",
+                      strerror(errno));
+               exit(1);
+       }
+
+       for (i = 0; i < nr_cpus; i++)
+               values[i] = i + 10;
+
+       for (key = 0; key < nr_keys; key++)
+               assert(bpf_map_update(fd, &key, values, BPF_ANY) == 0);
+
+       for (key = 0; key < nr_keys; key++) {
+               for (i = 0; i < nr_cpus; i++)
+                       values[i] = 0;
+
+               assert(bpf_map_lookup(fd, &key, values) == 0);
+
+               for (i = 0; i < nr_cpus; i++)
+                       assert(values[i] == i + 10);
+       }
+
+       close(fd);
+}
+
+#define MAP_SIZE (32 * 1024)
+
+static void test_map_large(void)
+{
+       struct bigkey {
+               int a;
+               char b[116];
+               long long c;
+       } key;
+       int fd, i, value;
+
+       fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
+                           MAP_SIZE, map_flags);
+       if (fd < 0) {
+               printf("Failed to create large map '%s'!\n", strerror(errno));
+               exit(1);
+       }
+
+       for (i = 0; i < MAP_SIZE; i++) {
+               key = (struct bigkey) { .c = i };
+               value = i;
+
+               assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == 0);
+       }
+
+       key.c = -1;
+       assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+              errno == E2BIG);
+
+       /* Iterate through all elements. */
+       for (i = 0; i < MAP_SIZE; i++)
+               assert(bpf_map_next_key(fd, &key, &key) == 0);
+       assert(bpf_map_next_key(fd, &key, &key) == -1 && errno == ENOENT);
+
+       key.c = 0;
+       assert(bpf_map_lookup(fd, &key, &value) == 0 && value == 0);
+       key.a = 1;
+       assert(bpf_map_lookup(fd, &key, &value) == -1 && errno == ENOENT);
+
+       close(fd);
+}
+
+static void run_parallel(int tasks, void (*fn)(int task, void *data),
+                        void *data)
+{
+       pid_t pid[tasks];
+       int i;
+
+       for (i = 0; i < tasks; i++) {
+               pid[i] = fork();
+               if (pid[i] == 0) {
+                       fn(i, data);
+                       exit(0);
+               } else if (pid[i] == -1) {
+                       printf("Couldn't spawn #%d process!\n", i);
+                       exit(1);
+               }
+       }
+
+       for (i = 0; i < tasks; i++) {
+               int status;
+
+               assert(waitpid(pid[i], &status, 0) == pid[i]);
+               assert(status == 0);
+       }
+}
+
+static void test_map_stress(void)
+{
+       run_parallel(100, test_hashmap, NULL);
+       run_parallel(100, test_hashmap_percpu, NULL);
+
+       run_parallel(100, test_arraymap, NULL);
+       run_parallel(100, test_arraymap_percpu, NULL);
+}
+
+#define TASKS 1024
+
+#define DO_UPDATE 1
+#define DO_DELETE 0
+
+static void do_work(int fn, void *data)
+{
+       int do_update = ((int *)data)[1];
+       int fd = ((int *)data)[0];
+       int i, key, value;
+
+       for (i = fn; i < MAP_SIZE; i += TASKS) {
+               key = value = i;
+
+               if (do_update) {
+                       assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == 0);
+                       assert(bpf_map_update(fd, &key, &value, BPF_EXIST) == 0);
+               } else {
+                       assert(bpf_map_delete(fd, &key) == 0);
+               }
+       }
+}
+
+static void test_map_parallel(void)
+{
+       int i, fd, key = 0, value = 0;
+       int data[2];
+
+       fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
+                           MAP_SIZE, map_flags);
+       if (fd < 0) {
+               printf("Failed to create map for parallel test '%s'!\n",
+                      strerror(errno));
+               exit(1);
+       }
+
+       /* Use the same fd in children to add elements to this map:
+        * child_0 adds key=0, key=1024, key=2048, ...
+        * child_1 adds key=1, key=1025, key=2049, ...
+        * child_1023 adds key=1023, ...
+        */
+       data[0] = fd;
+       data[1] = DO_UPDATE;
+       run_parallel(TASKS, do_work, data);
+
+       /* Check that key=0 is already there. */
+       assert(bpf_map_update(fd, &key, &value, BPF_NOEXIST) == -1 &&
+              errno == EEXIST);
+
+       /* Check that all elements were inserted. */
+       key = -1;
+       for (i = 0; i < MAP_SIZE; i++)
+               assert(bpf_map_next_key(fd, &key, &key) == 0);
+       assert(bpf_map_next_key(fd, &key, &key) == -1 && errno == ENOENT);
+
+       /* Another check for all elements */
+       for (i = 0; i < MAP_SIZE; i++) {
+               key = MAP_SIZE - i - 1;
+
+               assert(bpf_map_lookup(fd, &key, &value) == 0 &&
+                      value == key);
+       }
+
+       /* Now let's delete all elemenets in parallel. */
+       data[1] = DO_DELETE;
+       run_parallel(TASKS, do_work, data);
+
+       /* Nothing should be left. */
+       key = -1;
+       assert(bpf_map_next_key(fd, &key, &key) == -1 && errno == ENOENT);
+}
+
+static void run_all_tests(void)
+{
+       test_hashmap(0, NULL);
+       test_hashmap_percpu(0, NULL);
+
+       test_arraymap(0, NULL);
+       test_arraymap_percpu(0, NULL);
+
+       test_arraymap_percpu_many_keys();
+
+       test_map_large();
+       test_map_parallel();
+       test_map_stress();
+}
+
+int main(void)
+{
+       struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
+
+       setrlimit(RLIMIT_MEMLOCK, &rinf);
+
+       map_flags = 0;
+       run_all_tests();
+
+       map_flags = BPF_F_NO_PREALLOC;
+       run_all_tests();
+
+       printf("test_maps: OK\n");
+       return 0;
+}
similarity index 78%
rename from samples/bpf/test_verifier.c
rename to tools/testing/selftests/bpf/test_verifier.c
index 369ffaad3799a0590cfd86fd9c19d1c56feeb639..0ef8eaf6cea7c0bd161c5778e30d3b9b899f91f1 100644 (file)
@@ -7,29 +7,39 @@
  * modify it under the terms of version 2 of the GNU General Public
  * License as published by the Free Software Foundation.
  */
+
 #include <stdio.h>
 #include <unistd.h>
-#include <linux/bpf.h>
 #include <errno.h>
-#include <linux/unistd.h>
 #include <string.h>
-#include <linux/filter.h>
 #include <stddef.h>
 #include <stdbool.h>
+#include <sched.h>
+
 #include <sys/resource.h>
-#include "libbpf.h"
 
-#define MAX_INSNS 512
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+#include <linux/unistd.h>
+#include <linux/filter.h>
+#include <linux/bpf_perf_event.h>
+#include <linux/bpf.h>
+
+#include "../../../include/linux/filter.h"
+
+#include "bpf_sys.h"
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
 
-#define MAX_FIXUPS 8
+#define MAX_INSNS      512
+#define MAX_FIXUPS     8
 
 struct bpf_test {
        const char *descr;
        struct bpf_insn insns[MAX_INSNS];
-       int fixup[MAX_FIXUPS];
-       int prog_array_fixup[MAX_FIXUPS];
-       int test_val_map_fixup[MAX_FIXUPS];
+       int fixup_map1[MAX_FIXUPS];
+       int fixup_map2[MAX_FIXUPS];
+       int fixup_prog[MAX_FIXUPS];
        const char *errstr;
        const char *errstr_unpriv;
        enum {
@@ -44,15 +54,12 @@ struct bpf_test {
  * actually the end of the structure.
  */
 #define MAX_ENTRIES 11
+
 struct test_val {
-       unsigned index;
+       unsigned int index;
        int foo[MAX_ENTRIES];
 };
 
-struct other_val {
-       unsigned int action[32];
-};
-
 static struct bpf_test tests[] = {
        {
                "add+sub+mul",
@@ -287,10 +294,11 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {2},
+               .fixup_map1 = { 2 },
                .errstr = "invalid indirect read from stack",
                .result = REJECT,
        },
@@ -307,8 +315,10 @@ static struct bpf_test tests[] = {
        {
                "invalid argument register",
                .insns = {
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_cgroup_classid),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_cgroup_classid),
                        BPF_EXIT_INSN(),
                },
                .errstr = "R1 !read_ok",
@@ -319,9 +329,11 @@ static struct bpf_test tests[] = {
                "non-invalid argument register",
                .insns = {
                        BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_1),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_cgroup_classid),
                        BPF_ALU64_REG(BPF_MOV, BPF_REG_1, BPF_REG_6),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_cgroup_classid),
                        BPF_EXIT_INSN(),
                },
                .result = ACCEPT,
@@ -332,10 +344,8 @@ static struct bpf_test tests[] = {
                .insns = {
                        /* spill R1(ctx) into stack */
                        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
-
                        /* fill it back into R2 */
                        BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
-
                        /* should be able to access R0 = *(R2 + 8) */
                        /* BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), */
                        BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
@@ -363,13 +373,10 @@ static struct bpf_test tests[] = {
                .insns = {
                        /* spill R1(ctx) into stack */
                        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
-
                        /* mess up with R1 pointer on stack */
                        BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
-
                        /* fill back into R0 should fail */
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
-
                        BPF_EXIT_INSN(),
                },
                .errstr_unpriv = "attempt to corrupt spilled",
@@ -483,7 +490,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_delete_elem),
                        BPF_EXIT_INSN(),
                },
                .errstr = "fd 0 is not pointing to valid bpf_map",
@@ -496,11 +504,12 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {3},
+               .fixup_map1 = { 3 },
                .errstr = "R0 invalid mem access 'map_value_or_null'",
                .result = REJECT,
        },
@@ -511,12 +520,13 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
                        BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {3},
+               .fixup_map1 = { 3 },
                .errstr = "misaligned access",
                .result = REJECT,
        },
@@ -527,14 +537,15 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
                        BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
                        BPF_EXIT_INSN(),
                        BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {3},
+               .fixup_map1 = { 3 },
                .errstr = "R0 invalid mem access",
                .errstr_unpriv = "R0 leaks addr",
                .result = REJECT,
@@ -619,10 +630,11 @@ static struct bpf_test tests[] = {
                        BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_delete_elem),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {24},
+               .fixup_map1 = { 24 },
                .errstr_unpriv = "R1 pointer comparison",
                .result_unpriv = REJECT,
                .result = ACCEPT,
@@ -763,7 +775,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
                        BPF_EXIT_INSN(),
                        BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
@@ -771,7 +784,7 @@ static struct bpf_test tests[] = {
                                    offsetof(struct __sk_buff, pkt_type)),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {4},
+               .fixup_map1 = { 4 },
                .errstr = "different pointers",
                .errstr_unpriv = "R1 pointer comparison",
                .result = REJECT,
@@ -787,13 +800,14 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
                        BPF_EXIT_INSN(),
                        BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
                        BPF_JMP_IMM(BPF_JA, 0, 0, -12),
                },
-               .fixup = {6},
+               .fixup_map1 = { 6 },
                .errstr = "different pointers",
                .errstr_unpriv = "R1 pointer comparison",
                .result = REJECT,
@@ -810,13 +824,14 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
                        BPF_EXIT_INSN(),
                        BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
                        BPF_JMP_IMM(BPF_JA, 0, 0, -13),
                },
-               .fixup = {7},
+               .fixup_map1 = { 7 },
                .errstr = "different pointers",
                .errstr_unpriv = "R1 pointer comparison",
                .result = REJECT,
@@ -1039,7 +1054,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
                        BPF_MOV64_IMM(BPF_REG_2, 8),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_1),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_trace_printk),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_trace_printk),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1056,11 +1072,12 @@ static struct bpf_test tests[] = {
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
                        BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_update_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {3},
+               .fixup_map1 = { 3 },
                .errstr_unpriv = "R4 leaks addr",
                .result_unpriv = REJECT,
                .result = ACCEPT,
@@ -1072,11 +1089,12 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {3},
+               .fixup_map1 = { 3 },
                .errstr = "invalid indirect read from stack off -8+0 size 8",
                .result = REJECT,
        },
@@ -1127,6 +1145,112 @@ static struct bpf_test tests[] = {
                .errstr = "invalid bpf_context access",
                .result = REJECT,
        },
+       {
+               "unpriv: spill/fill of ctx",
+               .insns = {
+                       BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .result = ACCEPT,
+       },
+       {
+               "unpriv: spill/fill of ctx 2",
+               .insns = {
+                       BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_hash_recalc),
+                       BPF_EXIT_INSN(),
+               },
+               .result = ACCEPT,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       },
+       {
+               "unpriv: spill/fill of ctx 3",
+               .insns = {
+                       BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, 0),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_hash_recalc),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "R1 type=fp expected=ctx",
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       },
+       {
+               "unpriv: spill/fill of ctx 4",
+               .insns = {
+                       BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_10,
+                                    BPF_REG_0, -8, 0),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_hash_recalc),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "R1 type=inv expected=ctx",
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       },
+       {
+               "unpriv: spill/fill of different pointers stx",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 42),
+                       BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_2, 0),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+                       BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3,
+                                   offsetof(struct __sk_buff, mark)),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "same insn cannot be used with different pointers",
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       },
+       {
+               "unpriv: spill/fill of different pointers ldx",
+               .insns = {
+                       BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2,
+                                     -(__s32)offsetof(struct bpf_perf_event_data,
+                                                      sample_period) - 8),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_2, 0),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1,
+                                   offsetof(struct bpf_perf_event_data,
+                                            sample_period)),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .result = REJECT,
+               .errstr = "same insn cannot be used with different pointers",
+               .prog_type = BPF_PROG_TYPE_PERF_EVENT,
+       },
        {
                "unpriv: write pointer into map elem value",
                .insns = {
@@ -1134,12 +1258,13 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
                        BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {3},
+               .fixup_map1 = { 3 },
                .errstr_unpriv = "R0 leaks addr",
                .result_unpriv = REJECT,
                .result = ACCEPT,
@@ -1160,11 +1285,12 @@ static struct bpf_test tests[] = {
                .insns = {
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_1),
                        BPF_LD_MAP_FD(BPF_REG_2, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_tail_call),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .prog_array_fixup = {1},
+               .fixup_prog = { 1 },
                .errstr_unpriv = "R3 leaks addr into helper",
                .result_unpriv = REJECT,
                .result = ACCEPT,
@@ -1178,7 +1304,7 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {1},
+               .fixup_map1 = { 1 },
                .errstr_unpriv = "R1 pointer comparison",
                .result_unpriv = REJECT,
                .result = ACCEPT,
@@ -1193,6 +1319,19 @@ static struct bpf_test tests[] = {
                .errstr = "frame pointer is read only",
                .result = REJECT,
        },
+       {
+               "unpriv: spill/fill frame pointer",
+               .insns = {
+                       BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, 0),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "frame pointer is read only",
+               .result = REJECT,
+       },
        {
                "unpriv: cmp of frame pointer",
                .insns = {
@@ -1254,7 +1393,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, -8),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1270,7 +1410,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, ~0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1286,7 +1427,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1302,7 +1444,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 8),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1318,7 +1461,8 @@ static struct bpf_test tests[] = {
                        BPF_ST_MEM(BPF_DW, BPF_REG_6, 0, 0xcafe),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 8),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1331,13 +1475,14 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_2, 4),
                        BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
-                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
-                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  8), /* spill ctx from R1 */
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  8),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 8),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6,  8), /* fill ctx into R2 */
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6,  8),
                        BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
                                    offsetof(struct __sk_buff, mark)),
                        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
@@ -1354,11 +1499,12 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_2, 4),
                        BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
-                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 8),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), /* fill ctx into R0 */
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
                                    offsetof(struct __sk_buff, mark)),
                        BPF_EXIT_INSN(),
@@ -1373,15 +1519,16 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_2, 4),
                        BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
-                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
-                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  0), /* spill ctx from R1 */
-                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  8), /* spill ctx from R1 */
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  0),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  8),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 8),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6,  8), /* fill ctx into R2 */
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6,  0), /* fill ctx into R3 */
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6,  8),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6,  0),
                        BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
                                    offsetof(struct __sk_buff, mark)),
                        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
@@ -1402,15 +1549,16 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_2, 4),
                        BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
-                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
-                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  0), /* spill ctx from R1 */
-                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  8), /* spill ctx from R1 */
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  0),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1,  8),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 8),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6,  8), /* fill ctx into R2 */
-                       BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6,  0), /* fill data into R3 */
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6,  8),
+                       BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6,  0),
                        BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
                                    offsetof(struct __sk_buff, mark)),
                        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
@@ -1430,7 +1578,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -513),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 8),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1446,7 +1595,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 8),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1462,7 +1612,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 0xffffffff),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1478,7 +1629,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1494,7 +1646,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1510,7 +1663,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1526,7 +1680,8 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
                        BPF_MOV64_IMM(BPF_REG_4, 512),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1747,11 +1902,12 @@ static struct bpf_test tests[] = {
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_update_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {5},
+               .fixup_map1 = { 5 },
                .result_unpriv = ACCEPT,
                .result = ACCEPT,
                .prog_type = BPF_PROG_TYPE_XDP,
@@ -1762,11 +1918,12 @@ static struct bpf_test tests[] = {
                        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                                    offsetof(struct xdp_md, data)),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {1},
+               .fixup_map1 = { 1 },
                .result = REJECT,
                .errstr = "invalid access to packet",
                .prog_type = BPF_PROG_TYPE_XDP,
@@ -1789,11 +1946,12 @@ static struct bpf_test tests[] = {
                        BPF_JMP_REG(BPF_JGT, BPF_REG_5, BPF_REG_3, 4),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_4),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {11},
+               .fixup_map1 = { 11 },
                .result = ACCEPT,
                .prog_type = BPF_PROG_TYPE_XDP,
        },
@@ -1810,11 +1968,12 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {7},
+               .fixup_map1 = { 7 },
                .result = REJECT,
                .errstr = "invalid access to packet",
                .prog_type = BPF_PROG_TYPE_XDP,
@@ -1831,11 +1990,12 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 7),
                        BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 3),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {6},
+               .fixup_map1 = { 6 },
                .result = REJECT,
                .errstr = "invalid access to packet",
                .prog_type = BPF_PROG_TYPE_XDP,
@@ -1853,11 +2013,12 @@ static struct bpf_test tests[] = {
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
                        BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_update_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {5},
+               .fixup_map1 = { 5 },
                .result = ACCEPT,
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
        },
@@ -1867,11 +2028,12 @@ static struct bpf_test tests[] = {
                        BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
                                    offsetof(struct __sk_buff, data)),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {1},
+               .fixup_map1 = { 1 },
                .result = REJECT,
                .errstr = "invalid access to packet",
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -1894,11 +2056,12 @@ static struct bpf_test tests[] = {
                        BPF_JMP_REG(BPF_JGT, BPF_REG_5, BPF_REG_3, 4),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_4),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {11},
+               .fixup_map1 = { 11 },
                .result = ACCEPT,
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
        },
@@ -1915,11 +2078,12 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {7},
+               .fixup_map1 = { 7 },
                .result = REJECT,
                .errstr = "invalid access to packet",
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -1936,11 +2100,12 @@ static struct bpf_test tests[] = {
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 7),
                        BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 3),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
-               .fixup = {6},
+               .fixup_map1 = { 6 },
                .result = REJECT,
                .errstr = "invalid access to packet",
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
@@ -1959,7 +2124,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_2, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 42),
                        BPF_MOV64_IMM(BPF_REG_5, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_store_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_store_bytes),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -1979,7 +2145,8 @@ static struct bpf_test tests[] = {
                        BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_7, 3),
                        BPF_MOV64_IMM(BPF_REG_2, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 4),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_skb_load_bytes),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -2003,7 +2170,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_3, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
                        BPF_MOV64_IMM(BPF_REG_5, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_diff),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -2026,7 +2194,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_3, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
                        BPF_MOV64_IMM(BPF_REG_5, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_diff),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -2050,7 +2219,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_3, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
                        BPF_MOV64_IMM(BPF_REG_5, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_diff),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -2074,7 +2244,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_3, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
                        BPF_MOV64_IMM(BPF_REG_5, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_diff),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -2098,7 +2269,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_3, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
                        BPF_MOV64_IMM(BPF_REG_5, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_diff),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -2122,7 +2294,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_3, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
                        BPF_MOV64_IMM(BPF_REG_5, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_diff),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -2146,7 +2319,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_3, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
                        BPF_MOV64_IMM(BPF_REG_5, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_diff),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -2169,7 +2343,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_IMM(BPF_REG_3, 0),
                        BPF_MOV64_IMM(BPF_REG_4, 0),
                        BPF_MOV64_IMM(BPF_REG_5, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_diff),
                        BPF_MOV64_IMM(BPF_REG_0, 0),
                        BPF_EXIT_INSN(),
                },
@@ -2184,12 +2359,14 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
-                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+                                  offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3},
+               .fixup_map2 = { 3 },
                .errstr_unpriv = "R0 leaks addr",
                .result_unpriv = REJECT,
                .result = ACCEPT,
@@ -2201,16 +2378,18 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
                        BPF_MOV64_IMM(BPF_REG_1, 4),
                        BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
                        BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
-                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+                                  offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3},
-               .errstr_unpriv = "R0 leaks addr",
+               .fixup_map2 = { 3 },
+               .errstr_unpriv = "R0 pointer arithmetic prohibited",
                .result_unpriv = REJECT,
                .result = ACCEPT,
        },
@@ -2221,17 +2400,19 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
                        BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
                        BPF_JMP_IMM(BPF_JGE, BPF_REG_1, MAX_ENTRIES, 3),
                        BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
                        BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
-                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+                                  offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3},
-               .errstr_unpriv = "R0 leaks addr",
+               .fixup_map2 = { 3 },
+               .errstr_unpriv = "R0 pointer arithmetic prohibited",
                .result_unpriv = REJECT,
                .result = ACCEPT,
        },
@@ -2242,7 +2423,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
                        BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
                        BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 0xffffffff, 1),
@@ -2252,11 +2434,12 @@ static struct bpf_test tests[] = {
                        BPF_MOV32_IMM(BPF_REG_1, 0),
                        BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
                        BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
-                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+                                  offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3},
-               .errstr_unpriv = "R0 leaks addr",
+               .fixup_map2 = { 3 },
+               .errstr_unpriv = "R0 pointer arithmetic prohibited",
                .result_unpriv = REJECT,
                .result = ACCEPT,
        },
@@ -2267,13 +2450,14 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
                        BPF_ST_MEM(BPF_DW, BPF_REG_0, (MAX_ENTRIES + 1) << 2,
                                   offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3},
+               .fixup_map2 = { 3 },
                .errstr = "invalid access to map value, value_size=48 off=48 size=8",
                .result = REJECT,
        },
@@ -2284,16 +2468,20 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
                        BPF_MOV64_IMM(BPF_REG_1, MAX_ENTRIES + 1),
                        BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
                        BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
-                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+                                  offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3},
+               .fixup_map2 = { 3 },
+               .errstr_unpriv = "R0 pointer arithmetic prohibited",
                .errstr = "R0 min value is outside of the array range",
+               .result_unpriv = REJECT,
                .result = REJECT,
        },
        {
@@ -2303,16 +2491,20 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
                        BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
                        BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
                        BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
-                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+                                  offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3},
+               .fixup_map2 = { 3 },
+               .errstr_unpriv = "R0 pointer arithmetic prohibited",
                .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
+               .result_unpriv = REJECT,
                .result = REJECT,
        },
        {
@@ -2322,7 +2514,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
                        BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
                        BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
@@ -2330,11 +2523,14 @@ static struct bpf_test tests[] = {
                        BPF_MOV32_IMM(BPF_REG_1, 0),
                        BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
                        BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
-                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+                                  offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3},
+               .fixup_map2 = { 3 },
+               .errstr_unpriv = "R0 pointer arithmetic prohibited",
                .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
+               .result_unpriv = REJECT,
                .result = REJECT,
        },
        {
@@ -2344,7 +2540,8 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
                        BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
                        BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES + 1),
@@ -2352,11 +2549,14 @@ static struct bpf_test tests[] = {
                        BPF_MOV32_IMM(BPF_REG_1, 0),
                        BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
                        BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
-                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_0, 0,
+                                  offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3},
+               .fixup_map2 = { 3 },
+               .errstr_unpriv = "R0 pointer arithmetic prohibited",
                .errstr = "invalid access to map value, value_size=48 off=44 size=8",
+               .result_unpriv = REJECT,
                .result = REJECT,
        },
        {
@@ -2366,164 +2566,271 @@ static struct bpf_test tests[] = {
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
                        BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
                        BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
                        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
                        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
                        BPF_LD_MAP_FD(BPF_REG_1, 0),
-                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
                        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
                        BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_8),
-                       BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, offsetof(struct test_val, foo)),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
+                                   offsetof(struct test_val, foo)),
                        BPF_EXIT_INSN(),
                },
-               .test_val_map_fixup = {3, 11},
+               .fixup_map2 = { 3, 11 },
+               .errstr_unpriv = "R0 pointer arithmetic prohibited",
                .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
+               .result_unpriv = REJECT,
+               .result = REJECT,
+       },
+       {
+               "multiple registers share map_lookup_elem result",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_1, 10),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 4 },
+               .result = ACCEPT,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS
+       },
+       {
+               "invalid memory access with multiple map_lookup_elem calls",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_1, 10),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
+                       BPF_MOV64_REG(BPF_REG_7, BPF_REG_2),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+                       BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 4 },
                .result = REJECT,
+               .errstr = "R4 !read_ok",
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS
+       },
+       {
+               "valid indirect map_lookup_elem access with 2nd lookup in branch",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_1, 10),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_MOV64_REG(BPF_REG_8, BPF_REG_1),
+                       BPF_MOV64_REG(BPF_REG_7, BPF_REG_2),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_MOV64_IMM(BPF_REG_2, 10),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0, 3),
+                       BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 4 },
+               .result = ACCEPT,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS
        },
 };
 
-static int probe_filter_length(struct bpf_insn *fp)
+static int probe_filter_length(const struct bpf_insn *fp)
 {
-       int len = 0;
+       int len;
 
        for (len = MAX_INSNS - 1; len > 0; --len)
                if (fp[len].code != 0 || fp[len].imm != 0)
                        break;
-
        return len + 1;
 }
 
-static int create_map(size_t val_size, int num)
+static int create_map(uint32_t size_value, uint32_t max_elem)
 {
-       int map_fd;
+       int fd;
 
-       map_fd = bpf_create_map(BPF_MAP_TYPE_HASH,
-                               sizeof(long long), val_size, num, 0);
-       if (map_fd < 0)
-               printf("failed to create map '%s'\n", strerror(errno));
+       fd = bpf_map_create(BPF_MAP_TYPE_HASH, sizeof(long long),
+                           size_value, max_elem, BPF_F_NO_PREALLOC);
+       if (fd < 0)
+               printf("Failed to create hash map '%s'!\n", strerror(errno));
 
-       return map_fd;
+       return fd;
 }
 
 static int create_prog_array(void)
 {
-       int map_fd;
+       int fd;
 
-       map_fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY,
-                               sizeof(int), sizeof(int), 4, 0);
-       if (map_fd < 0)
-               printf("failed to create prog_array '%s'\n", strerror(errno));
+       fd = bpf_map_create(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int),
+                           sizeof(int), 4, 0);
+       if (fd < 0)
+               printf("Failed to create prog array '%s'!\n", strerror(errno));
 
-       return map_fd;
+       return fd;
 }
 
-static int test(void)
+static char bpf_vlog[32768];
+
+static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog,
+                         int *fd_f1, int *fd_f2, int *fd_f3)
 {
-       int prog_fd, i, pass_cnt = 0, err_cnt = 0;
-       bool unpriv = geteuid() != 0;
+       int *fixup_map1 = test->fixup_map1;
+       int *fixup_map2 = test->fixup_map2;
+       int *fixup_prog = test->fixup_prog;
+
+       /* Allocating HTs with 1 elem is fine here, since we only test
+        * for verifier and not do a runtime lookup, so the only thing
+        * that really matters is value size in this case.
+        */
+       if (*fixup_map1) {
+               *fd_f1 = create_map(sizeof(long long), 1);
+               do {
+                       prog[*fixup_map1].imm = *fd_f1;
+                       fixup_map1++;
+               } while (*fixup_map1);
+       }
 
-       for (i = 0; i < ARRAY_SIZE(tests); i++) {
-               struct bpf_insn *prog = tests[i].insns;
-               int prog_type = tests[i].prog_type;
-               int prog_len = probe_filter_length(prog);
-               int *fixup = tests[i].fixup;
-               int *prog_array_fixup = tests[i].prog_array_fixup;
-               int *test_val_map_fixup = tests[i].test_val_map_fixup;
-               int expected_result;
-               const char *expected_errstr;
-               int map_fd = -1, prog_array_fd = -1, test_val_map_fd = -1;
+       if (*fixup_map2) {
+               *fd_f2 = create_map(sizeof(struct test_val), 1);
+               do {
+                       prog[*fixup_map2].imm = *fd_f2;
+                       fixup_map2++;
+               } while (*fixup_map2);
+       }
 
-               if (*fixup) {
-                       map_fd = create_map(sizeof(long long), 1024);
+       if (*fixup_prog) {
+               *fd_f3 = create_prog_array();
+               do {
+                       prog[*fixup_prog].imm = *fd_f3;
+                       fixup_prog++;
+               } while (*fixup_prog);
+       }
+}
 
-                       do {
-                               prog[*fixup].imm = map_fd;
-                               fixup++;
-                       } while (*fixup);
-               }
-               if (*prog_array_fixup) {
-                       prog_array_fd = create_prog_array();
+static void do_test_single(struct bpf_test *test, bool unpriv,
+                          int *passes, int *errors)
+{
+       struct bpf_insn *prog = test->insns;
+       int prog_len = probe_filter_length(prog);
+       int prog_type = test->prog_type;
+       int fd_f1 = -1, fd_f2 = -1, fd_f3 = -1;
+       int fd_prog, expected_ret;
+       const char *expected_err;
 
-                       do {
-                               prog[*prog_array_fixup].imm = prog_array_fd;
-                               prog_array_fixup++;
-                       } while (*prog_array_fixup);
-               }
-               if (*test_val_map_fixup) {
-                       /* Unprivileged can't create a hash map.*/
-                       if (unpriv)
-                               continue;
-                       test_val_map_fd = create_map(sizeof(struct test_val),
-                                                    256);
-                       do {
-                               prog[*test_val_map_fixup].imm = test_val_map_fd;
-                               test_val_map_fixup++;
-                       } while (*test_val_map_fixup);
-               }
+       do_test_fixup(test, prog, &fd_f1, &fd_f2, &fd_f3);
 
-               printf("#%d %s ", i, tests[i].descr);
+       fd_prog = bpf_prog_load(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
+                               prog, prog_len * sizeof(struct bpf_insn),
+                               "GPL", bpf_vlog, sizeof(bpf_vlog));
 
-               prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER,
-                                       prog, prog_len * sizeof(struct bpf_insn),
-                                       "GPL", 0);
+       expected_ret = unpriv && test->result_unpriv != UNDEF ?
+                      test->result_unpriv : test->result;
+       expected_err = unpriv && test->errstr_unpriv ?
+                      test->errstr_unpriv : test->errstr;
+       if (expected_ret == ACCEPT) {
+               if (fd_prog < 0) {
+                       printf("FAIL\nFailed to load prog '%s'!\n",
+                              strerror(errno));
+                       goto fail_log;
+               }
+       } else {
+               if (fd_prog >= 0) {
+                       printf("FAIL\nUnexpected success to load!\n");
+                       goto fail_log;
+               }
+               if (!strstr(bpf_vlog, expected_err)) {
+                       printf("FAIL\nUnexpected error message!\n");
+                       goto fail_log;
+               }
+       }
 
-               if (unpriv && tests[i].result_unpriv != UNDEF)
-                       expected_result = tests[i].result_unpriv;
-               else
-                       expected_result = tests[i].result;
+       (*passes)++;
+       printf("OK\n");
+close_fds:
+       close(fd_prog);
+       close(fd_f1);
+       close(fd_f2);
+       close(fd_f3);
+       sched_yield();
+       return;
+fail_log:
+       (*errors)++;
+       printf("%s", bpf_vlog);
+       goto close_fds;
+}
 
-               if (unpriv && tests[i].errstr_unpriv)
-                       expected_errstr = tests[i].errstr_unpriv;
-               else
-                       expected_errstr = tests[i].errstr;
+static int do_test(bool unpriv, unsigned int from, unsigned int to)
+{
+       int i, passes = 0, errors = 0;
 
-               if (expected_result == ACCEPT) {
-                       if (prog_fd < 0) {
-                               printf("FAIL\nfailed to load prog '%s'\n",
-                                      strerror(errno));
-                               printf("%s", bpf_log_buf);
-                               err_cnt++;
-                               goto fail;
-                       }
-               } else {
-                       if (prog_fd >= 0) {
-                               printf("FAIL\nunexpected success to load\n");
-                               printf("%s", bpf_log_buf);
-                               err_cnt++;
-                               goto fail;
-                       }
-                       if (strstr(bpf_log_buf, expected_errstr) == 0) {
-                               printf("FAIL\nunexpected error message: %s",
-                                      bpf_log_buf);
-                               err_cnt++;
-                               goto fail;
-                       }
-               }
+       for (i = from; i < to; i++) {
+               struct bpf_test *test = &tests[i];
 
-               pass_cnt++;
-               printf("OK\n");
-fail:
-               if (map_fd >= 0)
-                       close(map_fd);
-               if (prog_array_fd >= 0)
-                       close(prog_array_fd);
-               if (test_val_map_fd >= 0)
-                       close(test_val_map_fd);
-               close(prog_fd);
+               /* Program types that are not supported by non-root we
+                * skip right away.
+                */
+               if (unpriv && test->prog_type)
+                       continue;
 
+               printf("#%d %s ", i, test->descr);
+               do_test_single(test, unpriv, &passes, &errors);
        }
-       printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
 
-       return 0;
+       printf("Summary: %d PASSED, %d FAILED\n", passes, errors);
+       return errors ? -errors : 0;
 }
 
-int main(void)
+int main(int argc, char **argv)
 {
-       struct rlimit r = {1 << 20, 1 << 20};
+       struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
+       struct rlimit rlim = { 1 << 20, 1 << 20 };
+       unsigned int from = 0, to = ARRAY_SIZE(tests);
+       bool unpriv = geteuid() != 0;
+
+       if (argc == 3) {
+               unsigned int l = atoi(argv[argc - 2]);
+               unsigned int u = atoi(argv[argc - 1]);
+
+               if (l < to && u < to) {
+                       from = l;
+                       to   = u + 1;
+               }
+       } else if (argc == 2) {
+               unsigned int t = atoi(argv[argc - 1]);
+
+               if (t < to) {
+                       from = t;
+                       to   = t + 1;
+               }
+       }
 
-       setrlimit(RLIMIT_MEMLOCK, &r);
-       return test();
+       setrlimit(RLIMIT_MEMLOCK, unpriv ? &rlim : &rinf);
+       return do_test(unpriv, from, to);
 }
index 0840684deb7d474578050f9c230fe9196e46a486..afe109e5508ab4cf5947a319940f6a3ec15ff0b2 100644 (file)
@@ -3,4 +3,5 @@ psock_fanout
 psock_tpacket
 reuseport_bpf
 reuseport_bpf_cpu
+reuseport_bpf_numa
 reuseport_dualstack
index 0e5340742620bc332df4ad49737fac072738d338..e24e4c82542e076856c0b99463e9e8cbb1363211 100644 (file)
@@ -1,14 +1,17 @@
 # Makefile for net selftests
 
-CFLAGS = -Wall -O2 -g
-
+CFLAGS =  -Wall -Wl,--no-as-needed -O2 -g
 CFLAGS += -I../../../../usr/include/
 
-NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf reuseport_bpf_cpu reuseport_dualstack
+NET_PROGS =  socket
+NET_PROGS += psock_fanout psock_tpacket
+NET_PROGS += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
+NET_PROGS += reuseport_dualstack
 
 all: $(NET_PROGS)
+reuseport_bpf_numa: LDFLAGS += -lnuma
 %: %.c
-       $(CC) $(CFLAGS) -o $@ $^
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
 
 TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh
 TEST_FILES := $(NET_PROGS)
diff --git a/tools/testing/selftests/net/reuseport_bpf_numa.c b/tools/testing/selftests/net/reuseport_bpf_numa.c
new file mode 100644 (file)
index 0000000..6f20bc9
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Test functionality of BPF filters with SO_REUSEPORT. Same test as
+ * in reuseport_bpf_cpu, only as one socket per NUMA node.
+ */
+
+#define _GNU_SOURCE
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <error.h>
+#include <linux/filter.h>
+#include <linux/bpf.h>
+#include <linux/in.h>
+#include <linux/unistd.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <numa.h>
+
+static const int PORT = 8888;
+
+static void build_rcv_group(int *rcv_fd, size_t len, int family, int proto)
+{
+       struct sockaddr_storage addr;
+       struct sockaddr_in  *addr4;
+       struct sockaddr_in6 *addr6;
+       size_t i;
+       int opt;
+
+       switch (family) {
+       case AF_INET:
+               addr4 = (struct sockaddr_in *)&addr;
+               addr4->sin_family = AF_INET;
+               addr4->sin_addr.s_addr = htonl(INADDR_ANY);
+               addr4->sin_port = htons(PORT);
+               break;
+       case AF_INET6:
+               addr6 = (struct sockaddr_in6 *)&addr;
+               addr6->sin6_family = AF_INET6;
+               addr6->sin6_addr = in6addr_any;
+               addr6->sin6_port = htons(PORT);
+               break;
+       default:
+               error(1, 0, "Unsupported family %d", family);
+       }
+
+       for (i = 0; i < len; ++i) {
+               rcv_fd[i] = socket(family, proto, 0);
+               if (rcv_fd[i] < 0)
+                       error(1, errno, "failed to create receive socket");
+
+               opt = 1;
+               if (setsockopt(rcv_fd[i], SOL_SOCKET, SO_REUSEPORT, &opt,
+                              sizeof(opt)))
+                       error(1, errno, "failed to set SO_REUSEPORT");
+
+               if (bind(rcv_fd[i], (struct sockaddr *)&addr, sizeof(addr)))
+                       error(1, errno, "failed to bind receive socket");
+
+               if (proto == SOCK_STREAM && listen(rcv_fd[i], len * 10))
+                       error(1, errno, "failed to listen on receive port");
+       }
+}
+
+static void attach_bpf(int fd)
+{
+       static char bpf_log_buf[65536];
+       static const char bpf_license[] = "";
+
+       int bpf_fd;
+       const struct bpf_insn prog[] = {
+               /* R0 = bpf_get_numa_node_id() */
+               { BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_numa_node_id },
+               /* return R0 */
+               { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
+       };
+       union bpf_attr attr;
+
+       memset(&attr, 0, sizeof(attr));
+       attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
+       attr.insn_cnt = sizeof(prog) / sizeof(prog[0]);
+       attr.insns = (unsigned long) &prog;
+       attr.license = (unsigned long) &bpf_license;
+       attr.log_buf = (unsigned long) &bpf_log_buf;
+       attr.log_size = sizeof(bpf_log_buf);
+       attr.log_level = 1;
+
+       bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
+       if (bpf_fd < 0)
+               error(1, errno, "ebpf error. log:\n%s\n", bpf_log_buf);
+
+       if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
+                       sizeof(bpf_fd)))
+               error(1, errno, "failed to set SO_ATTACH_REUSEPORT_EBPF");
+
+       close(bpf_fd);
+}
+
+static void send_from_node(int node_id, int family, int proto)
+{
+       struct sockaddr_storage saddr, daddr;
+       struct sockaddr_in  *saddr4, *daddr4;
+       struct sockaddr_in6 *saddr6, *daddr6;
+       int fd;
+
+       switch (family) {
+       case AF_INET:
+               saddr4 = (struct sockaddr_in *)&saddr;
+               saddr4->sin_family = AF_INET;
+               saddr4->sin_addr.s_addr = htonl(INADDR_ANY);
+               saddr4->sin_port = 0;
+
+               daddr4 = (struct sockaddr_in *)&daddr;
+               daddr4->sin_family = AF_INET;
+               daddr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+               daddr4->sin_port = htons(PORT);
+               break;
+       case AF_INET6:
+               saddr6 = (struct sockaddr_in6 *)&saddr;
+               saddr6->sin6_family = AF_INET6;
+               saddr6->sin6_addr = in6addr_any;
+               saddr6->sin6_port = 0;
+
+               daddr6 = (struct sockaddr_in6 *)&daddr;
+               daddr6->sin6_family = AF_INET6;
+               daddr6->sin6_addr = in6addr_loopback;
+               daddr6->sin6_port = htons(PORT);
+               break;
+       default:
+               error(1, 0, "Unsupported family %d", family);
+       }
+
+       if (numa_run_on_node(node_id) < 0)
+               error(1, errno, "failed to pin to node");
+
+       fd = socket(family, proto, 0);
+       if (fd < 0)
+               error(1, errno, "failed to create send socket");
+
+       if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)))
+               error(1, errno, "failed to bind send socket");
+
+       if (connect(fd, (struct sockaddr *)&daddr, sizeof(daddr)))
+               error(1, errno, "failed to connect send socket");
+
+       if (send(fd, "a", 1, 0) < 0)
+               error(1, errno, "failed to send message");
+
+       close(fd);
+}
+
+static
+void receive_on_node(int *rcv_fd, int len, int epfd, int node_id, int proto)
+{
+       struct epoll_event ev;
+       int i, fd;
+       char buf[8];
+
+       i = epoll_wait(epfd, &ev, 1, -1);
+       if (i < 0)
+               error(1, errno, "epoll_wait failed");
+
+       if (proto == SOCK_STREAM) {
+               fd = accept(ev.data.fd, NULL, NULL);
+               if (fd < 0)
+                       error(1, errno, "failed to accept");
+               i = recv(fd, buf, sizeof(buf), 0);
+               close(fd);
+       } else {
+               i = recv(ev.data.fd, buf, sizeof(buf), 0);
+       }
+
+       if (i < 0)
+               error(1, errno, "failed to recv");
+
+       for (i = 0; i < len; ++i)
+               if (ev.data.fd == rcv_fd[i])
+                       break;
+       if (i == len)
+               error(1, 0, "failed to find socket");
+       fprintf(stderr, "send node %d, receive socket %d\n", node_id, i);
+       if (node_id != i)
+               error(1, 0, "node id/receive socket mismatch");
+}
+
+static void test(int *rcv_fd, int len, int family, int proto)
+{
+       struct epoll_event ev;
+       int epfd, node;
+
+       build_rcv_group(rcv_fd, len, family, proto);
+       attach_bpf(rcv_fd[0]);
+
+       epfd = epoll_create(1);
+       if (epfd < 0)
+               error(1, errno, "failed to create epoll");
+       for (node = 0; node < len; ++node) {
+               ev.events = EPOLLIN;
+               ev.data.fd = rcv_fd[node];
+               if (epoll_ctl(epfd, EPOLL_CTL_ADD, rcv_fd[node], &ev))
+                       error(1, errno, "failed to register sock epoll");
+       }
+
+       /* Forward iterate */
+       for (node = 0; node < len; ++node) {
+               send_from_node(node, family, proto);
+               receive_on_node(rcv_fd, len, epfd, node, proto);
+       }
+
+       /* Reverse iterate */
+       for (node = len - 1; node >= 0; --node) {
+               send_from_node(node, family, proto);
+               receive_on_node(rcv_fd, len, epfd, node, proto);
+       }
+
+       close(epfd);
+       for (node = 0; node < len; ++node)
+               close(rcv_fd[node]);
+}
+
+int main(void)
+{
+       int *rcv_fd, nodes;
+
+       if (numa_available() < 0)
+               error(1, errno, "no numa api support");
+
+       nodes = numa_max_node() + 1;
+
+       rcv_fd = calloc(nodes, sizeof(int));
+       if (!rcv_fd)
+               error(1, 0, "failed to allocate array");
+
+       fprintf(stderr, "---- IPv4 UDP ----\n");
+       test(rcv_fd, nodes, AF_INET, SOCK_DGRAM);
+
+       fprintf(stderr, "---- IPv6 UDP ----\n");
+       test(rcv_fd, nodes, AF_INET6, SOCK_DGRAM);
+
+       fprintf(stderr, "---- IPv4 TCP ----\n");
+       test(rcv_fd, nodes, AF_INET, SOCK_STREAM);
+
+       fprintf(stderr, "---- IPv6 TCP ----\n");
+       test(rcv_fd, nodes, AF_INET6, SOCK_STREAM);
+
+       free(rcv_fd);
+
+       fprintf(stderr, "SUCCESS\n");
+       return 0;
+}